8

I have searched all over Google and I can't find a code sample of Scrypt usage (for hashing a password) using the Cryptsharp library.

Can you please provide a sample for hashing the password?

William Hurst
  • 2,231
  • 5
  • 33
  • 54
  • There is a lot of questions where you have not accepted an answer, William. Could you please go over them and see which ones can be accepted? If answers are not complete, please let us know! – Maarten Bodewes Nov 21 '13 at 01:10
  • Just needed some time to confirm that it works, it has now been marked as the answer. – William Hurst Nov 21 '13 at 09:40

2 Answers2

16

It's only a single call so I'll walk you through the parameters:

  1. key: this is your password, use UTF-8 encoding (without byte order mark) to encode your password into a byte array;
  2. salt: a string of secure random bytes stored with the result of the scrypt function, 16 bytes should be ample;
  3. cost: the given suggestion is 262144, but you may want to increase that value if your server can handle the additional load;
  4. blockSize: see cost, the given suggestion is 8;
  5. parallel: I would keep this to 1 unless you want to experiment with multi-threading;
  6. maxThreads: in general null will do nicely;
  7. derivedKeyLength: well, that depends, for passwords 128 should be ample though, it's unlikely that your password has more than 128 bits of security.

You should store at least the salt and result. You may want to use base 64 encoding if you want to store them as strings.

I would recommend you to store one additional piece of data: a version of your password based key derivation scheme (PBKDF). Say, set it to 1 for using scrypt, using the given key encoding, salt size, cost, blocksize etc. In that case you can upgrade your scheme later on (you need the user to supply his/her password to do this, so you will have to do this online, so you will end up having multiple schemes operational at the same time).

Note that you may chain PBKDF function calls, so you could use the original PBKDF output and use that as input for the next PBKDF. In that case the user doesn't have to supply the password (this hint was taken from CodesInChaos on another question).

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • In general you only require the performance benefits of multi-threading if you have multiple users. However if you have multiple users, they will likely do the multi-threading for you. So in that sense it is only useful if you want to have a shorter latency for a user that uses high `cost` or `blockSize`. – Maarten Bodewes Nov 18 '13 at 20:39
  • It seems to work just fine but I can't use the Crypter.CheckPassword() command. Would it be OK to just hash the provided password with the salt stored in the user's record and compare that against the saved password? – William Hurst Nov 21 '13 at 09:40
  • How does the cost influence the time taken to generate the hash? i.e. if I half the cost of 262144, will it take half the time or is it less linear than that? – William Hurst Nov 21 '13 at 10:48
  • Yes, a compare should work fine. It would be best to use a compare that returns in constant time (it should not be possible for an attacker to see which byte fails, even though the password was hashed before). The cost is input for a simple for/next, so yes, that should be a lineair value (note that it should be a power of two). Check the relatively small [scrypt draft](http://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01) for more information, it should be pretty easy to read. – Maarten Bodewes Nov 21 '13 at 11:49
  • @MaartenBodewes What does "a random set of secure random bytes" mean? And "stored with the result" means: store the result of this method, along with the salt value you passed as an argument to it, in your database row for this user in the "key" and "salt" columns respectively? –  Jul 14 '15 at 18:57
  • @Superstringcheese I've tried to clarify this in the answer, thanks for helping me sharpen it up. – Maarten Bodewes Jul 16 '15 at 22:42
4

@MaartebBodewes provides an excellent answer with very wise additional tips. Here is a code sample with his recommendations. I would also suggest reading 'Your password is too damn short' which shows the importance of using modern cryptography like (at the time of writing) BCrypt or Scrypt.

public string Hash(string secret, string salt)
{
    var keyBytes = Encoding.UTF8.GetBytes(secret);
    var saltBytes = Encoding.UTF8.GetBytes(salt);
    var cost = 262144;
    var blockSize = 8;
    var parallel = 1;
    var maxThreads = (int?)null;
    var derivedKeyLength = 128;

    var bytes = SCrypt.ComputeDerivedKey(keyBytes, saltBytes, cost, blockSize, parallel, maxThreads, derivedKeyLength);
    return Convert.ToBase64String(bytes);
}
Muhammad Rehan Saeed
  • 35,627
  • 39
  • 202
  • 311