jazzband / django-two-factor-auth

Complete Two-Factor Authentication for Django providing the easiest integration into most Django projects.
MIT License
1.67k stars 446 forks source link

Encrypt secrets in DB #96

Open vilda opened 9 years ago

vilda commented 9 years ago

A good practice is to encrypt or hash secret keys in DB. I would suggest to implement this. (Enhancement)

While for one-off keys one way hash functions such as scrypt/bcrypt are available, that's not the option for TOTP where the actual key value is needed. Simple encryption where the encryption key is not stored in DB suffice.

Encryption of secret keys is recommended by RFC 6238.

Bouke commented 9 years ago

The relevant part in the specification is the following:

We also RECOMMEND storing the keys securely in the validation system, and, more specifically, encrypting them using tamper-resistant hardware encryption and exposing them only when required: for example, the key is decrypted when needed to verify an OTP value, and re-encrypted immediately to limit exposure in the RAM to a short period of time.

The key store MUST be in a secure area, to avoid, as much as possible, direct attack on the validation system and secrets database. Particularly, access to the key material should be limited to programs and processes required by the validation system only.

Hardware encryption cannot be enforced by this package, but the encryption could be implemented.

Bouke commented 7 years ago

A possible package to perform the encryption would be: https://github.com/pyca/cryptography.

wkschwartz commented 7 years ago

Another possible package: https://github.com/defrex/django-encrypted-fields

Bouke commented 7 years ago

I've looked into this and the issue is that this package only stores the PhoneDevice, but not the other Devices, most notably the TOTPDevice. So while we could encrypt some of the fields, we still wouldn't cover all situations.

wkschwartz commented 7 years ago

Perhaps a more thorough solution would involve django_otp adopting database encryption in a way that this package could inherit?

wkschwartz commented 7 years ago

Incidentally, I should probably take back my recommendation of django-encrypted-fields: it's not Python 3 compatible: defrex/django-encrypted-fields#27

blubber commented 6 years ago

Encryption doesn't really add any security in this case, unless you have a safe way to store the encryption keys.

One possible solution would be to somehow derive a key from the user's password (you can use Django's pbkdf2 implementation for this, but don't use the stored password hash!) However, looking at django-otp's code this is currently not possible and would be best done in their TOTPDevice implementation.

For now, a better solution is to use a secure store for the keys, something like Vault.