I am hoping someone can shed some light on a problem that has been vexing me for the last few hours.
I am trying to decode a string that has been encoded in Ruby thus:
#!/usr/bin/env ruby
require 'base64'
require 'openssl'
require 'openssl/cipher'
require 'openssl/digest'
aes = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
aes.encrypt
aes.key = Digest::SHA256.digest('IHazSekretKey')
p Base64.encode64( aes.update('text to be encrypted') << aes.final )
Executing the above spits out: "3P86KyOrN2QJ/HFxxo3b7kAsxTgpDMMjROUPclsuXj0=\n"
I now try to decrypt this string in NodeJS 0.6.17
#!/usr/bin/env node
var crypto = require('crypto');
function decrypto(toDecryptStr) {
var result,
encoded = new Buffer(toDecryptStr, 'base64'),
decodeKey = crypto.createHash('sha256').update('IHazSekretKey', 'ascii').digest(),
decipher = crypto.createDecipher('aes-256-cbc', decodeKey);
result = decipher.update(encoded);
result += decipher.final();
return result;
};
console.log(decrypto('3P86KyOrN2QJ/HFxxo3b7kAsxTgpDMMjROUPclsuXj0='));
console.log(decrypto('3P86KyOrN2QJ/HFxxo3b7kAsxTgpDMMjROUPclsuXj0=\n')
The second script yields:
nazar@xfce:~/tmp/tst$ ./js_decrypt
Å'{ H£V)ÜB
Å'{ H£V)ÜB
Any help would be very much appreciated as my only remaining option now is to drown myself in a barrel of [Jamerson || Kirin Ichiban] (I'm only kidding)
PS there is a similar question on SO here, which sadly hasn't yielded any inspiration for my case.
The critical missing piece is the IV, which is required when encryption/decryption is to be made across language boundaries as apparently the encrypter will generate a random IV (or something like that - still don't understand how Ruby decrypts the string without an IV.... but then what do I know....), if one is not provided.
The following snippets show how to encrypt a string in Ruby and decrypt in NodeJS.
#!/usr/bin/env ruby
require 'openssl'
require 'base64'
require 'openssl/cipher'
require 'openssl/digest'
aes = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
aes.encrypt
aes.key = Digest::SHA256.digest('IHazSekretKey')
aes.iv = '1234567890123456'
p Base64.encode64( aes.update('text to be encrypted') << aes.final )
The above prints: "eiLbdhFSFrDqvUJmjbUgwD8REjBRoRWWwHHImmMLNZA=\n"
#!/usr/bin/env node
var crypto = require('crypto');
function decrypto(toDecryptStr) {
var result,
encoded = new Buffer(toDecryptStr, 'base64'),
decodeKey = crypto.createHash('sha256').update('IHazSekretKey', 'ascii').digest(),
decipher = crypto.createDecipheriv('aes-256-cbc', decodeKey, '1234567890123456');
result = decipher.update(encoded);
result += decipher.final();
return result;
}
console.log(decrypto('eiLbdhFSFrDqvUJmjbUgwD8REjBRoRWWwHHImmMLNZA=\n'))
The JS script now properly decrypts the string.
One unfortunate side effect is that existing encrypted data will need to be decrypted and then re-encrypted with an IV that is then used in the decrypting implementation.
A PITA but nonetheless a working solution.