使用Blowfish和Ruby验证在PHP中加密的密码

时间:2011-12-16 16:14:22

标签: php ruby authentication encryption blowfish

有一个用PHP编写的应用程序,我将其转换为Ruby。加密密码时,PHP应用程序使用以下代码:

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

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

Ruby中的Blowfish实现使用以下语法(取自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相同的结果呢?

1 个答案:

答案 0 :(得分:4)

如果设置$pass$2a$07$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxx$),PHP代码将使用salt CRYPT_BLOWFISH散列CRYPT_BLOWFISH == 1。 salt必须遵循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忽略它:< / p>

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个字符),其余部分将被忽略,如果盐太短,它将返回0.例如PHP:

<?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
?>