What should I use as a secure/strong salt for PBKDF2 hashing when salt is not available to use before login as it will be client-side javascript to hash user+pass with PBKDF2 ? I'm going to use sha(user+pass) as salt for pbkdf2.

If I use a random generated salt, I should store it in DB, but when user wants to login, user won't have salt to encrypt his password with salt before sending it to server for verification.

So what's good/safe/secure solution here? P.S. I'm trying to achieve "zero knowledge" protocol. Also I am already using SSL.


First, make sure you read this answer to the question "Client side password hashing", paying particular attention to the last paragraph.

Also, please realize that client side javascript is going to be incredibly slow at PBKDF2 compared to good server side code. At least try to find a PBKDF2 implementation that uses HMAC-SHA-512 as a base.

That said, if you want to give the user peace of mind, that's fine; do the following:

  • Client side PBKDF2 hashing for a known, "high" iteration count.
    • Double bonus points if the user is allowed to select the iteration count themselves!
    • I put high in quotes because I doubt your javascript code's going to be fast enough to do tens or hundreds of thousands of iterations in the time you can get enough of your user base to accept, particularly on cheaper mobile devices.
    • A good hash of the username and password as a salt isn't great, though it's better if your code pads the username out to the maximum possible length and puts it first.
      • That way, "user1" and "password" don't make the same salt as "user" and "1password"!
      • There is, of course, no maximum length on the password except what's caused by your back end software; SQL Server, for instance, has an 8000 byte maximum on "less inefficient" string work.
  • Send that hash by itself to the server
    • which then DOES generate a cryptographically random salt of 12-16 bytes
    • and then uses PBKDF2 with a much higher iteration count to hash the hash passed in
      • again hopefully HMAC-SHA-512 for the 64 bit operations to lessen the proportionate advantage of offline GPU attacks.
      • because then someone who gets your leaked password database still has to do the work of an attack against a password hashing function to log in, rather than simply sending the client-generated hash they stole and having it be accepted as-is.

Remember with PBKDF2 password hashing in particular, never ask for an output size larger than the native base hash's output size. Smaller is all right if you're really, really concerned about storage; for instance, requesting only 32 bytes of PBKDF2-HMAC-SHA-512's native 64 byte output.

  • 20 bytes for SHA-1
  • 32 bytes for SHA-256
  • 64 bytes for SHA-512
  • Thank you, you deserve your username! So in short, I'm going to pad username with lets say 0x90909090 (will be constant) for max. salt length. Then I'll use user's password and padded salt to generate 64 bytes of SHA512 PBKDF2 with min of 5000 iterations. User will be able to set iterations during account creation and in settings page. In server I'll also additionally PBKDF2 (SHA512) 5000 times hash sent by user and store (during creation) and check (login) with my entry in DB. Also in server during creation I'll assign a user specific salt so I can use for server side PBKDF2. Approve? – JustACPPFan Jan 11 '15 at 21:36
  • P.S. I'll have a fast JS library for PBKDF2 and SHA512, I already have something for it. – JustACPPFan Jan 11 '15 at 21:41
  • To clarify, you're not padding username for max salt length, you're padding username to the maximum allowable username length before you concatenate the password for the client side salt, i.e. the salt is HASH(LEFT(username + 0x909090...90,UsernameLength)+password). Note that your zero knowledge protocol means the user's client side iteration count must be set on the client's browser, not in your database; perhaps a field on the login screen itself. If they can get the iteration count from the database, they can get the salt, and then you can use a real cryptographically random salt. – Anti-weakpasswords Jan 11 '15 at 22:26
  • Also, if you have a fast JS library for PBKDF2-HMAC-SHA-512 under an open source license, I'd like to try adding it to my GitHub repository, which also has a reasonable set of test vectors if you'd like to test your library. – Anti-weakpasswords Jan 11 '15 at 22:27
  • I'm using this: github.com/digitalbazaar/forge and all code you need (after script src stuff) is this: var key = forge.pkcs5.pbkdf2(userpass, username, 5000, 64, forge.sha512.create()); I tried output of it with other libraries (PHP PBKDF2 and CryptoPP) same output. I didn't really get your padding thing. What's max username length? It's user's email address? Should I really do padding and can you tell me who defines max. username length? It's just email address. – JustACPPFan Jan 12 '15 at 1:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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