Can I reproduce the exact behavior of PHP AES encryption in ruby?

I'm rebuilding a PHP web application in Ruby on Rails and would really like to avoid forcing all existing users to reset their encrypted passwords. The PHP site uses mcrypt_encrypt with AES-256-ECB, and I canโ€™t get the same text for the rest of my life using ruby โ€‹โ€‹OpenSSL. I also can not decrypt them (which is good in principle), since the actual data stored in the user database is an MD5 hash of AES encryption text.

I read these previous, closely related questions and very helpful answers:

including linked pages, and if I understand correctly, PHP and Ruby implementations use different fill methods. Since I need to live with how everything works on the PHP side, is there a way to force the same filling method on ruby โ€‹โ€‹/ OpenSSL somehow? I am using ruby โ€‹โ€‹1.9.2-p180.

Here is a sample code in PHP:

$salt = "12345678901234567890123456789012"; $plain = "password"; $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $cipher = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $salt, $plain, MCRYPT_MODE_ECB, $iv); echo md5($cipher); 

Output: 6337137fd88148250fd135a43dbeb84a

and in ruby:

 require 'openssl' salt = "12345678901234567890123456789012" plain = "password"; c = OpenSSL::Cipher.new("AES-256-ECB") c.encrypt c.key = salt cipher = c.update(plain) cipher << c.final puts Digest::MD5.hexdigest(cipher) 

Output: 18dee36145c07ab83452aefe2590c391

+4
source share
3 answers

Itโ€™s not really an openssl solution at all, but it may work fine for you.

 require 'mcrypt' require 'openssl' plaintext = 'password' puts plaintext key = '12345678901234567890123456789012' enc = Mcrypt.new(:rijndael_256, :ecb, key, nil, :zeros) encrypted = enc.encrypt(plaintext) puts Digest::MD5.hexdigest(encrypted) 

I used an extra gem (ruby-mcrypt). There seems to be a problem with openssl. Actually, the problem is that Openssl does not support zero padding and uses either no-padding or default-openssl-padding. Due to the fact that you are using a zero padding in php, you should also use a zero padding in ruby.

Output on my computer for php script:

 [~/test] โž” php5 t.php 6337137fd88148250fd135a43dbeb84a 

and for ruby โ€‹โ€‹script:

 [~/test] โž” ruby t2.rb password 6337137fd88148250fd135a43dbeb84a 

and my ruby โ€‹โ€‹version:

 [~/test] โž” ruby -version ruby 1.9.2p0 (2010-08-18 revision 29036) [i686-linux] 

Hope this helps.

+5
source

If the key size is not standard on the php side, you need to fill the key with zeros to the next valid key size to make the ruby โ€‹โ€‹side, for example:

 php_encrypted = string_encoded_with_php_mcrypt key = "longerthan16butnot24".to_a.pack('a24') enc = Mcrypt.new(:rijndael_256, :ecb, key, nil, :zeros) enc.decrypt(php_encrypted) 

In this case, the next valid key length is 24.

For: rijndael_256 valid key lengths: 16, 24, 32

You can get additional information about the algorithms:

 Mcrypt.algorithm_info(:rijndael_256 
+1
source

if you can use other encryption methods, you can try TEA Block Encryption. I used the Ruby, JS, ActionScript method. It should also work with PHP. github repo here

0
source

All Articles