如何解决nodejs AES/GCM/NoPadding 加密
我提到了 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,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,2145,32,'sha512');
const key1 = crypto.pbkdf2Sync(cryptoConfig.masterKey,salt1,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 时搞砸了,因此与加密时使用的内容不匹配。
解决方法
这是我为我的跨平台加密博客编写的示例程序 - 这应该可以帮助您分离和传送 salt、iv 和 gcm 标签。
可以在此处找到实时运行版本:https://replit.com/@javacrypto/CpcNodeJsCryptoAesGcm256Pbkdf2StringEncryption#index.js/
var crypto = require('crypto');
console.log('AES GCM 256 String encryption with PBKDF2 derived key');
var plaintext = 'The quick brown fox jumps over the lazy dog';
console.log('plaintext: ',plaintext);
var password = "secret password";
console.log('\n* * * Encryption * * *');
var ciphertextBase64 = aesGcmPbkdf2EncryptToBase64(password,plaintext);
console.log('ciphertext (Base64): ' + ciphertextBase64);
console.log('output is (Base64) salt : (Base64) nonce : (Base64) ciphertext : (Base64) gcmTag');
console.log('\n* * * Decryption * * *');
var ciphertextDecryptionBase64 = ciphertextBase64;
console.log('ciphertext (Base64): ',ciphertextDecryptionBase64);
console.log('input is (Base64) salt : (Base64) nonce : (Base64) ciphertext : (Base64) gcmTag');
var decryptedtext = aesGcmPbkdf2DecryptFromBase64(password,ciphertextBase64);
console.log('plaintext: ',decryptedtext);
function aesGcmPbkdf2EncryptToBase64(password,data) {
var PBKDF2_ITERATIONS = 15000;
var salt = generateSalt32Byte();
var key = crypto.pbkdf2Sync(password,salt,PBKDF2_ITERATIONS,32,'sha256');
var nonce = generateRandomNonce();
const cipher = crypto.createCipheriv('aes-256-gcm',key,nonce);
let encryptedBase64 = '';
cipher.setEncoding('base64');
cipher.on('data',(chunk) => encryptedBase64 += chunk);
cipher.on('end',() => {
// do nothing console.log(encryptedBase64);
// Prints: some clear text data
});
cipher.write(data);
cipher.end();
var saltBase64 = base64Encoding(salt);
var nonceBase64 = base64Encoding(nonce);
var gcmTagBase64 = base64Encoding(cipher.getAuthTag());
return saltBase64 + ':' + nonceBase64 + ':' + encryptedBase64 + ':' + gcmTagBase64;
}
function aesGcmPbkdf2DecryptFromBase64(password,data) {
var PBKDF2_ITERATIONS = 15000;
var dataSplit = data.split(":");
var salt = base64Decoding(dataSplit[0]);
var gcmTag = base64Decoding(dataSplit[3]);
var key = crypto.pbkdf2Sync(password,'sha256');
var nonce = base64Decoding(dataSplit[1]);
var ciphertext = dataSplit[2];
const decipher = crypto.createDecipheriv('aes-256-gcm',nonce);
decipher.setAuthTag(gcmTag);
let decrypted = '';
decipher.on('readable',() => {
while (null !== (chunk = decipher.read())) {
decrypted += chunk.toString('utf8');
}
});
decipher.on('end',() => {
// do nothing console.log(decrypted);
});
decipher.write(ciphertext,'base64');
decipher.end();
return decrypted;
}
function generateSalt32Byte() {
return crypto.randomBytes(32);
}
function generateRandomNonce() {
return crypto.randomBytes(12);
}
function base64Encoding(input) {
return input.toString('base64');
}
function base64Decoding(input) {
return Buffer.from(input,'base64')
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。