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?
Related
I am building an Electron app and implementing Cloud Storage support. Users can upload files within my app to their account. Me, as an admin, I don't want to be able to read the files through the Firebase admin console. I also want to avoid a user password as people might forget it. Just logging into their account should be enough to access their files.
In my prototype I store user files in data/${user.uid}/. But now I am stuck and don't know which password I should use to encrypt the files.
There are a few questions around this topic which involve DigitalOcean which looks too overkill for what I am doing. Is there anything else I could use as a password that is part of the User object that is not exposed anywhere else?
I came across multiple options for Client Side Encryption in File Storage in Firebase. The encryption itself is simple enough to perform with existing libraries, using a symmetric key (a key that can both encrypt data, and decrypt the encrypted data). As the usual problem goes, we now need to find a secure place to store this all-powerful key.
Option 1 : Store Key on User Device
Pros : This stores the key on the user’s device, so the key is never in the application servers.
Cons : The key, and therefore the data, is not accessible from other devices. It’s not a bad solution depending on the use case and situation.
Option 2 : Google Key Management Service for Encryption
Pros : Encrypting the key with another data key stored in Google Key Management Service. The user’s key encrypts the data, and then the key is encrypted by a KMS key and stored in the database. As Andy rightly points out in his blog, that the KMS key belongs to a different Google account to the Firebase database, so no one user has permission to both read the data and decrypt it. A hacker would need to compromise both accounts to access the unencrypted data.
Cons : User has to manage two accounts.
Option 3 : Stash the Key in User’s Google Account
Pros : When the user logs in, we get the OAuth credentials to request the user’s personal encryption key, or create one if we can’t find one, from the user’s Google account. This way, the key is always fully in the user’s possession, but they never have to deal with it directly. Google Drive provides an API for creating a special application data folder (user consent is required during OAuth). The contents of this folder are not visible to the user, and is only accessible via your application’s credentials.
Cons : User has to be cautious not accidentally deleting their own encryption key.
Option 4 : Asymmetric Key Pair
Pros : User first gets the public keys of the recipients. He then generates a symmetric key for himself with which he encodes the file. He then creates a copy of this symmetric key for each recipient and encrypts it with the respective public keys. Finally, he transfers the encrypted copies of the symmetric key together with the encrypted file to the server and stores them there.If another user wants to download the file, he gets it in the encrypted form together with the copy of the symmetric key that is encrypted for him. He can decrypt the latter using his private key and now has the symmetric key with which he can decode the file.
Option 5 : Public and Private Key Encryption
Pros : Create private & public keys for your users when you sign them up. Encrypt data on User 1's device with User 2's public key. Store the encrypted data in your database. When User 2 reads up the encrypted data, his/her private key will be able to decrypt it.
I have to store sensitive data on the server for a web application. The data has to be viewable in plain text later so I can't hash it.
My question is what would be the most secure way to apply the algorithm / where to store my key. I could store it locally on the server or do you have any ideas to store this data as secure as possible while still being able to decrypt it?
We cannot decrypt a cipher text without a key. Hashing is an irreversible process. It wont work in your scenario. There are two types of cryptography techniques: Symmetric and Asymmetric.
Asymmetric cryptography is maintaining two keys for everyone:public key and private key.When you want to communicate with someone, you should encrypt the plain text using their public key and they will decrypt the same using their private key. When they want to communicate with you, they will encrypt the plain text using your public key and you can decrypt the same using your private key. So every party should hold two types of keys.
Symmetric Cryptography is maintaining a single key for a communication. The single key will encrypt and decrypt the data. When two parties wants to communicate, they should have a shared secret key (common key). When you want to communicate, you can encrypt the plain text using the key and they will convert back the cipher into plain text using the same key.
In your scenario, you can use Symmetric cryptography techniques such as AES,DES etc., You can maintain a separate key for every user. You can use that key for encryption and decryption. The keys can be stored in another database. whenever you want to display the password in plain text, you can take the key for the user and decrypt it using the same cryptographic technique.
I would like to AES encrypt some users profiles info.
When a user registers, I use the password he provides, I compleate it to 16 bits with zeros to have the required key lenght (16 bit) for AES if the password does not have 16 in lenght, then I encrypt all his data profile with that key. I know that at this point my AES keys will be secure because no one knows them except the users them selves.
When a user logs in, I take his password do the same 16 bit process and decrypt his data. The problem I have is with password recovery, if the user forget his password, the data is lost forever. Is there a better way or a work around this issue?
Thanks.
Your AES key "derivation" is not secure, you should use password hashing (or, to be more precise, use a password based key derivation function - PBKDF) instead of padding with zero's. A password is not the same thing as a key, which should consists of 128 or more randomized bits.
Instead of recovering the key (or password) you could encrypt your data with a random data key. Then you can in turn encrypt this data key with the key of the user. You can additionally encrypt the data key using a public (RSA) key, of which you keep the private key safe on detached storage or somewhere in the back office. The encryption of one key with another key is called key wrapping.
Some data you may want to keep private to the user, in that case simply do not encrypt with the public key in the back office. You could possibly encrypt this kind of data at the location of the user instead of on your server.
What encryption algorithm can use 2 keys:
admin - encrypt & decrypt
and
user - only decrypt ?
You can do this with RSA by using the private key for encryption (as if you would be signing). The tuple (d,n) would be the admin key (normally named private key), (e,n) would be the user key (normally named public key). The admin key is used for encryption, the user key for decryption. Only the admin is in possession of the admin key, while both the user and the admin know the user key. Now only the admin can encrypt, while the user can only decrypt.
Note that I deliberately chose the exponent d for the encrypting admin key and not vice-versa, because e is usually chosen to be very small for better performance, and if you'd do that with the admin key instead of the user key, then the system would be broken.
Note that if you construct a hybrid system for this, the desired decrypt-only property breaks, because the user can get to the symmetrical session key as well and modify the message.
I suspect you might want the decrypt-only property to actually achieve authentication of potentially large amounts of encrypted data (i.e. so that the user knows the data must come from the admin and has not been tampered with). If so, what you really need is a more complex scheme with a proper digital signature (providing authentication) and some form of encryption for confidentiality, e.g. hybrid using a symmetrical cipher for bulk encryption and e.g. RSA for encryption of the symmetrical key.
However, you should be very careful when designing cryptographic systems like this, there are a lot of things which can go wrong and completely compromise the security of your system. Seek expert advice.
Edit: This is incorrect (see Daniel's comment).
You can modify any algorithm to allow two keys by generating a session key, using that to encrypt the payload, then using the two keys to each encrypt the session key.
For example, if Ak is the admin key, Uk is the user's key, Sk is a random session key, and e(k, p) is a symmetric encryption function, then you would use:
ciphertext = e(Ak, Sk) . e(Uk, Sk) . e(Sk, p)
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.