Разница в шифровании Blowfish между Perl и Ruby - PullRequest
7 голосов
/ 10 ноября 2011

Почему существует разница в шифровании Blowfish между Crypt :: CBC (perl) и 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, по-видимому, добавляет Salted__ к выводу по умолчанию.Можете ли вы объяснить, что происходит так сильно отличается между ними?Есть ли способ заставить OpenSSL вести себя так же, как Crypt :: CBC?

Ответы [ 2 ]

7 голосов
/ 14 ноября 2012

Crypt :: CBC (perl) использует свой собственный метод для рандомизации соли и вектора инициализации. Плюс в случае Blowfish он использует длину ключа 56, как упомянуто выше.

Используя код perl из вашего примера:

Perl

use Crypt::CBC;

my $cipher = Crypt::CBC->new( -key => 'length32length32length32length32', -cipher =>  'Blowfish' );
my $ciphertext = $cipher->encrypt_hex('test');
# 53616c7465645f5f409c8b8eb353823c06d9b50537c92e19

Для декодирования этого с использованием ruby ​​(OpenSSL) требуется небольшая настройка для извлечения ключа и вектора инициализации:

рубин

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   
1 голос
/ 12 ноября 2011

Оказывается, между этими двумя значениями по умолчанию размер ключа blowfish различаются. OpenSSL по умолчанию равен 16, Crypt :: Blowfish по умолчанию равен 56.

Вы можете переопределить размер ключа в Crypt :: CBC, указав -keysize => n, но, к сожалению, не существует способа переопределить размер ключа в OpenSSL.

В библиотеке Openssl по умолчанию используются 16-байтовые размеры ключей Blowfish, поэтому для совместимость с Openssl вы можете установить -keysize => 16

http://metacpan.org/pod/Crypt::CBC

Perl (указать размер ключа)

my $cipher = Crypt::CBC->new( 
    -key => 'length32length32length32length32',
    -keysize => 16,
    -cipher => 'Blowfish' 
);
...