I'm trying to migrate users from our legacy Cerberus SFTP server to a new AWS Transfer Family SFTP server. The problem is most of our Cerberus users have password based authentication and all I have access to is their one-way hashed password. Thus I'm trying to reverse engineer how Cerberus hashes it's password so I don't have to ask our 100+ customers to submit a new password to use or switch to a public key based authentication.
I came across this blog post that I think details how to do it but I can't seem to get it to work for some reason - https://support.cerberusftp.com/hc/en-us/articles/360000040039-Securely-Storing-User-Passwords.
Here are the steps I've taken so far -
Here is what my script looks like so far - https://replit.com/@ryangrush/sample.
import hashlib
import base64
password = b'asdf'
salt = b'sample_salt'
combined = salt + password
first = hashlib.pbkdf2_hmac('sha256', combined, b'', 5000)
combined = salt + first
second = hashlib.pbkdf2_hmac('sha256', combined, b'', 5000)
base_16 = base64.b16encode(second)
print(second.hex())
print(base_16)
The documentation must've been written before the v7.0 PBKDF2 HMAC functions were adopted. The salt and the password are now used just as described in the documentation for PBKDF2.
import hashlib
import base64
hashed_password_entry = '{{PBKDF2 HMAC SHA256}}:5000:42ED67592D7D80F03BF3E2413EB80718C5DAFEB5237FC4E5E309C2940DF1DBB2A4ABD9BB63B8AD285858B532A573D9DE'
entry_components_strings = hashed_password_entry.split(':')
password = b'asdf'
iterations = int(entry_components_strings[1])
salt_plus_hashvalue = base64.b16decode(entry_components_strings[2])
hash_len = 256 // 8
salt, hashvalue = salt_plus_hashvalue[:-hash_len], salt_plus_hashvalue[-hash_len:]
hashvalue_test = hashlib.pbkdf2_hmac('SHA256', password, salt, iterations)
print(hashvalue_test.hex())
the output is c5dafeb5237fc4e5e309c2940df1dbb2a4abd9bb63b8ad285858b532a573d9de
which you can see matches the hashed value that is at the end of entry.