linked answer中的数据结构描述如下:
加密数据以 v10 的 ASCII 编码开头(即
0x763130),后跟 12 个字节的 nonce,实际密文和
最后是 16 字节的认证标签。
我。 e.数据结构如下:
- 3 字节前缀 v10
- 12 字节 IV
- 密文
- 16字节认证标签
长度为:3 + 12 + ciphertextlength + 16。另外,由于GCM模式没有使用padding,所以密文的长度与明文的长度相同。
除其他外,发布的代码使用了错误的 IV 长度,没有连接 IV,也没有考虑身份验证标签。
加密/解密的一种可能实现是:
var crypto = require('crypto');
function encryptCookie(cookie, key){
const iv = crypto.randomBytes(12);
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
const encryptedCookie = Buffer.concat(
[
Buffer.from('v10'), // prefix
iv, // 12 bytes nonce
cipher.update(cookie), // cookie data
cipher.final(),
cipher.getAuthTag() // 16 bytes authentication
]);
return encryptedCookie;
}
function decryptCookie(encryptedCookie, key){
const prefix = encryptedCookie.slice(0, 3); // prefix
const iv = encryptedCookie.slice(3, 3 + 12); // 12 bytes nonce
const ciphertext = encryptedCookie.slice(3 + 12, encryptedCookie.length - 16); // encrypted cookie
const authTag = encryptedCookie.slice(encryptedCookie.length - 16); // 12 bytes authentication tag
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(authTag);
const decryptedCookie = Buffer.concat(
[
decipher.update(ciphertext), // encrypted cookie
decipher.final(),
]);
return decryptedCookie;
}
// Encryption
const cookie = Buffer.from('The test cookie with some data');
const key = Buffer.from('01234567890123456789012345678901');
const encryptedCookie = encryptCookie(cookie, key);
console.log(encryptedCookie);
console.log(encryptedCookie.length);
// Decryption
const decryptedCookie = decryptCookie(encryptedCookie, key);
console.log(decryptedCookie.toString('utf8'));
对于长度为 30 字节的示例 cookie,加密数据的长度为 3 + 12 + 30 + 16 = 61 字节。