GCM
使用由NodeJS/Crypto单独处理的身份验证标记,而WebCrypto会自动将其与密文连接起来。
因此,在NodeJS代码中,必须明确确定标记并将其附加到密文中。这在当前的NodeJS代码中缺失,可以考虑如下。注意标签的确定
cipher.getAuthTag()
以及它的连接:
var crypto = require('crypto');
function encrypt(key, plaintext) {
var nonce = getRandomIV();
var cipher = crypto.createCipheriv('aes-256-gcm', key, nonce);
var nonceCiphertextTag = Buffer.concat([
nonce,
cipher.update(plaintext),
cipher.final(),
cipher.getAuthTag() // Fix: Get tag with cipher.getAuthTag() and concatenate: nonce|ciphertext|tag
]);
return nonceCiphertextTag.toString('base64');
}
function getRandomIV() {
return crypto.randomBytes(12);
}
var message = Buffer.from('The quick brown fox jumps over the lazy dog', 'utf8');
var sharedKey = Buffer.from('MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDE=', 'base64');
var ciphertext = encrypt(sharedKey, message);
console.log(ciphertext); // wRE5KM6FG81QSMNvG0xR+iaIeF77cyyeBceGS5NkcYaD17K9nL0/helnqRBOkD9pLVoWM/nRAcaKg/YdvfNJcO1Zn/7ZM0k=
一个可能的输出是
wRE5KM6FG81QSMNvG0xR+iaIeF77cyyeBceGS5NkcYaD17K9nL0/helnqRBOkD9pLVoWM/nRAcaKg/YdvfNJcO1Zn/7ZM0k=
以下WebCrypto端的解密代码基本上基于您的代码(没有从共享密钥派生密钥,这与当前问题无关):
(async () => {
var nonceCiphertextTag = base64ToArrayBuffer('wRE5KM6FG81QSMNvG0xR+iaIeF77cyyeBceGS5NkcYaD17K9nL0/helnqRBOkD9pLVoWM/nRAcaKg/YdvfNJcO1Zn/7ZM0k=');
var nonceCiphertextTag = new Uint8Array(nonceCiphertextTag);
var decrypted = await decrypt(nonceCiphertextTag);
console.log(decrypted); // The quick brown fox jumps over the lazy dog
})();
async function decrypt(nonceCiphertextTag) {
const SERVER_ENCRYPTION_IV_LENGTH = 12; // For GCM a nonce length of 12 bytes is recommended!
var nonce = nonceCiphertextTag.subarray(0, SERVER_ENCRYPTION_IV_LENGTH);
var ciphertextTag = nonceCiphertextTag.subarray(SERVER_ENCRYPTION_IV_LENGTH);
var aesKey = base64ToArrayBuffer('MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDE=');
aesKey = await window.crypto.subtle.importKey('raw', aesKey, 'AES-GCM', true, ['encrypt', 'decrypt']);
var decrypted = await crypto.subtle.decrypt({name: 'AES-GCM', iv: nonce}, aesKey, ciphertextTag);
return new TextDecoder().decode(decrypted);
}
// Helper
// https://stackoverflow.com/a/21797381/9014097
function base64ToArrayBuffer(base64) {
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes.buffer;
}
成功解密NodeJS端的密文:
The quick brown fox jumps over the lazy dog