我可以在ruby中复制PHP的AES加密的确切行为吗?

时间:2011-07-14 21:05:01

标签: php ruby encryption aes

我正在使用Ruby on Rails重建PHP Web应用程序,并且非常希望避免强制所有现有用户重置其加密密码。 PHP站点使用mcrypt_encrypt和AES-256-ECB,我不能在我的生活中使用ruby的OpenSSL获得相同的密文。我也无法解密它们(原则上这是好的),因为实际存储在用户数据库中的是AES密文的MD5哈希值。

我已经阅读了这些以前密切相关的问题以及非常有用的答案:

包括那里引用的页面,如果我理解正确,PHP和ruby实现使用不同的填充方法。既然我必须接受PHP方面的工作方式,有没有办法在某种程度上强制在ruby / OpenSSL上使用相同的填充方法?我正在使用ruby 1.9.2-p180。

以下是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);

输出:6337137fd88148250fd135a43dbeb84a

在红宝石中:

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)

输出:18dee36145c07ab83452aefe2590c391

3 个答案:

答案 0 :(得分:5)

实际上通常不是一个openssl解决方案,但也许你可以有一个有效的例子。

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)

我使用了额外的宝石(ruby-mcrypt)。似乎是openssl的一个问题。实际上问题似乎是Openssl不支持零填充并使用no-padding或default-openssl-padding。由于你在php中使用零填充,你必须在ruby中使用零填充。

我的机器上为php脚本输出:

[~/test] ➔ php5 t.php 
6337137fd88148250fd135a43dbeb84a

和红宝石脚本:

[~/test] ➔ ruby t2.rb 
password
6337137fd88148250fd135a43dbeb84a

和我的红宝石版本:

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

希望这有帮助。

答案 1 :(得分:1)

如果密钥大小在php端不是标准的,你需要用零填充密钥到下一个有效的密钥大小,以使ruby端工作如下:

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)

在这种情况下,下一个有效密钥长度为24。

对于:rijndael_256有效密钥长度为:16,24,32

您可以获得有关算法的更多信息:

Mcrypt.algorithm_info(:rijndael_256

答案 2 :(得分:0)

如果您可以使用其他加密方法,则可以尝试TEA块加密。我已经采用了Ruby,JS,ActionScript的方法。它也应该与PHP一起使用。 github repo是here