Why is something encrypted in PHP not matching the same line encrypted in Ruby?

Here are my requirements:

I need to encrypt a string in PHP using AES encryption (including random iv), Base64 encode it, and then encode by URL so that it can be passed as a URL parameter.

I am trying to get the same result in both PHP and Ruby, but I cannot get it to work.

Here is my PHP code:

function encryptData($data,$iv){ $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); $iv_size = mcrypt_enc_get_iv_size($cipher); if (mcrypt_generic_init($cipher, 'g6zys8dlvvut6b1omxc5w15gnfad3jhb', $iv) != -1){ $cipherText = mcrypt_generic($cipher,$data ); mcrypt_generic_deinit($cipher); return $cipherText; } else { return false; } } $data = 'Mary had a little lamb'; $iv = '96b88a5f0b9efb43'; $crypted_base64 = base64_encode(encryptData($data, $iv)); 

Here is my Ruby code:

 module AESCrypt def AESCrypt.encrypt(data, key, iv) aes = OpenSSL::Cipher::Cipher.new("aes-256-cbc") aes.encrypt aes.key = key aes.iv = iv aes.update(data) + aes.final end end plaintext = "Mary had a little lamb" iv = "96b88a5f0b9efb43" @crypted = AESCrypt::encrypt(plaintext, "g6zys8dlvvut6b1omxc5w15gnfad3jhb", iv) @crypted_base64 = Base64.encode64(@crypted) @crypted_base64_url = CGI.escape(@crypted_base64) 

The concern is that both code samples create similar but not identical hashes. For example, the above code generates (base64 encoded, not URL encoded):

PHP: /aRCGgLBMOOAarjjtfTW2Qg2OtbPDLhx3KmgfgMzDJU=

Ruby: /aRCGgLBMOOAarjjtfTW2XIZhZ9VjBx8PdozxSL8IE0=

Can someone explain what I'm doing wrong here? Also, it is easier for me (since I'm usually Ruby, not PHP) to fix the Ruby code, not the PHP code. Therefore, if you want to provide a solution in Ruby that works well with PHP, I would really appreciate it.

Oh, and also, in production, iv will indeed be random, but for this example, I set it on an ongoing basis the same so that the result can be compared.

EDIT:

Thanks to Eugen Rieck's answer, I came to a solution. Ruby overlays blocks, but PHP does not, and you must do this manually. Change the PHP code to the following and you will get encrypted strings that can be decrypted higher than the Ruby code:

 $iv = '96b88a5f0b9efb43'; $data = 'Mary had a little lamb'; function encryptData($data,$iv){ $key = 'g6zys8dlvvut6b1omxc5w15gnfad3jhb'; $padded_data = pkcs5_pad($data); $cryptogram = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $padded_data, MCRYPT_MODE_CBC, $iv); return $cryptogram; } function pkcs5_pad ($text, $blocksize){ $pad = $blocksize - (strlen($text) % $blocksize); return $text . str_repeat(chr($pad), $pad); } 
+6
ruby php openssl mcrypt
source share
1 answer

It turns out it's pretty simple: the gasket is the culprit.

AES is a block cipher, so it works on blocks of fixed size. This means that the last block will always be supplemented, and, you know, the good thing about standards is that there are so many of them. PHP uses zero padding, you will need to examine AESCrypt to find out what Ruby uses.

The same problem exists with various JS AES libraries and PHP. We finished everything by making our own addition, as it made me bloody red furious several times.

Of course, this explains why the first part (carrying information) is identical, and the second part (with gasket) is different.

+8
source share

All Articles