Most secure way to temporarily store a password - security

I have the following use case:
My web application is used for creating prescriptions. When I send the prescription creation request to the government API it is signed with the current user's certificate. The certificate is stored on the application server and is encrypted with a password which only the user knows.
Users want to be able to store their password in my app temporarily so that they don't need to paste it in for each prescription they create.
What would be the most secure way to store this password? Couple of ideas:
Local storage in the browser.
Bad because anyone with an access to the user's device can see the
password even if they're not logged in. Also if the app is not running I have no way to clear the password if the desired storage time expires.
Frontend app memory.
Bad because if user refreshes the page or opens another tab the stored password is gone.
Backend, in database
This sounds like the best option because I can encrypt the password. Is it even worth encrypting though? I would have to encrypt it with some key stored on the same machine so if someone gains access to this machine the encryption doesn't matter because they would be able to decrypt it quite easily.

Separate the password encryption key and the encrypted password:
Generate and store a random key (and nonce / salt)
Encrypt the password (e.g. AES-256-GCM) with the random key
Store the encrypted password on your backend
Send the random key with the request to temporarily decrypt the password
Delete the encrypted password on the backend when the session expires
That way:
The random key stored in the browser can only be used within the current user session and is useless on its own
The encrypted password on your backed can only be used with the random key stored in the browser and is useless on its own

Related

Can you send a hashed password back to the user in plain text?

So I am dealing with a website concern, I am a intermediate level programmer and I was shopping on a website that I have heard other friends use. When I signed up for my account, they sent me my password back in plain text to my email. I always thought that in a html form, if you hashed a password and sent it to the server, there would be no way of sending a password back in plain text. I am assuming the website I made the account is hashing the password, but I have no way of knowing. I'm not a security expert or anything, but I am pretty sure they aren't hashing the password and probably storing my data in plain text on their servers. Is my conclusion correct?
If your password is sent to you during the registration process, it can be that it's sent right when the server receives it and still has it plaintext, and then it gets hashed and stored properly.
This would still not be the best practice though, cleartext passwords should not be sent over insecure channels, like in email.
Of course in this case it's not possible for them to send it again in another request. If that happens, that really means they are not storing it hashed.
If it's properly hashed and secure they should not be able to see it in plaintext. If they could access it easily then so could hackers.
There is another way to store the passwords, encryption. In this way, the application server stores an encryption key to encrypt users' passwords and store them on the database.
When users try to login, they encrypt the new incoming password of the login attempt to see that it is matching.
In case of lost of the passwords, they can send users' password back to them by decrypting it using the key on the application server.
If the application server is compromised, the attackers can access all passwords as the same way the application server does.
By no means, they should send back to users, their passwords. If users don't remember, they have to force users generate into a new one.
For more discussion see Difference between Hashing a Password and Encrypting it

On a local application that stores one set of user credentials, is password salting necessary? Why/Why not?

I've heard a unique salt only provides protection in the event that you have a lot of user credentials stored in the same location. Is there any benefit to salting on a single user application where the password is never sent to the web? Thanks!
Password hashing is used if you don't need to retrieve the original password. For example a website with a account system will hash your password when you register and save the hash of the password in a database. When you login the next time it will again hash the password you entered and compare it to the hash stored in the database. You can use salting to make it even harder to retrieve the original password.
You have a different use case. You want to retrieve the password to be able to decrypt the data that you recieve from the server. To achieve that you have a view options:
Generate a key for the user and store it in plaintext on the disk.
Don't store the password at all but let the user enter it each time he wants to access the data on the server or upload data to the server (potentially store it in memory, you should make sure to completely erease it from memory bevore the program ends).
Generate a key for the user and store on the disk like in option 1 but encrypt it with a password thats handled like the password from option 2.
The 3rd option is definitely the safest of them. You have control over the key generation so you can make sure the key has a decent size to make it impossible for the server to guess while the key is encrypted on the disk.

Securing a Temporary Access Key for Encrypted Data

I am building a secure data store that can share secure information between a number of authenticated users, as well as letting unauthenticated users check data into the secure data store without making it public or divulging its contents.
Currently, the data is encrypted with a 1024-bit key, and has an associated RSA (2048-bit) Key Pair (with the Private Key being encrypted by the 1024-bit key). This means that if people want to check data in, then can use the RSA keys.
The 1024-bit key is also encrypted using User Secrets that are specific to each user, completely private, and randomly generated at the onset (or reset when requested). This means that the users can access the data without the key being public.
The final bit is storing the Users Secret. The secret itself is encrypted using another RSA (also with a 2048-bit key) Key Pair. The Public Key is associated with the user, and the Private Key is encrypted using their login Password.
When it comes to actually logging in, the user's username and password is validated, then a unique token is returned to the browser that will authorize it as a specific user.
At the login point, if it's valid, the password will be used to decrypt the RSA private key, so that the User Secret can be recovered.
But the user's password is only available to the system at one time, so I was going to use that moment to get the Users Secret and store it somewhere where it is available to the current login session, but no-one else.
Although I could store it in a separate database that would encrypt it (lets say with the Access Token) that would be lost when the user signs out, my worry is that if someone tries to break into the system when someone is logged in, they could recover the secret, and therefore, the rest of the data.
Does anyone have any ideas or references to implementations that can protect the User Secret from access by everyone except for the Session?

Store email account's password

I'm developing an email client in PHP for IMAP accounts. Which would be the most secure way to store the account's password being able to retrieve it afterward to check emails?
I guess I should encrypt it somehow. However, how can I make sure that only my app will be able to decrypt it?
If you require login without any user interactions, then there is no secure solution. You'll need to rely on your OS's storage options which might prevent hostile unprivileged applications from reading the password.
If the user entering a single password on startup is fine, then you can encrypt the other passwords with symmetric encryption, and then use a KDF, such as scrypt or PBKDF2 to derive the master key from the password (and a salt).
Store the passwords in an encrypted file; require the decryption key when starting the app.

How to obtain two independent passwords from a single string?

I'm not sure the title is accurate, please feel free to rename the question if appropriate.
I'm thinking about a service that stores sensitive data on a remote server. For maximum privacy, the data would be encrypted on the client (using AES) and the encryption key not stored in any place, so that should the server be compromised, sensitive data would still be relatively safe.
Now the problem is, I need a second password to access the service, but this second password must be stored somewhere on the server.
This would be what happens when a user registers:
user picks a username/password (Password A) and an encryption key (Password B).
hash(Password A) is stored on the server
Password B isn't stored anywhere.
then:
user enters Password A => Password A is transmitted to the server
server checks hash(Password A) against the user db, grants access
client downloads preferences and encrypted data
User enters Password B -> encrypted data is decrypted (locally).
This looks good to me, but the drawback is that the user needs two distinct passwords. This is impractical and also carries the risk that users pick the same string for both, strongly reducing the model's effectiveness.
What I would like is to use two independent passwords but only ask the user a single one.
First attempt
The first idea I had is to ask the user a password, then split it in two and use the first part as service credentials (Password A) while the second part would be the encryption key (Password B).
This has the drawback of reducing the strength of the passwords: if the user-provided string is already weak/short, Password A and Password B would be even weaker.
Second attempt
Another option: use the user-provided password as encryption key (Password B) and use a hash (SHA-256) of that password as service credentials.
Registration:
user picks a single password PASS
hash(PASS) is transmitted to the server
server stores hash(hash(PASS)) with username in the user db
Then:
user enters PASS
service sends Password A = hash(PASS) to the server
server checks hash(Password A) against the user db, grants access
client downloads preferences and encrypted data
client decrypts encrypted data with Password B = PASS.
This means that
a hash of the encryption password travels over the network 2) a
a hash(hash(encryption key)) is now stored on the server, i.e. alongside the encrypted data
Does this significantly reduces the security of the system? I.e. when an attacker gains access to the server, is it easier to decrypt the sensitive data when knowing hash(hash(encryption key))?
Is there another (better) way to get two independent passwords starting from a single string?
I would go a different approach. Using openid to authenticate to your system. This way you do not have to transmit a password to your server at all.
On your first approach, you should only transmit the hash.
If I remember correctly, LastPass uses this system:
User enters email address and password
Password is hashed and the hash used as key to encrypt the user's sensitive data
Password hash + email is hashed into a second password which is used to log into the server and upload the encrypted data blob
I may have it backwards which hash is used for which, but it sounds like you want something very similar. The whole thing was explained in detail in Security Now #256, if you're interested.
The advice to use a secure password scheme is correct. What you might want to do is to make a small change before passing the user's text to the password scheme. If the user enters "password" then pass "passwordLOCAL" to the local password scheme and "passwordREMOTE" to the remote password scheme.
That allows the user to enter a single password yet still have two different local and remote passwords. Don't actually use "LOCAL" and "REMOTE" of course, far too insecure. Use two different random strings, much like two different salts.
As suggested by #Tim in his answer - do not create a new user authentification scheme (your own user-id & password combination).
Based on what you are building this for, you basically have 2 options:
If this in an corporate internal application just integrate to Active Directory or whatever internal user database and authentication backend you have
If this is public, use OpenID (if you need just authentication) or OAuth if you also need authorization.
Please note that your application does not have to be web based in order to use them. (You do need internet access, though). See this question for details
For the encryption keys, use some sort of Key Derivation Function (also known as PRF+) for the key derivation - preferably with other components as well. Feed the PRF/KDF for example the following (concatenated):
User's unique identifier from the authenticator (OpenID, AD, whatever)
a system-wide application identifier string (e.g Francescos secureapp keypad)
per user random data stored with the user information (e.g. 16 bytes from the system random source)
user's encryption password - this is the single password you have to care about.
This is somewhat similar to AUTH payload calculation in the IKEv2 protocol
This way the potential attacker would need to access bits of information from various locations in order to be able to decrypt user's sensitive data.
Also, don't store the user's encryption password on the server side. The client should always ask it (or cache it for certain amount of time) from the user and send it (in plain or hashed) over an encrypted channel to the server whenever requesting something that needs [en|de]cryption.
Furthermore, if you want to enforce some sort of a password policy on the encryption passwords, see this comic and this answer for reference how it should be done.
You could generate and store an IV (or two, if needed) on the server, and send it to the client to HMAC. This produces the encryption keys that are needed.

Resources