Let's say we have a database with usernames and passwords, where the passwords are naively secured using a single round of SHA-1 (such as was kinda best practice a number of years ago).

Now, let's say we wish to upgrade the security of the credential storage, but users must remain blissfully unaware that any change is taking place.

Obviously, we don't have the passwords in plaintext, but I am considering just treating the sha1(password) as if it was the plaintext password, and secure on top of that.

Here's my thinking:

  1. Generate random salt per user (128 bit)
  2. Replace "username","sha1(password)" in the database with "username","salt","bcrypt(salt,sha1(password)),iterations=20000"
  3. Change the validation-code to validate passwords by first doing sha1, then bcrypt the result with the salt n times, and then check.

Are there any glaring faults in this strategy?

While not perfect, is it reasonable to say that this vastly improves the security of the users passwords, in the case of a breach?

  • If changing the hash vastly improves the security, then you might need to look at your database security. To brute force those sha1 passwords, they first have to obtain them, which really aught to be extremely difficult. Apr 6 '16 at 8:32
  • 2
    Obviously, database access security is paramount, but breaches do happen. If it happened to Sony, it can happen to me. To protect my users as well as possible, within my constraints, I believe it is relevant to look at worst-case scenarios. I did write "in the case of a breach" for this exact reason.
    – Niels2000
    Apr 6 '16 at 8:41
  • One side note: bcrypt manages its own salt internally, you don't need to generate and store it.
    – AviD
    Apr 6 '16 at 10:10

I see no faults there. When using bcrypt, it's often actually a good idea to use a regular hash first, because bcrypt has a little known downside of being limited to only 72 characters of input. Using a hash before makes the input size effectively unlimited, while not reducing security at all. So not only do you get the extra strength of bcrypt, but continuing to use SHA-1 improves bcrypt's flexibility, rather than improving its strength (which it only improves by an insignificant amount).


With this scheme you are certainly making an attacker’s life harder. Here is the general attack algorithm for cracking bcrypt-protected plaintext passwords:

  1. Obtain hashes (obviously)
  2. Generate candidate passwords for password cracking tool
  3. Perform the cracking attempt

And here is the attack algorithm for cracking your sha1-hashed-than-bcrypted passwords:

  1. Obtain hashes
  2. Generate candidate passwords for password cracking tool
  3. Calculate corresponding SHA-1
  4. Perform the cracking attempt

So, as you can see, the attacker must perform one cheap additional step to crack the password. So, your scheme should provide at least the same security level as using bcrypt to protect plaintext passwords.

As a small bonus, you are getting scheme which is not implemented out-of-box in common cracking tools. It will make password cracking even harder if the attacker is not very sophisticated and will not be able to figure out hashing scheme. But this feature is security by obscurity, so it is better to expect that attacker will know all about your password hashing approach.

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