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)
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 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?
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.
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.