Why is there a difference in blowfish encryption between Crypt::CBC (perl) and OpenSSL (ruby)?
Perl
use Crypt::CBC;
my $cipher = Crypt::CBC->new( -key => 'length32length32length32length32', -cipher => 'Blowfish' );
my $ciphertext = $cipher->encrypt_hex('test');
# ciphertext is 53616c7465645f5f409c8b8eb353823c06d9b50537c92e19
Ruby
require "rubygems"
require "openssl"
cipher = OpenSSL::Cipher::Cipher.new("bf-cbc")
cipher.encrypt
cipher.key = "length32length32length32length32"
result = cipher.update("test") << cipher.final
ciphertext = result.unpack("H*").first
# ciphertext is 16f99115a09e0464
Crypt::CBC seems to be prepending Salted__
to the output by default. Can you explain what is going on that is so different between these? Is there a way to make OpenSSL behave in a similar way to Crypt::CBC?
Crypt::CBC (perl) uses its own method to randomize the salt and initialization vector. Plus in the case of Blowfish it uses a key length of 56 as mentioned above.
Using the perl code from your example:
Perl
use Crypt::CBC;
my $cipher = Crypt::CBC->new( -key => 'length32length32length32length32', -cipher => 'Blowfish' );
my $ciphertext = $cipher->encrypt_hex('test');
# 53616c7465645f5f409c8b8eb353823c06d9b50537c92e19
To decode this using ruby (OpenSSL) requires a little tweaking to extract the key and initialization vector:
Ruby
require 'openssl'
# Hex string to decode(from above)
string = '53616c7465645f5f409c8b8eb353823c06d9b50537c92e19'
# Pack Hex
string = [string].pack('H*')
# Some Config
pass = 'length32length32length32length32'
key_len = 56;
iv_len = 8;
desired_len = key_len + iv_len;
salt_re = /^Salted__(.{8})/
#Extract salt
salt = salt_re.match(string)
salt = salt.captures[0]
data = '';
d = '';
while (data.length < desired_len)
d = Digest::MD5::digest("#{d}#{pass}#{salt}");
data << d;
end
#Now you have extracted your key and initialization vector
key = data.slice(0..key_len-1)
iv = data.slice(key_len .. -1)
# Trim string of salt
string = string[16..-1]
cipher = OpenSSL::Cipher::Cipher.new "bf-cbc"
cipher.decrypt
cipher.key_len = key_len
cipher.key = key
cipher.iv = iv
puts cipher.update(string) << cipher.final
# test
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With