Django password check in Ruby on Rails gives inconsistent password

I am rewriting a Django application in Ruby on Rails and want to keep old passwords for users.

Django uses PBKDF2SHA1 as an encryption mechanism. This way I have one encrypted password

pbkdf2_sha256$10000$YsnGfP4rZ1IZ$Tpf4922MoNEjuJQA9EG2Elptyt3dMAyzBPUgmunFOW4= 

original password 2bulls

In Ruby, I use the gem PBKDF256 and base64 for validation.

 Base64.encode64 PBKDF256.dk("2bulls", "YsnGfP4rZ1IZ", 10000, 32) 

I expect

 Tpf4922MoNEjuJQA9EG2Elptyt3dMAyzBPUgmunFOW4= 

However i got

 YEfK6oUGFHdaKZMDXC0Dz8TpwsJlKfqC5vjCxjo+ldU= 

Any ideas?

UPDATE

Found code in django source if that makes more sense to you.

 class PBKDF2PasswordHasher(BasePasswordHasher): """ Secure password hashing using the PBKDF2 algorithm (recommended) Configured to use PBKDF2 + HMAC + SHA256 with 10000 iterations. The result is a 64 byte binary string. Iterations may be changed safely but you must rename the algorithm if you change SHA256. """ algorithm = "pbkdf2_sha256" iterations = 10000 digest = hashlib.sha256 def encode(self, password, salt, iterations=None): assert password assert salt and '$' not in salt if not iterations: iterations = self.iterations hash = pbkdf2(password, salt, iterations, digest=self.digest) hash = base64.b64encode(hash).decode('ascii').strip() return "%s$%d$%s$%s" % (self.algorithm, iterations, salt, hash) def verify(self, password, encoded): algorithm, iterations, salt, hash = encoded.split('$', 3) assert algorithm == self.algorithm encoded_2 = self.encode(password, salt, int(iterations)) return constant_time_compare(encoded, encoded_2) def safe_summary(self, encoded): algorithm, iterations, salt, hash = encoded.split('$', 3) assert algorithm == self.algorithm return SortedDict([ (_('algorithm'), algorithm), (_('iterations'), iterations), (_('salt'), mask_hash(salt)), (_('hash'), mask_hash(hash)), ]) 

OUTPUT:

It turns out that this problem has only an account with 2bulls being a password. Other accounts are in order. When I know the exact reason for the inconsistent password for 2bulls, I will post here.

+6
source share
2 answers

If you use this 2bulls password using the following script (the same logic that Django uses for hash passwords), this is what you get (run this on the Django shell):

 >>> import base64, hashlib >>> hash = pbkdf2("2bulls","YsnGfP4rZ1IZ", 10000, 32, hashlib.sha256) >>> hash.encode('base64').strip() 'YEfK6oUGFHdaKZMDXC0Dz8TpwsJlKfqC5vjCxjo+ldU=' 

Notice how I use the same options that you use in Ruby:

 password = "2bulls" salt = "YsnGfP4rZ1IZ" iterations = 10000 dklen = 32 digest = hashlib.sha256 

Are you sure your expected hash matches the 2bulls password?

+6
source

I just released a stone for this purpose. I also get the same result as @Daniel Aronne:

 require 'pbkdf2_password_hasher' puts Pbkdf2PasswordHasher::hash_password('2bulls','YsnGfP4rZ1IZ',10000,32) #=> "YEfK6oUGFHdaKZMDXC0Dz8TpwsJlKfqC5vjCxjo+ldU=" 
0
source

All Articles