I suppose it’s not a bad idea to delete all your DB backups, too. After all, the backups of your database have the easy to hack password in them. It would be just as bad if an attacker got a hold of a backup.
I opted for a different solution. Just invalidated all passwords in our DB without a migration process. Yes it’s annoying for users and generates some support requests but at least it’s immediate with no additional code to maintain and make errors in.
Ah wow we were in exactly this scenario a year ago and solved it in exactly the same way! We defined our own “$shyp_crypt$” format for decoding the bcrypt(sha1(hashes)) too (vs $2a$)
[Comment removed by author]
I am not sure where you got the idea that the post says anything about storing the passwords encrypted. The post does not use the word encrypt or contain any references to common encryption systems (AES, etc). You may be confusing bcrypt, which is not an encryption algorithm. Bcrypt is an adaptive hash function specifically designed for passwords, you can read the original paper at: https://www.usenix.org/legacy/events/usenix99/provos/provos.pdf. If you’re unclear on the difference between encrypting and hashing, then I suggest reading this StackOverflow post: http://stackoverflow.com/questions/4948322/fundamental-difference-between-hashing-and-encryption-algorithms.
The problem with the scheme you described is the same problem that just hashing the password with a standard cryptographic hash function would have, in that it is incredibly fast. The adaptive part of bcrypt and similar functions means they can be tuned to be intentionally slow. The reason that fast is bad is it doesn’t slow down an attacker that is attempting to brute force the password. If it takes a user an additional 500ms to login, they won’t typically notice, however an attacker is definitely going to notice if each guess of a password against the leaked database values takes 500ms.
The article has been changed in a way that is closer to what I was recommending in my previous comment, and I never recommended not using bcrypt. I recommended using bcrypt differently than the article suggested. Encryption was the wrong word, but I feel like my suggestion is more important than bike shedding over whether “encryption” was the right word or not.
The point is simply that the best way to store user passwords is to not store them.
I wrote the article and I can assure you it has not been changed. Passing random bytes through bcrypt doesn’t make sense. Bcrypt is a function that takes three parameters: a cost, a salt, and a password. In most bcrypt implementations it will take care of providing a random salt for you and it will default cost to something reasonable. The only parameter you typically have to specify is the password. If you were trying to say you need to pass a random value as a salt than sure, I agree, but that is not what the remainder of your comment was describing.
To put it simply bcrypt takes two inputs and it would make sense for the article to emphasize that the password should be the salt and not as the key. Using the password as the salt and random bytes as the key is all I’m suggesting. The article is ambiguous about this.
You do realize that the value you give to bcrypt as the salt is not protected at all. I really hope you haven’t built this into any systems. If you have, you should go back and have a security professional evaluate them.