我想使用node.js的一部分解密来解密某些内容,但收到错误消息。如果我对相同的输入数据使用伪造,则可以解密数据。在nodeDecrypt函数中我怎么了?
const crypto = require('crypto');
const keyHash = "b6db3d66f4f8bd82aea61576e221f23634bb7c585340a8a42140701f5a468e04"
const encryptedB64 = "cHIaTs0vA6phV8jyT3X78cTSrUnLeBwbAqstVBAl7kl4uV+4oGQFVgsChW8lfw4QOyECkZAay7c0rDi816T9ZA==";
const encryptedBuffer = Buffer.from(encryptedB64, 'base64');
var userKey = Buffer.from(keyHash, 'hex');
const forge = require('node-forge');
function nodeDecrypt(encrypted, key) {
const iv = encrypted.slice(0, 16);
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
encrypted = encrypted.slice(16);
var decrypted = decipher.update(encrypted);
console.log(decrypted.toString());
try {
decrypted += decipher.final();
} catch (e) {
console.log(e);
}
return decrypted;
}
function forgeDecrypt(encrypted, key) {
const encoding = 'latin1';
key = key.toString(encoding);
initVal = encrypted.toString(encoding).substring(0, 16);
encrypted = encrypted.toString(encoding).substring(16);
var decipher = forge.cipher.createDecipher('AES-CBC', key);
decipher.start({ iv: initVal });
decipher.update(forge.util.createBuffer(encrypted));
var result = decipher.finish();
return decipher.output.getBytes();
}
var decrypted;
decrypted = nodeDecrypt(encryptedBuffer, userKey);
console.log(decrypted.toString());
decrypted = forgeDecrypt(encryptedBuffer, userKey);
console.log(decrypted.toString());
输出
1a24989e-75d1-4631-8210-b17bb5e6
decryptor.js:26
Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
at Decipheriv.final (<node_internals>/internal/crypto/cipher.js:174:29)
...
at internal/main/run_main_module.js:17:47 {library: 'digital envelope routines', function: 'EVP_DecryptFinal_ex', reason: 'bad decrypt', code: 'ERR_OSSL_EVP_BAD_
1a24989e-75d1-4631-8210-b17bb5e6
1a24989e-75d1-4631-8210-b17bb5e6a2a1
这是与nodes.js 14.15.0版本一起使用的
答案 0 :(得分:1)
CBC模式通常(包括这种情况)需要填充,而加密使用填充,其中只有最后一个字节指定长度,而其他字节是随机的。 node-forge显然接受了这一点,但是内置crypto
的nodejs使用OpenSSL(特别是EVP_Decrypt*
API,您可以在错误消息中看到)由by default实现的PKCS5/7 padding,其中< em>所有字节必须包含长度。
OpenSSL和crypto
确实可以选择根本不执行任何填充和取消填充操作,而您可以自己完成。您可以在此处使用该选项,如下所示:
const crypto = require('crypto');
const keyHash = "b6db3d66f4f8bd82aea61576e221f23634bb7c585340a8a42140701f5a468e04"
const encryptedB64 = "cHIaTs0vA6phV8jyT3X78cTSrUnLeBwbAqstVBAl7kl4uV+4oGQFVgsChW8lfw4QOyECkZAay7c0rDi816T9ZA==";
const encryptedBuffer = Buffer.from(encryptedB64, 'base64');
var userKey = Buffer.from(keyHash, 'hex');
const forge = require('node-forge');
function nodeDecrypt(encrypted, key) {
const iv = encrypted.slice(0, 16);
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
decipher.setAutoPadding(false);
encrypted = encrypted.slice(16);
var decrypted = Buffer.concat([decipher.update(encrypted),decipher.final()]);
var padlen = decrypted[decrypted.length-1];
return decrypted.slice(0,decrypted.length-padlen);
}
function forgeDecrypt(encrypted, key) {
const encoding = 'latin1';
key = key.toString(encoding);
initVal = encrypted.toString(encoding).substring(0, 16);
encrypted = encrypted.toString(encoding).substring(16);
var decipher = forge.cipher.createDecipher('AES-CBC', key);
decipher.start({ iv: initVal });
decipher.update(forge.util.createBuffer(encrypted));
var result = decipher.finish();
return decipher.output.getBytes();
}
var decrypted;
decrypted = nodeDecrypt(encryptedBuffer, userKey);
console.log(decrypted.toString());
decrypted = forgeDecrypt(encryptedBuffer, userKey);
console.log(decrypted.toString());