2

This question, but focused on .NET's given PBKDF2 implementation, has been asked here now.

Situation

I am currently updating a password storage mechanism for a website.

My plan for storing a password was

  • Create a 16 byte salt*
  • Create a 64 byte hash with that salt, using SHA512*
  • Concatenate the 2
  • Convert the whole thing to Base64
  • Store the result in a 108 character DB field

The amount of iterations is still to be determined (aiming for an amount that will take a bit under one second per login).

*I am working in C#, using the language-provided RNGCryptoServiceProvider and Rfc2898DeriveBytes classes to create salt and hash respectively. This is a standard industry solution. Also it's a verified implementation, which apparently C# bcrypt is not

Do note Rfc2898DeriveBytes is Microsoft's implementation of PBKDF2. (Source Rfc2898DeriveBytes class)

Issue

Well, that was my plan until yesterday.

Then I read that it's a good idea to add the amount of iterations to the password, so that it can be updated to a higher iteration count later (when technology gets faster).

And then I found some suggestions for using a pepper, and some against it. Trying to figure that out ultimately led me to this highly upvoted answer on stackoverflow (last updated 2017)...

...which advocates using encryption instead of hashing, so that you can later re-encrypt all passwords with a higher iteration count/workload, instead of waiting for users to log in again (which might not happen at all anymore).

Common sense tells me that this is a good idea, but - let me put it this way -
Common sense does often not apply when it comes to security.

Question

How should I currently store a user's password in a database?

I would consider this one question, but there are several components to it:

  • Salt length
  • Pepper vs. no pepper
  • Pepper length
  • Encryption vs. hash
  • Encryption/hash algorithm choice
  • Encryption/hash length
  • How to combine all that into one string for the DB
    (For example, I have seen a pattern [salt]$[hash]$[iterations])
  • Reasonably future-proof length for the DB field
    (Considering e.g. that iterations will get bigger over time)
  • The accepted answer on that duplicate I linked to contains all the answers you need and is still 100% applicable. Definitely don't use SHA512! You want a KDF, not a hash function. Definitely don't encrypt. Use one of the suggested KDFs in that answer, most of which will automatically deal with the salt for you. They also have tuneable cost parameters so you can adjust iterations as desired. There is no need to do the hashing yourself - use a standard library – Conor Mancone Nov 5 at 10:39
  • 1
    @ConorMancone "You want a KDF, not a hash function [...] Use a standard library" - you mean like the Rfc2898DeriveBytes that I mentioned I am using? – Raphael Schmitz Nov 5 at 10:44
  • @ConorMancone I also still have to choose an algorithm for that, and SHA512 seemed like a good choice. The answer you linked is akin to a whole book, explaining a semester worth of theory, going into several different algorithms, filling whole screens with solutions which they actually do not really advise... all in all a bit unfocused when applied to a question which could be answered in 1 or 2 paragraphs. – Raphael Schmitz Nov 5 at 11:03
  • @ConorMancone I hate you, I have noticed I was doing it wrong because of the linked answer – bradbury9 Nov 5 at 11:36
  • @RaphaelSchmitz From here, your comment sounds like, "Why are you asking me to read the manual - just tell me what I want to know!". While I appreciate your desire to get to the bottom of things, your question showed a couple misunderstandings about a few different key aspects of password storage. As a result, I think reading the manual is really the right way to go here. Regardless, stackoverflow is not a fan of duplicates, and your question is definitely just a duplicate of the linked to question. Still, you might very well get an answer before this gets closed. – Conor Mancone Nov 5 at 11:40
3

Why do you want to create your own scheme for this? Please use one of the industry standard solutions for this:

I would suggest Bcrypt as that's the most accessible on a PC. but all of them have considerations you will probably miss if you try to implement your own (as would anyone).

This list is time sensitive, so please check for the current best practices. It is based in part on the list of key derivation functions from Wikipedia.

  • OK, same as the comment by Conor Mancone under the question: "Please use one of the industry standard solutions for this" - so, like .NET's Rfc2898DeriveBytes that I mentioned I am using? Concerning bcrypt, apparently that's a bad choice in my situation. – Raphael Schmitz Nov 5 at 10:48
  • as stated in that awnser use PBKDF2 in C#. I am not a C# developer so I can not tell you if just the RFC2898 is enough – LvB Nov 5 at 11:09
  • @LvB That class according to MS documentation is a PBKDF2 implementation. "Implements password-based key derivation functionality, PBKDF2, by using a pseudo-random number generator based on HMACSHA1" Source .NET API reference – bradbury9 Nov 5 at 11:42
  • @bradbury9 Good to know. than it looks like Raphael Schmitz can just use that. – LvB Nov 5 at 11:43
  • I have submitted an edit with the MS link, hope it makes it into the question. I think OP question is more likely "not sure if PBKDF2 is the best choice because of Pepper" – bradbury9 Nov 5 at 11:48

Not the answer you're looking for? Browse other questions tagged or ask your own question.