CBC mode generally (including this case) needs padding, and your encryption uses padding where only the last byte specifies the length and the other bytes are random. node-forge evidently accepts this, but nodejs builtin crypto
uses OpenSSL (specifically the EVP_Decrypt*
API, as you can see in the error message) which by default implements PKCS5/7 padding where all bytes must contain the length.
OpenSSL, and crypto
, does have an option to not do any padding and unpadding at all, leaving you to do it yourself. You can use that option here as follows:
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());
CLICK HERE to find out more related problems solutions.