【发布时间】:2021-09-24 00:19:19
【问题描述】:
我提到了https://stackoverflow.com/a/65072352/4910936 中提到的 nodejs 加密,我可以加密并在解密时收到错误“错误:不支持的状态或无法验证数据”
var crypto = require('crypto');
console.log('AES GCMC 256 String encryption with PBKDF2 derived key');
var plaintext = 'The quick brown fox jumps over the lazy dog';
console.log('plaintext: ', plaintext);
const cryptoConfig = {
cipherAlgorithm: 'aes-256-gcm',
masterKey: 'somekey',
iterations: 65535,
keyLength: 32,
saltLength: 16,
ivLength: 12,
tagLength: 16,
digest: 'sha512'
}
var ciphertext = encrypt(plaintext);
console.log('ciphertext: ', ciphertext);
decrypt(ciphertext)
function encrypt(content) {
const salt = crypto.randomBytes(cryptoConfig.saltLength);
console.log("salt : ", salt)
const iv = crypto.randomBytes(cryptoConfig.ivLength);
console.log("iv : ", iv)
const key = crypto.pbkdf2Sync(cryptoConfig.masterKey, salt, cryptoConfig.iterations,
cryptoConfig.keyLength, cryptoConfig.digest);
const cipher = crypto.createCipheriv(cryptoConfig.cipherAlgorithm, key, iv);
const encrypted = Buffer.concat([cipher.update(content, 'utf8'), cipher.final()]);
const tag = cipher.getAuthTag();
console.log("tag : ", tag)
// ### put the auth tag at the end of encrypted
//const encdata = Buffer.concat([salt, iv, tag, encrypted]).toString('base64');
const encdata = Buffer.concat([salt, iv, encrypted, tag]).toString('base64');
return encdata;
}
function decrypt(encdata){
///decrypt
// base64 decoding
const bData = Buffer.from(encdata, 'base64');
// convert data to buffers
const salt1 = bData.slice(0, 16);
const iv1 = bData.slice(16, 32);
const tag1 = bData.slice(32, 48);
const text1 = bData.slice(48);
// derive key using; 32 byte key length
// const key = crypto.pbkdf2Sync(cryptoConfig.masterkey, salt , 2145, 32, 'sha512');
const key1 = crypto.pbkdf2Sync(cryptoConfig.masterKey, salt1, cryptoConfig.iterations,
cryptoConfig.keyLength, cryptoConfig.digest)
// AES 256 GCM Mode
const decipher = crypto.createDecipheriv('aes-256-gcm', key1, iv1);
decipher.setAuthTag(tag1);
// encrypt the given text
const decrypted = decipher.update(text1, 'binary', 'utf8') + decipher.final('utf8');
console.log(decrypted)
}
从错误看来,我在从加密数据中分离 IV、salt 时搞砸了,因此与加密时使用的不匹配。
【问题讨论】:
-
你做
Buffer.concat([salt, iv, encrypted, tag]),其中 iv(又名 nonce)是 12 个字节,但(在 de-base64 之后)你拆分为 salt、iv、tag,用 iv 加密为 16,最后两个交换。为什么不使用与加密时相同的config.字段进行解密? -
@dave_thompson_085 跨平台共享相同的加密和解密。在Nodejs中加密,在java中解密,反之亦然,所以不能使用config。感谢您发现加密和标签已交换。我在加密版本中修复了它,并按照下面的 Micahel 回答并工作。
-
您的代码可以通过
const iv1 = bData.slice(16, 28); const text1 = bData.slice(28, bData.length - 16); const tag1 = bData.slice(bData.length - 16);轻松修复> -
@user9014097 是的,我看到现在使用多个 Base64 编码并删除了分隔符并使用了您的建议。谢谢
标签: node.js encryption aes-gcm