"Unsupported state or unable to authenticate data" 在节点中使用 aes-128-gcm
"Unsupported state or unable to authenticate data" with aes-128-gcm in Node
我正在尝试使用节点加密提供的 aes-128-gcm 来实现 encrypt/decrypt 功能。根据我的理解,gcm 加密了密文,但也对其进行了哈希处理,并将其作为 'authentication tag' 提供。但是,我不断收到错误消息:"Unsupported state or unable to authenticate data".
我不确定这是否是我的代码中的错误 - 查看加密的密文和 auth 标签,解密函数获取的标签与加密函数生成的标签相同。
function encrypt(plaintext) {
// IV is being generated for each encryption
var iv = crypto.randomBytes(12),
cipher = crypto.createCipheriv(aes,key,iv),
encryptedData = cipher.update(plaintext),
tag;
// Cipher.final has been called, so no more encryption/updates can take place
encryptedData += cipher.final();
// Auth tag must be generated after cipher.final()
tag = cipher.getAuthTag();
return encryptedData + "$$" + tag.toString('hex') + "$$" + iv.toString('hex');
}
function decrypt(ciphertext) {
var cipherSplit = ciphertext.split("$$"),
text = cipherSplit[0],
tag = Buffer.from(cipherSplit[1], 'hex'),
iv = Buffer.from(cipherSplit[2], 'hex'),
decipher = crypto.createDecipheriv(aes,key,iv);
decipher.setAuthTag(tag);
var decryptedData = decipher.update(text);
decryptedData += decipher.final();
}
decipher.final() 引发错误。
我设法解决了这个问题:问题是我没有为 cipher.final() 指定编码类型并且我在字符串中返回它,所以它没有返回 Buffer 对象, decipher.final() 所期待的。
为了修复,我在 cipher.update 和 cipher.final 中将 'utf-8' 添加到 'hex' 编码参数,反之亦然。
以防有人仍然试图获得加密和解密过程的工作示例。
我留下了一些应该考虑的评论。
import * as crypto from 'crypto';
const textToEncode = 'some secret text'; // utf-8
const algo = 'aes-128-gcm';
// Key bytes length depends on algorithm being used:
// 'aes-128-gcm' = 16 bytes
// 'aes-192-gcm' = 24 bytes
// 'aes-256-gcm' = 32 bytes
const key = crypto.randomBytes(16);
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(algo, key, iv);
const encrypted = Buffer.concat([
cipher.update(Buffer.from(textToEncode, 'utf-8')),
cipher.final(),
]);
const authTag = cipher.getAuthTag();
console.info('Value encrypted', {
valueToEncrypt: textToEncode,
encryptedValue: encrypted.toString('hex'),
authTag: authTag.toString('hex'),
});
// It's important to use the same authTag and IV that were used during encoding
const decipher = crypto.createDecipheriv(algo, key, iv);
decipher.setAuthTag(authTag);
const decrypted = Buffer.concat([
decipher.update(encrypted),
decipher.final(),
]);
console.info('Value decrypted', {
valueToDecrypt: encrypted.toString('hex'),
decryptedValue: decrypted.toString('utf-8'),
});
我正在尝试使用节点加密提供的 aes-128-gcm 来实现 encrypt/decrypt 功能。根据我的理解,gcm 加密了密文,但也对其进行了哈希处理,并将其作为 'authentication tag' 提供。但是,我不断收到错误消息:"Unsupported state or unable to authenticate data".
我不确定这是否是我的代码中的错误 - 查看加密的密文和 auth 标签,解密函数获取的标签与加密函数生成的标签相同。
function encrypt(plaintext) {
// IV is being generated for each encryption
var iv = crypto.randomBytes(12),
cipher = crypto.createCipheriv(aes,key,iv),
encryptedData = cipher.update(plaintext),
tag;
// Cipher.final has been called, so no more encryption/updates can take place
encryptedData += cipher.final();
// Auth tag must be generated after cipher.final()
tag = cipher.getAuthTag();
return encryptedData + "$$" + tag.toString('hex') + "$$" + iv.toString('hex');
}
function decrypt(ciphertext) {
var cipherSplit = ciphertext.split("$$"),
text = cipherSplit[0],
tag = Buffer.from(cipherSplit[1], 'hex'),
iv = Buffer.from(cipherSplit[2], 'hex'),
decipher = crypto.createDecipheriv(aes,key,iv);
decipher.setAuthTag(tag);
var decryptedData = decipher.update(text);
decryptedData += decipher.final();
}
decipher.final() 引发错误。
我设法解决了这个问题:问题是我没有为 cipher.final() 指定编码类型并且我在字符串中返回它,所以它没有返回 Buffer 对象, decipher.final() 所期待的。
为了修复,我在 cipher.update 和 cipher.final 中将 'utf-8' 添加到 'hex' 编码参数,反之亦然。
以防有人仍然试图获得加密和解密过程的工作示例。
我留下了一些应该考虑的评论。
import * as crypto from 'crypto';
const textToEncode = 'some secret text'; // utf-8
const algo = 'aes-128-gcm';
// Key bytes length depends on algorithm being used:
// 'aes-128-gcm' = 16 bytes
// 'aes-192-gcm' = 24 bytes
// 'aes-256-gcm' = 32 bytes
const key = crypto.randomBytes(16);
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(algo, key, iv);
const encrypted = Buffer.concat([
cipher.update(Buffer.from(textToEncode, 'utf-8')),
cipher.final(),
]);
const authTag = cipher.getAuthTag();
console.info('Value encrypted', {
valueToEncrypt: textToEncode,
encryptedValue: encrypted.toString('hex'),
authTag: authTag.toString('hex'),
});
// It's important to use the same authTag and IV that were used during encoding
const decipher = crypto.createDecipheriv(algo, key, iv);
decipher.setAuthTag(authTag);
const decrypted = Buffer.concat([
decipher.update(encrypted),
decipher.final(),
]);
console.info('Value decrypted', {
valueToDecrypt: encrypted.toString('hex'),
decryptedValue: decrypted.toString('utf-8'),
});