I'm working on improving a CMS where the current implementation of storing password is just sha1(password). I explained to my boss that doing it that way is incredibly insecure, and told him that we should switch to bcrypt, and he agreed.

My plan was to just run all the existing hashes through bcrypt and store those in the password field, and then use the following psudo-code to check the password: correctPassword = bcrypt_verify(password, storedHash) or bcrypt_verify(sha1(password), storedHash).

This way, new users, or users who change their passwords will get "real" bcrypt hashes, while existing users won't all have to change their passwords. Are there any disadvantages to doing this? While it would probably be ideal to ask all users to choose a new password, do we lose much in the way of security by doing this?

I was thinking that even if an attacker got access to both the database and the code, cracking won't be substantially faster even if the majority of the "input" to bcrypt was a 40 character hex string, since the slow part (bcrypt_verify()) still has to be invoked for each password attempt on each user.

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

