Should 2FA secret codes be hashed for storage?

6.4k views Asked by At

I'm working on implementing 2FA with Google Authenticator on our website. If I understand correctly every user will have their own secret code, which I will need on login to verify the 6 digit code they enter.

Storing these secret codes in the same database as the user passwords seems like a bad idea (although, if someone got a hold of the database we have bigger problems), is there anyway around it? Or should they just be treated like a password and encrypted?

2

There are 2 answers

1
philnash On BEST ANSWER

You cannot hash the secret used to generate the TOTP code for Google Authenticator because you need the original secret to actually generate the code.

It pretty much is as you say, if someone has your database then you're in bigger trouble anyway. However this is how 2 Factor Authentication is supposed to work. If the password is indeed hashed securely and the attacker has only the TOTP secret then all they can do is generate 1 out of the 2 factors required to login and they have more work to do to break or steal the password.

If you'd rather not worry about storing these secrets for your users and letting a third party take care of it, can I recommend you take a look at Twilio's Two Factor Authentication API. Full disclosure, I work for Twilio, but if you don't want to worry about looking after secrets that you can't hash, as well as take advantage of other things like the Authy app (including secret transfer without QR codes) and the extra device data that is now available with authentications then it might be of interest.

0
ton On

You are right.

Is true that the 2FA increase the user security, but is not so strong at server side by definition. If a hacker or malicious employee with database access dump and publish the users secrets, the adtional security is gone.

What can be done ? You can create a external isolated microservice, that receive a user hash and generate a 2FA secret keys, cryptography it and store in a key-value database, like elasticsearch. You can set the cryptographic key dynamically after the server start, to not store it hard-coded. You can store the database at a external server where the employees have no access other than via API.

This way if a malicious actor dump the elasticsearch database, they can not know what is the secret, and even if he gain access to the crypto keys he doesn't know who is the user that use that secret, because the key is the user id hash(not the user id).

Nothing is perfect, but 2FA targets to make harder to a attacker to have success. I think it help.