Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference in blowfish encryption between perl and ruby

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?

like image 236
joepestro Avatar asked Nov 09 '11 23:11

joepestro


1 Answers

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   
like image 114
bwicklund Avatar answered Oct 10 '22 08:10

bwicklund