Is using bcrypt on existing SHA1 hashes good enough when switching password implementation?

Actually this is a good way to protect the otherwise unsecurely stored passwords. There is one weak point in this scheme though, which can be overcome easily in marking old hashes, so I would prefer this solution:

if (checkIfDoubleHash(storedHash))
  correctPassword = bcrypt_verify(sha1(password), storedHash)
else
  correctPassword = bcrypt_verify(password, storedHash)

Imagine an attacker getting hold of an old backup. He would see the SHA hashes, and could use them directly as passwords if you test with bcrypt_verify(...) or bcrypt_verify(sha1(...)).

Most bcrypt libraries add a mark of the used algorithm themselves, so it is not a problem if you add your own "double hash mark", but of course you can also use a separate database field for this:

$2y$10$nOUIs5kJ7naTuTFkBy1veuK0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa
 |
 hash-algorithm = 2y = BCrypt

Why not simply use bcrypt(sha1(password)) for all passwords both old and new? This avoids the problem of people using your old hashes as passwords and is also simpler than your proposal.


It's a good strategy, you won't loose any security unless a user decided to generate a truely random password longer than 160-bits as it will be truncated. So the difference is minimal. (in which case it would still take a significant amount of time to bruteforce the original text)

You might opt to implement some logic to migrate the passwords next time a user changes it, but I don't see any risk that would require immediate change of passwords, unless you believe the hashes have leaked.