I have a receiving application that expects a string from a PHP producer that looks like this:
<?php
$shared_secret = 'secret';
$data = 'whatever';
# Newline added for viewing convenience only
echo bin2hex(mcrypt_encrypt(MCRYPT_BLOWFISH, $shared_secret, $data,
MCRYPT_MODE_ECB)) . "\n";
# -> 05c3febb9970204a
?>
The receiver is expensive to change.
I am building another producer using node.js and I can't get my JavaScript code to produce the same output:
var data, encrypt, sharedSecret;
sharedSecret = 'secret';
data = 'whatever';
encrypt = function(d) {
var cipher, crypto;
crypto = require('crypto');
cipher = crypto.createCipher('bf-ecb', sharedSecret, '\0\0\0\0\0\0\0\0');
cipher.update(d);
return cipher.final('hex');
};
console.log(encrypt(data));
// -> 35c9801f2afca332
I chose the 'bf-ecb' cipher, because I think that's blowfish in ECB mode. I provided 8 null bytes as the IV, because the PHP documentation for mcrypt_encrypt says that if you omit the IV, it uses all null bytes, and mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB) answers 8. I chose 'hex' because I think it provides the same representation as PHP'2 bin2hex().
What should I do to my JavaScript code to match the output of the PHP code?
There were only four problems with my code:
mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB) which reports 8 instead of saying "you are a fool".crypto.createCipheriv(), which uses the key as given. crypto.createCipher() uses a derivation of the given key (md5, I think).update() must not be thrown away.So the working solution is:
var data, encrypt, sharedSecret;
sharedSecret = 'secret';
data = 'whatever';
encrypt = function(d) {
var cipher, crypto;
crypto = require('crypto');
cipher = crypto.createCipheriv('bf-ecb', sharedSecret, '');
return cipher.update(d, 'utf8', 'hex') + cipher.final('hex');
};
console.log(encrypt(data));