I'm trying (and failing) to decipher in Delphi usung LockBox 3 a message that was encrypted using Node.js' crypto library.
node.js code:
var crypto = require('crypto');
var cipher = crypto.createCipher('aes-256-ctr', 'my password');
var crypted = cipher.update('hello world', 'utf8', 'base64');
crypted += cipher.final(output_encoding);
console.log(crypted);
The result from that is
oyC1KRVx3JZBLlI=
Delphi code:
var
Codec: TCodec;
CipherText: AnsiString;
begin
Codec := TCodec.Create(nil);
try
Codec.CryptoLibrary := TCryptographicLibrary.Create(Codec);
//
Codec.StreamCipherId = 'native.StreamToBlock';
Codec.BlockCipherId = 'native.AES-256';
Codec.ChainModeId = 'native.CTR';
//
Codec.Password := 'my password';
Codec.DecryptAnsiString(CipherText, 'oyC1KRVx3JZBLlI=');
//
Result := string(CipherText);
finally
Codec.Free;
end;
end;
What am I missing?
What is the problem?
The problem is that both libraries use different keys and initialization vectors (IVs) internally.
Remember that AES cipher does not work with passwords, but keys and IVs.
When you provide a password to the cryptographic library it uses some internal mechanism to automatically derive a key and IV.
This mechanism is not obvious, but is usually described in documentation of cryptographic libraries.
Documentation of
crypto
module innode.js
says it is using theEVP_BytesToKey
function of OpenSSL to derive the key and IV:Quote from Node.js v5.6.0 Documentation.
How to solve the problem?
The proper solution is to use a cryptographically secure hash algorithm to derive key from the password, and then manually provide the keys and IVs to the cryptographic library, whichever it is.
A quick and dirty (and highly insecure) solution is to find a Delphi routine that is equivalent to
EVP_BytesToKey
and just use that to make it work.Remember to also check that you are using the same padding scheme.
TCodec
should allow you to choosePaddingScheme
ofpadPKCS
, which should be compatible with the one used by the crypto module innode.js
. If it does not work try other options too.Another option is to use OpenSSL in Delphi, which should already be compatible with what is used in
node.js
.Also, see this question with similar problem to yours: