const crypto = require('crypto');
const mode = 'aes-256-gcm';
// 因為aes-256要求之key 長度為256bits 也就是32 bytes = 32個ASCII英文字母
// aes-128 要求之key 長度為128bits 也就是16 bytes = 16個英文字母
let key = Buffer.from("abcbbbbbbbbbbbbbabcbbbbbbbbbbbbb", 'utf-8') //or crypto.randomBytes(32);
const IV_LENGTH = 12;
let tag;
function encrypt(text) {
let iv = crypto.randomBytes(IV_LENGTH);
let cipher = crypto.createCipheriv(mode, new Buffer(key), iv);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
// 需要加上AuthTag
tag = cipher.getAuthTag();
// 將IV附上 在解密時須告知
return iv.toString('hex') + ':' + encrypted.toString('hex');
}
function decrypt(text) {
let textParts = text.split(':');
let iv = new Buffer(textParts.shift(), 'hex');
let encryptedText = new Buffer(textParts.join(':'), 'hex');
let decipher = crypto.createDecipheriv(mode, new Buffer(key), iv);
// 需要加上AuthTag
decipher.setAuthTag(tag);
let decrypted = decipher.update(encryptedText, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted.toString();
}
console.log(encrypt("test"));
console.log(decrypt(encrypt("test")))
IV 與 AuthTag
IV and the auth tag can be sent in plain.
The auth tag is a tag the recipient can use to verify that the message has not been altered. This is important because AES-GCM acts as a stream cipher and anyone could flip bits.
The IV is not a secret, the only thing to be concerned about is that it must not be reused with the same key.