4

Im failing to understand how should i store hashed passwords with scrypt.

Here is the example:

import pyscrypt

hashed = pyscrypt.hash(password = b"password",
                       salt = b"seasalt",
                       N = 1024,
                       r = 1,
                       p = 1,
                       dkLen = 16)
print(hashed.hex()) #70ac953b777e24c4f41c4657eb9f03c2

hashed = pyscrypt.hash(password = b"password",
                       salt = b"seasalt",
                       N = 1024,
                       r = 2,
                       p = 1,
                       dkLen = 16)
print(hashed.hex()) #b00b951cd50675806c55d903dba9cbca

hashed = pyscrypt.hash(password = b"password",
                       salt = b"seasalt",
                       N = 1024,
                       r = 1,
                       p = 2,
                       dkLen = 16)
print(hashed.hex()) #7c3fa22552c8a9071da0e8c80a0a2767

In the example above we can see that hash is changed depending of parameter N, r, p values.

Does that mean that i should save N, r, p values too in database?

What should i do in the future when more powerful hardware will be available on the market? For example, ask users to change their password so new hashing function can be applied or something?

RhymeGuy
  • 2,102
  • 5
  • 32
  • 62

2 Answers2

1

Yes, you'll need to store the parameters you used to generate the hash together with the hash. It's usually easiest to uniquely concatenate them into a string, e.g. N|r|p|len|salt|hash, or perhaps JSON-encode a dict. You must also generate a unique, random salt for each password.

Future upgrades can be handled while a user logs in. Pseudo code:

if login_successful:
    if not params_up_to_date(hashed_password):
        hashed_password = hash(entered_password)
        # update database record

You check if the parameters of the hashed password are the same as what you're currently using, and if not you rehash the password which you just used during the login process. Users can be gradually, transparently upgraded this way.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • Nice point regarding future updates. Do you mind telling me how would you concatenate parameters with piece of code. Im stuck right there and im spinning my head. I mean do you literally mean to use something as: `hash_value_to_submit_do_db = ('|'.join(["N","r","p","len","salt","hash"]))`. That would be something like what bcrypt is using, right? – RhymeGuy Nov 18 '15 at 21:16
  • Yes, something as trivial as that'll do. As long as you can reverse the operation and extract the original separate values from it again, that's fine. – deceze Nov 19 '15 at 07:02
0

Most importantly you have to store salt per user.

Typically your record would therefore be something like:

username: scrypt,params,seasalt,89435389985698348998364

(You want to explicitly store type of the record in case some other mechanism is ever used, earlier for migration, or later in general)

Dima Tisnek
  • 11,241
  • 4
  • 68
  • 120