Я пытаюсь перенести устаревший код PHP в ruby, и у меня возникла проблема с некоторым шифрованием 3DES. Это реализация PHP с использованием mcrypt:
function encrypt_3DES($message, $key){
$bytes = array(0,0,0,0,0,0,0,0); //byte [] IV = {0, 0, 0, 0, 0, 0, 0, 0}
$iv = implode(array_map("chr", $bytes)); //PHP 4 >= 4.0.2
$ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv);
return $ciphertext;
}
и это мой рубиновый код:
def encrypt_3DES(message, key)
des=OpenSSL::Cipher.new('des3')
des.encrypt
des.key = key
des.update(message)+des.final
end
Однако результаты немного отличаются (в кодировке base64):
//PHP
ZpgH7NWpRx+Mi6tDBZ9q2Q==
# Ruby
ZpgH7NWpRx/usGDIsQ+A8A==
Как вы можете видеть, это самая низкая часть байтов строки, которая отличается. Любые указатели очень ценятся.
Я отвечаю на свой вопрос.
Это был вопрос о том, как реализации openssl и mcrypt используют заполнение. Мои знания в области криптографии не слишком глубоки, но я нашел здесь полезный пример кода http://opensourcetester.co.uk/2012/11/29/zeros-padding-3des-ruby-openssl/
#ENCRYPTION
block_length = 8
des.padding = 0 #Tell Openssl not to pad
des.encrypt
json = '{"somekey":"somevalue"}'
json += "\0" until json.bytesize % block_length == 0 #Pad with zeros
edata = des.update(json) + des.final
b64data = Base64.encode64(edata).gsub("\n",'')
В основном, ruby openssl будет использовать заполнение PKCS, в то время как mcrypt использует заполнение 0. Так что в нашем коде я должен был сказать openssl не дополнять строку des.padding = 0
а затем выполните заполнение вручную: json += "\0" until json.bytesize % block_length == 0
,
Это важные биты, которые отсутствовали в моей первоначальной реализации.
Может ли PHP
комбинация MCRYPT_3DES
а также MCRYPT_MODE_CBC
не быть эквивалентным рубину OpenSSL
библиотеки 3des
(или же des-ede3-cbc
). Есть примеры других несоответствий.
Попробуйте один из других режимов, таких как des-ede-cbc
или же des-cbc
(Смотрите полный список Вот)