Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Authenticating password encrypted in PHP using Blowfish with Ruby

There is an application written in PHP which I am converting to Ruby. When encrypting passwords the PHP app uses the following code:

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

I'm assuming this is using a Blowfish implementation. The x's here are all a-zA-Z0-9 characters.

The Blowfish implementation in Ruby uses the following syntax (taken from http://crypt.rubyforge.org/blowfish.html):

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

I don't have a 56 or fewer byte long string and it's not clear what that should be from the PHP version. So how can I write a Ruby function which will encrypt passwords to give the same result as the PHP one?

like image 408
Luke Saunders Avatar asked Dec 16 '11 16:12

Luke Saunders


1 Answers

The PHP code is hashing $pass with the salt $2a$07$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxx$ if CRYPT_BLOWFISH is set (CRYPT_BLOWFISH == 1). The salt has to follow the format indicated in the PHP documentation ("$2a$", a two digit cost parameter, "$", and 22 digits from the alphabet "./0-9A-Za-z").

I'm not sure if you can do it with the library you are referring, but you can use bcrypt-ruby instead.

For your code it would be something like this, I'm using the same data from the PHP example ( http://php.net/manual/en/function.crypt.php ), I only take the 29 first characters of the salt because beyond that PHP ignores it:

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"

This gives you the same output as on the PHP example. If your salt is too long take the first 29 characters ($2a$07$ plus the next 22 extra characters).

I tested the behavior of PHP, if the salt is too long (beyond 29 characters in total) the rest is ignored, if the salt is too short it will return 0. E.g in 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
?>
like image 126
Jorge Núñez Avatar answered Oct 10 '22 08:10

Jorge Núñez