2011-12-16 43 views
6

有一个用PHP编写的应用程序,我将它转换为Ruby。当加密密码的PHP应用程序使用以下代码:验证在PHP中使用Blowfish和Ruby加密的密码

if($method == 2 && CRYPT_BLOWFISH) return crypt($pass, '$2a$07$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxx$'); 

我假设这是使用Blowfish实现。这里的x都是a-zA-Z0-9个字符。

在Ruby中的河豚实现使用以下语法(从http://crypt.rubyforge.org/blowfish.html拍摄):

blowfish = Crypt::Blowfish.new("A key up to 56 bytes long") 
plainBlock = "ABCD1234" 
encryptedBlock = blowfish.encrypt_block(plainBlock) 

我没有56或更少字节长的字符串,目前还不清楚是什么,应该是从PHP版本。那么,如何编写一个Ruby函数来加密密码以得到与PHP相同的结果呢?

回答

4

如果设置了CRYPT_BLOWFISHCRYPT_BLOWFISH == 1),则PHP代码将散列$pass与盐$2a$07$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxx$进行散列。盐必须遵循PHP文档("$2a$", a two digit cost parameter, "$", and 22 digits from the alphabet "./0-9A-Za-z")中指定的格式。

我不确定您是否可以使用您所指的库,但可以使用bcrypt-ruby代替。

为您的代码会是这样的,我用从PHP示例(http://php.net/manual/en/function.crypt.php)相同的数据,我只取盐的29个字符,因为超出了PHP忽略它:

require 'bcrypt-ruby' 
pass = "rasmuslerdorf" # Here you should put the $pass from your PHP code 
salt = '$2a$07$usesomesillystringfors' # Notice no $ at the end. Here goes your salt 
hashed_password = BCrypt::Engine.hash_secret(pass,salt) # => "$2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi" 

这给出了与PHP示例相同的输出。如果您的盐太长,请先拿出29个字符($ 2a $ 07 $加上接下来的22个额外字符)。

我测试PHP的行为,如果盐过长(超过总29个字符),余下部分被忽略,如果实在嫌盐总之它会在PHP返回0。例如:

<?php 
    crypt('rasmuslerdorf', '$2a$07$usesomesillystringforsalt$') 
    // returns $2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi 

    crypt('rasmuslerdorf', '$2a$07$usesomesillystringfors') 
    // returns $2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi 

    crypt('rasmuslerdorf', '$2a$07$usesomesilly') 
    // returns 0 because the salt is not long enough 
?> 
+0

这工作完美。谢谢! – 2012-01-29 16:42:52