How to save Two Factor Auth TOTP Secret? - encryption

I'm currently developing two factor authentication based on totp. For this you have to generate a secret and save it on the server side and on the client-side (usually through the QR code).
My Question: How do I store it in the database? My requirements are that it's saved secure, preferably encrypted. Hashed doesn't work because I need to be able to have the plain-text value in order to calculate the totp secret code. When I encrypt it, with what key? Should I use a general key? Should I use the password from the user as the key? This would have the disadvantage that when a password reset is done, I can't Decrypt the totp secret key anymore.
Any ideas?

Related

Generate Passphrase for Encryption

I am working on Encrypting some data using AES 128bit encryption algorithm (Symmetric Encryption Algorithm).
Problem I am facing with this is generating a Key ? As I have mutliple Users and I don't want to share the common key across the users.
Is there is any possibility to generate passphrase in such a way that it is not common to all and can be passed to AES to decrypt/Encrypt the same data?
Example:
lets assume I have a table with employee and their salary. I want to encrypt Salary Column of Employee with AES encryption.
Now when Someone authorized from HR wants to see the salary of Employee they can check, but they should have their own Key (not the common Key).
One possible solution is to create an encrypted version of the master key per user.
So you will:
Encrypt your data with a "master key"
Encrypt your "master key" with a "personal key" (one for each user)
Then, when a user provides its personal key, you use it to decrypt the stored and encrypted master key, and then use that to decrypt the data. This way the encryption for the data can be done with always the same key, and you can regulate access with the personal keys.
This assumes though the master key and encrypted data never leave the server, you will have to decrypt on the server and send unencrypted to the user (but of course use a secure line for that, against eavesdropping).
There is no way to do this if you want to send the data to the user encrypted.
Now when Someone authorized from HR wants to see the salary of Employee they can check, but they should have their own Key (not the common Key).
Using symmetric encryption - effectively there is only a single data encryption key (DEK). The DEK can be random and content specific. You cannot have multiple keys to decrypt the same encrypted content.
What is commonly done using asymmetric encryption, when someone authorizes (shares/assigns) an encrypted content to a user, the DEK is re-encrypted by the user's public key, so only an authorized user could decrypt the DEK and then content (though - the DEK is the same for all users).
when user logs in I will ask them Key
To log in the user anyway needs to provide a secret (its user password or other credentials), so - do you really need to go through all the hustle? Isn't enough to encrypt data at REST with some system-specific master key and provide the encrypted content only to an authenticated and authorized user?

Password derived key (i.e PBKDF2) + oAuth2

I have an application that needs to store secrets on behalf of the user. These secrets should be stored securely, but need to be decryptable when the user is present.
Ordinarily I would turn to password based keys (i.e. PBKDF2) to derive the key, however I also have to provide oAuth2 sign in capabilities (with Facebook and Google), which means I don't have a password that I can use to generate the key.
I have tried to find a unique, consistent and secret key that's returned from the oAuth2 providers, but I can't find one.
Are there any approaches that can combine the two? I suspect the answer is no, but wanted to ask just in case.

Saving decryptable password

I know there was question like this million times, but I was unable to find answer that will fit my needs.
I'm building something like small internal password manager for my company, to store login data for various servers and so on.
When new user is registered, his password will be saved in database in salted/hashed version so no one can get access to it (and for that part I think it's all ok, correct me if I'm wrong).
But then, when user is logged in, he is able to add new server with it's login details.
Question is, how to store those.
Because, at some point, I have to present this login details to user in plain text (that is whole point of this application).
Best I could came up with is using some kind of symmetric encryption.
Idea is that app will crypt login details with symmetric encryption and save it in that way into database, and then when data is needed once again will extract data from database, decrypt it with same key and present to user (and key should be in source code of application?).
It could be asymmetric encryption but it's the same if public and private key are stored in same source code, then there is no any benefit of using it?
That doesn't seem too secure, but I can't think of anything better.
Is there any better way to do this, to store this login data?
If it's important to you, application will be in PHP and database is Oracle
I would just use symmetric encryption. The standard steps are:
Derive a symmetric key from a user-supplied password (e.g. PBKDF2 or scrypt)
Encrypt the data using AES-128-CBC or better with a good random IV
HMAC the result (e.g. HMAC_SHA256) or just use AES GCM mode
Store IV+ciphertext+MAC in the database.
This can all run in a browser these days (see crypto-js and aes-js). That way the server never gets to see the plaintext password (not sure if this is a requirement).
The MAC can also serve as a password hash, i.e. if the MAC validation fails, then it means the supplied password is incorrect.

use each user's password as encryption key for his own data

I want to encrypt user's personal data then save them in database .
the encryption must be done in application ( I can't do that in sql server side )
now I wonder if it's possible to use each user's password to encrypt and later decrypt their data ? what are pros and cons of this approach /
One big 'con': what if the user changes his/her password? Then you would need to re-encrypt all data!
You've said that you want to store secure personal data of a user. Doing this unless the personal info. is extremely sensitive is generally NOT recommended for a number of reasons. What is commonly done however is hashing + salting of the user's password.
This page has a good explanation on how hashing and salting works and why it's better than encrypting, and then decrypting the password.
http://net.tutsplus.com/tutorials/php/understanding-hash-functions-and-keeping-passwords-safe/
As for encrypting the user's personal information, just like a password we can use a custom salt + hashing algorithm that's quite simple but effective on our application to use the custom hash equivalent of the userID which is expected to be permanent, static and persistent forever.
Since the uID (or a specialized unique string for every user) can be hidden from normal public and we ensure that our custom shared function cannot be accessed from unauthorized sources, we have a solid secured system.
This means, we hash+salt personal info based on a unique string such as a userID and a hash+salt the user's password aswell. For the personal information to be decrypted, both the userID hash and password hash should match with the database.
A better approach would just be to use known encryption protocols within your program. Data sent via HTTPS TLS for example is quite secure if implemented right.

How can I encrypt user content on my site so that not even I can access the content?

I need to encrypt content in my web application on a per-user basis.
I, the root user, do not want to have access to users' content, period.
How can I make it so users are the only ones with access to their content? Perhaps I can make it so a hash of their login password acts as an encryption and decryption key (then their password is stored one-way hashed in my database, and the encryption/decryption hash is generated from their raw password on login and stored in a local cookie)? But what if they change their password? Then I have to update all their content which could take a lot of processing power.
Is there an encryption method that would provide this, without having to re-encrypt their content if their password changes? Something similar to ecryptfs on Linux, perhaps? Is researching ecryptfs a good place to start?
Is making it so only the user can access their content on my servers (and not even me) even feasible?
Process:
Generate a random secret to encrypt their content.
Using their provided password encrypt the random secret from #1.
Store their password as a one-way hash (with salt, maybe multi-hash).
Upon Password change:
Re-generate the value from step #2.
Re-generate the hash-cache from step #3.
Upon Login:
Hash password and check against hash generated in step #3.
If password matches - use actual provided password to decrypt random secret from #2.
Use random secret from #2 to unlock data encrypted in #1.
Notes:
No one can decode the data without knowing the random secret (#1). Random secret can only be unlocked with user's actual password (#2) (short of brute-force). User's actual password is only known in one-way hashed form (#3) so you can confirm it's the same, but cannot decode it and recover #2.
A forgotten password process is not possible (you can regenerate #3, but random key in #2 is now lost as is everything locked in their vault).
You don't have to re-encrypt everything in step #1 every time they change their password, only the (simple/quick) random secret from #2.
If you cache their provided password, or the random secret generated at step 1, or their (decrypted) content anywhere you could cause data leaks.
You're spot on that you need to use their password as a key.
I wouldn't monkey with ecryptfs because an encrypted file system isn't the best solution. You wouldn't want one user's data to be encrypted with the same key that another user used.
When you encrypt the data, you should generate a random string to use as salt. This prevents someone from using a pre-generated list of hashes to decrypt your data. It also changes the hash of two people who might use the same password.
When a user changes their password, you'll have to re-encrypt the data and generate a new salt value. This is the level of security I would expect as a customer, knowing that when I change my password, I'm re-encrypting all of my data to prevent someone from trying to brute force my key.
You can store the salt value in your database unencrypted.

Resources