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.
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'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?
I have a firebase powered app. The requirement is to update the account password by typing the currentPassword and the newPassword.
On the server (firebase cloud function + admin sdk) i need to check if the provided currentPassword is valid.
When an account is created for the first time, firebase automatically encrypts the password, and gives me back only the hash.
The problem is - this encryption is done automatically, under the covers.
Without having access to the encryption method, i can't obtain the hash of the currentPassword in order to compare it to the stored hash of the real password.. to see if this 2 hashes match.
So how can i check if the currentPassword is valid? How to get access to the same method firebase-auth uses for encryption?
I coudn't find anything relevant so far. am I using the wrong approach here? Why is it so hard to find it ?
I'm not quite sure that you can verify the password with cloud function, the point is to make sure that hackers would not be able to recover users' passwords even if they somehow hacked into the server, if you can recover the passwords by knowing the hash and salt, why wouldn't them hackers? However, you can do that in your app:
firebase.auth().currentUser.reauthenticateWithCredential(firebase.auth.EmailAuthProvider.credential(firebase.auth().currentUser.email, oldPassword);
Also, just to provide an alternative way for users who want to change their password, just send them a reset password email, this way, it's quite safe and they won't have to enter their old password:
firebase.auth().sendPasswordResetEmail(firebase.auth().currentUser.email)
passwordHash and passwordSalt are only available when you retrieve the user information via a call to listUsers(). Therefore they are only useful if you ever migrate user data from Firebase Auth to a different user management system.
For this use-case i needed to implemented 2 different approaches.
case 1: when the agent changes it's own password.
I use browser code as provided by #K.Wu - firebase automatically sends a password reset email to the user.
firebase.auth().sendPasswordResetEmail(firebase.auth().currentUser.email)
case 2: when a high privilege user: admin / manager changes the agent password
I use server code - firebase admin sdk. Here the manager doesn't know the currentPassword, and doesn't need to know since the firebase-admin can change account passwords without needing to send confirmation emails.
Still, What i don't uninterested is this:
When i create the user for the first time, firebase gives me a userRecord object which has 2 properties: passwordHash, and passwordSalt. But since i can't encrypt a given password manually, then what is the use of this 2 properties? When are they ever needed?
I considered them being specifically designed for when you compare the hash of a provided password - with this passwordHash that is stored in firebase. Seems this is not the case, and I'm still confused a bit.
Anyway splitting the password update functionality between client and server, based on who performs the action, as explained above - worked like a charm.
note: also this setup allows for the account creation to be done by admin / manager.
I think you can check against the password hash with scrypt. You need to download the scrypt config from account and compare. Please check the below docs
https://firebaseopensource.com/projects/firebase/scrypt/
Util function for scrypt if found here for hashing and verification
https://github.com/xeewi/firebase-scrypt
Note: Only listUsers() method will return the passwordHash. getUser() or no other function will return the passwordHash values.
Given is a ServiceStack REST Service that can sign documents with one of the public/private key algorithm. The prvate key is encrypted using a passphrase only the admin of this privat/public key pair knows.
Know it should be possible that other logins then the admin can sign documents (authorized by roles, permissions, etc.)
Currently they need to provide the passphrase for the private key in every signature request as the service needs to decrypt the private key and sign the document.
But i dont want to give the private key passphrase to other users and i also don't like to send it on every request over the wire.
So what is the best way to store the passphrase on the service side so that authorized logins can sign documents without knowing and sending the passphrase.
Is there a possibility to store it (automatically encrypted/decrypted from ServiceStack) in the user's session/UserAuth object?
Or is there are any other solution? It should work on .net and mono.
I'd recommend you look at Microsoft's guidance on encrypting/decrypting config sections. This way you can store it encrypted in web.config and your back end service can have access to it.
See http://msdn.microsoft.com/en-us/library/zhhddkxy(v=vs.100).aspx
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.