I have some encrypted data in my database
I did it few years ago using crypto.createCipher
const cipher = crypto.createCipher('aes192', password);
As createCipher
and createDecipher
is deprecated, I would like to change to createCipheriv
and createDecipheriv
. The problem is that the data I have in my database are encoded without iv.
Is it possible to decode with createDecipheriv
data encoded with createDecipher
and to generate the same secret with createCipher
and createCipheriv
.
I tried setting the iv to null
but not working
Thanks, because the database migration is an heavy work !
I tried setting the iv to null but not working
This is because this method didn’t allow for passing an initialization vector (IV), and instead derived the IV from the key using the OpenSSL EVP_BytesToKey
derivation function, using a null
salt meaning that the IV would be deterministic for a given key which is an issue for ciphers with counter mode like CTR, GCM and CCM.
Looking at your code:
const cipher = crypto.createCipher('aes192', password);
If you want to make this code backwards compatible, you need to call OpenSSL’s EVP_BytesToKey
function yourself, typically through evp_bytestokey module which makes it available in JS userland.
Is it possible to decode with
createDecipheriv
data encoded withcreateDecipher
and to generate the same secret withcreateCipher
andcreateCipheriv
.
Yes, you can. check out my example code here:
const crypto = require('crypto');
const EVP_BytesToKey = require('evp_bytestokey')
const ALGO = 'aes192';
const password = 'Your_Password_Here';
const KEY_SIZE = 24;
function decrypt_legacy_using_IV(text) {
const result = EVP_BytesToKey(
password,
null,
KEY_SIZE * 8, // byte to bit size
16
)
let decipher = crypto.createDecipheriv(ALGO, result.key, result.iv);
let decrypted = decipher.update(text, 'hex','utf8') + decipher.final('utf8');
return decrypted.toString();
}
function encrypt_legacy_using_IV(text) {
const result = EVP_BytesToKey(
password,
null,
KEY_SIZE * 8, // byte to bit size
16
)
var cipher = crypto.createCipheriv(ALGO, result.key, result.iv);
var encrypted = cipher.update(text, 'utf8', 'hex') + cipher.final('hex');
return encrypted.toString();
}
For complete running example, clone node-snippets and run node apogee-legacy-crypto-cipheriv.js
.
However the reason this function is deprecated in the first place is because you shouldn’t use it, and instead use a random unpredictable IV, which requires you to change your code to something like this:
const iv = crypto.randomBytes(16)
const cipher = crypto.createCipheriv('aes192', password, iv)
Here, for AES-192 in CBC mode (aes192
being aliased to AES-192-CBC
by OpenSSL), the IV size is expected to be the same as the block size, which is always 16 bytes.
In order to decrypt the message, you will need the IV as well. Typically you’d store the IV together with the message, as the important part is for the IV to not be predictable ahead of time.