在
链接的答案中,数据的结构描述如下:
引用:
加密数据以v10(即0x763130)的ASCII编码开头,后跟12个字节的nonce、实际密文和最后16个字节的身份验证标记。
即数据结构如下:
- 3个字节的前缀v10
- 12个字节的IV
- 密文
- 16个字节的身份验证标记
长度为:3 + 12 + 密文长度 + 16。此外,在GCM模式下不使用填充,因此密文的长度与明文相同。
此外,发布的代码使用了错误的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'),
iv,
cipher.update(cookie),
cipher.final(),
cipher.getAuthTag()
]);
return encryptedCookie;
}
function decryptCookie(encryptedCookie, key){
const prefix = encryptedCookie.slice(0, 3);
const iv = encryptedCookie.slice(3, 3 + 12);
const ciphertext = encryptedCookie.slice(3 + 12, encryptedCookie.length - 16);
const authTag = encryptedCookie.slice(encryptedCookie.length - 16);
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(authTag);
const decryptedCookie = Buffer.concat(
[
decipher.update(ciphertext),
decipher.final(),
]);
return decryptedCookie;
}
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);
const decryptedCookie = decryptCookie(encryptedCookie, key);
console.log(decryptedCookie.toString('utf8'));
对于长度为30字节的样本cookie,加密数据的长度为3 + 12 + 30 + 16 = 61字节。