Hi, in my current C# windows application password has been stored in plain text which is obviously not good. so i just want to know what is the best way to encrypt the password and stored into SQL Server. I have read that using hash+salt is better. but i feel "EncryptByPassPhrase","DecryptByPassPhrase" new feature in sql 2005 is better to use because you are handling everything from SQL Server itself and i suppose it uses triple DES. can somebody suggest is it good to use it ?
A hash & salt is the way to go, because its impossible to retrieve the original password from it. If you encrypt then decrypt the password, the plaintext password is retrievable so its not the best.
I agree it makes sense to have the encryption all in 1 place. However if you separate the key from the data (key in the c# code, data in the db), that will increase security. Also, Sql Server uses a master key when encrypting, which means if you need to restore the data to a new server, you will have trouble restoring the data.
This all comes down to key management and how you want to do this.
Do you need to have access to the original password, or are you just going to try and compare an entered password against one in the database?
If you need access to the original password, then you are going to have to use an encryption algorithm instead of a hash algorithm.
If all you're doing is storing a password in the database so that you can check it later against a known input value, then a hash with a salt will work.
Remember that when the client is sending the credentials across to be validated, that you don't want to be sending the password in clear text!
As with most questions the best answer depends on the context of your situation. There is no good solution.
Some options:
Leave the password in plain text or reversably encrypt. Use SQLServer facilities to encrypt important fields at the RDBMS level or use similiar encryption functions and hope that MS has implemented reasonable key management and the keys are reasonably secure for your purposes. In practice all encryption does is collapse storage of a whole lot of little secrets into storage of one big secret.. It might make the problem more managable but the problem itself never goes away.
Irreversably "Encrypt" the password using a hashing algorithm or some form of crypt(). Depending on the attack vectors available this method may not provide much in the way of actual improvment of security over plaintext storage.
. Use of hashed passwords limits your options in terms of selection of a secure authentication algorithm. With this approach you will likely end up sending plain texts or other material that is no better over a transport (regardless of if unbound encryption is used or not) this can be a substantial risk from a trust POV.
. Succeptable to offline dictionary attack if hashes are stolen recovery of some portion of passwords should be outright assumed if they have any value to an attacker.
. In some cases knowledge of the password hash can be just as bad as knowing the password in terms of system access.
If you are certain that you will never use a hashed scheme to authenticate (like HTTP Digest Auth), hashed password is more secure. To avoid rainbow table attack, please use a nonce (or salt). I would use HMAC-SHA1 and use the nonce as the key. They key must be stored with the password.
Otherwise, you will have to store encrypted password because hashed password can't work with authentication involving hashes. For encryption, I have following suggestions,
- Don't store the key in DB, don't hardcode it either. Store it some other secure place, like using DPAPI on Windows.
- Make sure you have a key version so you can rotate the key to comply with certain standards.
- I am not familiar with the encryption in SQLServer. Make sure it has a random Initial Vector. You can check this by encrypting same password twice, it should yield different ciphertext. If no random IV, don't use it, just encrypt it in your application.