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.