概要
下記githubのソースをもとにVue.js用にプラグイン化しました。
https://gist.github.com/Agoreddah/511864e2c00da064586523b3087c30e2
ソース
// load dependencies
const crypto = require('crypto');
'use strict';
const APP_KEY = 暗号化キー;
const SETTINGS = {
key : Buffer.from(APP_KEY.substring(7), 'base64'),
sha : 'sha256',
mode : 'AES-256-CBC'
}
const Crypto = {
install(Vue) {
Vue.prototype.crypto = {
/**
* Caclulate MAC.
* Paylod needs to be decoded to JSON with getJsonPayload(payload)
* @param {Object} payload with iv & value
* @param {String} key
*/
calculateMac(payload, key){
let hashedData = this.hash(payload['iv'], payload['value'])
return this.hashHmac(hashedData, key);
},
/**
* Decrypts payload with master key
* @param {String} Payload - base64 encoded json with iv, value, mac information
*/
decrypt(payload){
if(payload !== ''){
try {
let _payload = this.getJsonPayload(payload);
let _iv = Buffer.from(_payload['iv'], 'base64');
let decipher = crypto.createDecipheriv(SETTINGS.mode, SETTINGS.key, _iv);
let decrypted = decipher.update(_payload['value'], 'base64', 'utf8');
decrypted += decipher.final('utf8');
return this.hashDeserialize(decrypted);
}catch (e) {
return payload;
}
}else{
return '';
}
},
/**
* Create payload encrypted with master key.
* Payload contains: iv, value, mac
* @param {String} data to be encrypted
* @return {String} Base64 encdoded payload
*/
encrypt(data){
let serializedValue = this.hashSerialize(data);
try{
let _iv = crypto.randomBytes(16);
let base64_iv = _iv.toString('base64');
let cipher = crypto.createCipheriv(SETTINGS.mode, SETTINGS.key, _iv);
let encrypted = cipher.update(serializedValue, 'utf8', 'base64');
encrypted += cipher.final('base64');
let _mac = this.hash(base64_iv, encrypted);
let payloadObject = {
'iv' : base64_iv,
'value' : encrypted,
'mac' : _mac
}
let _payload = JSON.stringify(payloadObject);
return Buffer.from(_payload).toString('base64');
}
catch(e){
throw new Error('Cannot encrypt data provided !');
}
},
/**
* Get JSON object from payload.
* Payload needs to be base64 encoded and must contains iv, value, mac attributes.
* MAC is validated
* @param {String} payload
* @return {Object} Data with iv, value, mac
*/
getJsonPayload(payload){
if(payload === undefined || payload === ''){
throw new Error('Payload MUST NOT be empty !');
}
if(typeof payload !== 'string'){
throw new Error('Payload MUST be string !');
}
try{
this._payload = JSON.parse(Buffer.from(payload, 'base64'));
}
catch(e){
throw new Error('Payload cannot be parsed !');
}
if(!this.isValidPayload(this._payload)){
throw new Error('Payload is not valid !');
}
if(!this.isValidMac(this._payload)){
throw new Error('Mac is not valid !!');
}
return this._payload;
},
/**
* Hash function.
* Combines initialization vector (iv) with data to be hashed (value).
* Uses master key to hash results
* @param {String} iv Initialization vector
* @param {String} value Data
*/
hash(iv, value){
if(iv === undefined || iv === ''){
throw new Error('Iv is not defined !');
}
if(value === undefined || value === ''){
throw new Error('Value is not defined !');
}
let data = String(iv) + String(value);
return this.hashHmac(data, SETTINGS.key);
},
/**
* Crypto function to hash data with given key
* @param {String} data
* @param {String} key
*/
hashHmac(data, key){
let hmac = crypto.createHmac(SETTINGS.sha, key);
hmac.update(data);
return hmac.digest('hex');
},
/**
* MAC validation function.
* Payload must be decoded to JSON
* @param {Object} payload
*/
isValidMac(payload){
let bytes = crypto.randomBytes(16),
calculatedMac = this.calculateMac(payload, bytes);
let originalMac = this.hashHmac(payload['mac'], bytes);
return originalMac === calculatedMac;
},
/**
* Payload validation function.
* Payload must be decoded to JSON
* @param {Object} payload
*/
isValidPayload(payload){
return (
Object.prototype.hasOwnProperty.call(payload, "iv") &&
Object.prototype.hasOwnProperty.call(payload, "value") &&
Object.prototype.hasOwnProperty.call(payload, "mac")
);
},
hashDeserialize(data) {
let str = String(data)
return str.substring(str.indexOf(':', 2) + 2, str.lastIndexOf(';') - 1)
},
hashSerialize(data){
if(typeof data !== 'string'){
throw new Error('Data to be serialized must be type of string !');
}
let str = String(data);
return 's:'+str.length+':"'+str+'";';
}
}
}
}
export default Crypto;
const APP_KEY = 暗号化キー;
暗号化キーは直接書いても良いですし、.envファイルに設定しても良いと思います。
Vue.jsのプラグイン登録
import Crypto from './plugins/encrypter';
Vue.use(Crypto);
暗号化
this.crypto.encrypt('暗号化したい文字列');
復号化
this.crypto.decrypt('this.crypto.encryptで暗号化された文字列');