So I need to be able to actually decrypt the password because some old websites don't use OAuth and I need to have some of my users have access to them through there API. Therefore one way hashing does not work for me. I have been told that the best way to store the passwords with AES and using the salted hash of the passwords as the key. How do I store all the keys and where do I store the salt? Basically how would I exactly implement this.
Thank You
If I understand you correctly you have the following situation. Users log in to your system with a username and password. Your system then needs to impersonate these users by logging into another system that you do not control using the user's username and password for that system which they have given to you.
If that is correct, then it might be reasonable to encrypt their credentials for the other websites using AES. In this case, I would not store the key used to encrypt those crendentials. The password that the user uses to access your system should be used as the key, and it should not be stored anywhere. In this way, you have a chance of protecting your users privacy (depending on the design of the rest of the system, of course).
Since you are encrypting rather than hashing, and the encryption key would be differnet for each user, salting is not necessary.
Also, I would encrypt the full credentials, not just the passwords. Your users are showing an incredible amount of trust by giving you their credentials in the first place, so I would do everything possible to justify that trust!
Your approach is essentially to use AES as a hash function but this will not allow you to decrypt the passwords (short of brute force or some yet-to-be-discovered vulnerability).
You might want to consider asymetric key encryption instead (e.g. RSA). You'll need to encrypt the passwords with the public key of each person you expect would need to decrypt it (which would include the user).
Related
So basically I'm developing a service that requires plain text input of user and password from the user.
The main server won't ever need to decrypt the password, so it should encrypt the user password with the public key and store it to DB.
Consuming service, which does web scraping needs the password as plain text to be able to authenticate.
And uses a private key for decryption.
I'm wondering whats the best practice to store the cert, I tried to base64 encrypt the key and use it from env. But something is getting corrupted at times. And being unable to decrypt the password.
Any advice on how to handle it is helpful
Wouldn't worry so much about obfuscating the key. Just make sure the server its on is secured, and limit access to the key via permissions and users which have access to that account. If it were a service account with no login ability, that would be better. If you need to reproduce this concept multiple times, use different key/cert for each unique use of this process to limit the exposure if there is a compromise. I'm sure there will be more good responses... let them stack up and see which mix best suits your use case.
Best practice it to hash passwords and store the hashes. When a user logs in, hash their input and compare its value to the hash you already have stored. In this manner a compromise only reveals the hashes, not the actual passwords. There are rainbow tables to crack hashes, but that's a topic for another day.
I'm building a system that connects to a third party api, and I have to store passwords for each of our users connected to that api. I need to make sure that the passwords are stored securely, so I don't want to trust the user's password as an encryption key. But I also need to make sure that we need the user to authenticate the use of this password, by entering their password.
I had the idea of creating a key by combining the user's id and password with a secret key on the server (just by concatenating them all). I then use crypto's createCipher with aes256 and the new generated key to encrypt the third party password and send it off to storage.
I noticed the text in the createCipher documentation that says this:
In line with OpenSSL's recommendation to use pbkdf2 instead of EVP_BytesToKey it is recommended that developers derive a key and IV on their own using crypto.pbkdf2() and to use crypto.createCipheriv() to create the Cipher object.
And I read up about IVs and the attacks they are meant to prevent (still pretty confused about how that works, especially with my use case) but I think that since this will technically be using a different key every time, that will be a non-issue.
Is this kosher? Is there some vulnerability of this system that I'm missing?
I have the need to store private keys for multiple users, so that my server application can sign files on their behalf.
I want to store the private keys securely, but I couldn't find best practices around this. If I was storing a password I would salt+hash the password to make a hash that can't be easily turned back into the password. However, with a private key I need to store it in a way I can later retrieve it.
I was thinking I would encrypt the private key and then store it in my database. I originally thought each key would be encrypted with a different password (based on some properties of the user). However, those properties would most likely be stored in the database, so if my database got leaked then the attacker has everything.
I could encrypt all private keys with a single password that is only known to my application. Then an attacker would have to steal my database, and my application to do any harm.
Is there a technique/best practice I'm missing?
You could encrypt the private key with a symmetric key based on the users password. Simply store an additional salt and perform the password "hash" to get a separate key. Then use that as key for encrypting the private key. Note that it is required to use a Password Based Key Derivation Function (PBKDF) such as PBKDF2, bcrypt or scrypt to create a secure password hash (given the normal security level of a password).
If the user is not online at the time that a signature needs to be generated, then you should indeed protect the passwords in a sense that only you / our backoffice can decrypt the keys. You can use some user ID + your own secret key to calculate an encryption/decryption key. You may even want to generate a separate RSA key pair to perform hybrid encryption decryption.
Storing private keys on behalf of users is a very dangerous practice. There are a lot of ways for the private key to become exposed (e.g. side channel attacks). To do it professionally you should really be using an HSM somewhere in the process. If this is for any serious data, please consult a professional and a lawyer.
I am developing a website that will allow two factor authentication using Google Authenticator. My question is: what is the best way to store users' secret keys? If I keep it in a database and it is hacked then the attacker would be able to generate one time passwords. And I cannot encrypt it like passwords with one-way encryption because I need this secret seed to generate one-time passwords.
You could store it in a secure token (smart card), but then you will have to configure access to that secure token - which brings you back to your original problem. If you are able to perform an action before starting up your application then you can use Password Based Encryption to protect (wrap) the secret key. Or you could require a PIN for the smart card holding the key. USB-memory cards could also be used to permanently store the key (don't forget that backup).
Obviously it is a good idea to protect access to your application in the first place. You may still need the key in memory at some point of time, so an attacker would be able to fish it out if that memory is not protected.
Another method often used it to obfuscate the key. But a determined hacker will usually not have too much trouble retrieving the key whichever way the obfuscation is done.
There are a lot of questions on Stack Overflow about how to store user passwords, and the general advice of course is to hash the passwords and compare hashes.
However, imagine you are building a shrinkwrap intranet application (like SharePoint) that people deploy in their own environments. And suppose it requires a username/password combination to access an external service via HTTP (solutions that rely on API keys or federated security aren't supported).
In this case, we can't hash the password because we will need to pass the original password to the web service that we call. Encrypting would be the second best solution, but what would we use for the encryption key? If an attacked compromised the database, presumably they would have access to whatever key is used to encrypt the data in the first place?
If it was really a requirement for you to get the plain-text version of a stored password, how would you approach the problem in the most secure way?
This is actually a really interesting question. I'll join in.
You should encrypt it when storing it. No matter how you look at it it's better than storing it in plain text. Let's say an attacker finds an sql injection ad dumps the db, he still don't hold the encryption key. On the other hand, if he gets access to the server he will probably also find the encryption key.
To improve it a bit, you could store the encryption key in the server configuration. Assuming you are using Apache, you could use SetEnv.
I in my environment are required to enter the encryption key when Apache starts, this is then stored as en environment variable, so the key isn't really stored anywhere on my server.
There is no way, unless you require the user to enter a key to decrypt the password that you will be 100% safe.
You could generate the encryption key from the user's password. (Not their password for the external service—their password for your service.) Since you're not storing their password in plain text, an attacker who compromised your database wouldn't be able to decrypt the passwords. The downside is that you have to ask them for their password (for your service) whenever you need their external password.
You have the question inverted. The problem is not how to let the consumer "view" the password; the problem is how to let the consumer verify authentication.
In your implementation provide a means by which the consumer can provide a password and a username and get either a yes or a no. Then you continue to store encrypted (not hashed) passwords in the database.