tags:

views:

2117

answers:

15

I want my application to save the password encrypted in a DB or in a text file. How can I do that assuming that the DB or text file can be open by anyone.

Duplicate

http://stackoverflow.com/questions/287517/encrypting-hashing-plain-text-passwords-in-database

Not duplicate I'm asking for code specific for .NET

EDIT: I'm saving the password for later use, i need to decode it and use it to login. It doesn't have to be super secure, It just needs to be unreadable to the human eye, and difficult to decode with a trivial script.

A: 

Like ocdecio I would use TripleDes, I would also save the salt in the database too. The key for me is usually hard coded, but the salt should change for each encrypted item.

David Basarab
the salt should be algorithmically dependant on the item, but not stored
annakata
If the salt is algorithmically dependent on the item, then it is useless. The purposes of a salt is to make it hard to break several passwords at once. If the salt is dependent on the item, the resulting hash will be the same for two equal strings, which is exactly what a salt is supposed to prevent
Zuu
+1  A: 

do you need to encrypt it ever again? otherwise use a hashfunction to encrypt it and encrypt the password given by the user with the same hashfunction and look if the hashes are equal.

The reason for not using a 2-way-encryption is that one cannot decrypt your key - since a good hashfunction has collisions.

Gambrinus
+9  A: 

Triple DES is one way to do it, as long as you mean "A password that my system needs to be able to recall in order to access a resource". If you mean the password is something a user needs to be able to gain access to your system, probably don't want encryption, just a hash will do. When you store the hashed password value, it is useless to anyone with direct database access, but can still be used for authentication. All you do is compare the stored hash against a hash of the incoming password. If they match, then you grant access.

It isn't perfect, by any means, but it is the way 99.999% of people store their passwords.

If you want to argue that you wish to provide the password back to a user if they lose/forget it, then please don't. Issue them with a temporary password (which you store hashed in the db) and get them to change it on first login.

ZombieSheep
Why all the 3DES fanboys? Isn't AES modern, faster and more secure?
joeforker
Exactly so, 3DES is dead outside of the old online transaction companies
annakata
(addendum: but stored passwords should generally be a hash not an encryption anyway)
annakata
@annakata - That's what I said. <confused />
ZombieSheep
@ZombieSheep we expect you to say "TripleDES is not a good way to do it because it is obsolete and shouldn't even be mentioned to n00bs as a valid choice".
joeforker
@joeforker, +1. Its not 2002 anymore... AES is the (almost) only real choice. (I say almost, cuz well, there are others... Blowfish is still in use ;) ) But anyway 3des is loooong out of date. Unless you're still coding in COBOL anyway... ;-)
AviD
@joeforker and @AviD - while your points are valid, the jist of my answer was essentially "You can use 3DES, but don't - use a hash instead" I guess it wasn't worded adequately. I'm not going to edit it now, though - the comments here should be enough to clarify my position.
ZombieSheep
@ZombieSheep except he modified his question to make clear he needs to recover the plaintext later... but hopefully the hashing technique will be useful for someone else.
joeforker
A: 

If you just need the password for an internal authentication process, you should not save the actual password, but save a hash of this password. When you need to check if a password is valid, you'll have to run the hash function on provided password and compare it with the hash you stored in your database/file. You can never find the original password from the hash.

If you need to keep the original password, you'll have to encrypt it. You can use for example a public key infrastructure if you have a process that writes the passwords (public key) and another one that reads them (private key).

ybo
A: 

Do you really need to be able to retrieve the password itself? If you're storing a password for the purposes of authenticating someone (or something), you should rather hash it (with salting) and then compare that hash to the hash of the password supplied by the party wishing to be authenticated.

If, on the other hand, you need to store the password in order to be able to retrieve it and supply it to some other authentication service later, then you might want to store it encrypted. In that case, use any decent symmetrical encryption algorithm you can, such as TripleDES or AES or Blowfish.

Vojislav Stojkovic
+4  A: 

If you use encryption for securely storing passwords, you'll need to store the encryption "key" somewhere, too. This will be the "weak link", since if someone gets hold of the encryption key, they will be able to decrypt the encrypted passwords.

Since this is passwords that we're talking about here, a much better solution is to use a one-way hash. You hash the password when the user first creates it (preferably hashing with a salt value) and store the resulting hash value. Since hashes are one-way, no one can reverse the hash to the original plain text value.

To check that a users password is correct, you simply ask the user for the plain-text password, hash their input again and compare the resulting hash value with the hash value you have stored (taking salts into account of course). If the two hash values are the same, the user has entered the correct password.

Please see the following links for further info: Hashing Password with Salt

For encryption (if you need to use that), I'd use Rijndael (AES).

CraigTP
On the other hand, the linked code is horribly long-winded.
joeforker
If security is a concern, having an ever-changing salt increases security. I don't think the linked code is long-winded considering it uses ever-changing salt values and allows multiple hash algorithms and also includes functionality to validate/verify a hash. It's a good all-purpose hash class.
CraigTP
@CraigTP unfortunately for your answer, Svish's answer 'BCrypt' is correct and all the other answers are wrong. Read the article in my comment and you will be forced to agree.
joeforker
@joeforker - I am aware of BCrypt. Nothing wrong with it and it's based on the Blowfish algorithm, so should be very secure. However, you agree with the BCrypt answer and you think the code that *I* linked to is horribly long winded?
CraigTP
@CraigTP BCrypt.cs is long because it does a lot, your link is long because it was written by morons who comment every single line. From the code: "(if any other value is specified MD5 hashing algorithm will be used)". In other words "DO NOT USE THIS LIBRARY BECAUSE WE ARE MORONS". QED. Sorry Craig.
joeforker
@joe - There's a lot of comments because it's *example* code. I don't think it's moronic since it has the same security as BCrypt (ie. nonce values etc.), but uses .NET's built in hash algorithms rather being based on the Blowfish algorithm. After all, the original question wanted .NET code.
CraigTP
@CraigTP nonce values are so 1976. BCrypt is better because it's been pessimized to be SLOW to disadvantage the attacker and it gets slower with a single parameter, at least run the salted hash a few thousand times! BCrypt.cs is C# how much more .NET can you want?
joeforker
An MD5 default proves the implementer doesn't know about security, comments or not, but the worse offense is only running MD5 once. Please read the 'Enough With The Rainbow Tables' article.
joeforker
the answer gets +1 because it talks about hash over encryption and doesn't say "3DES"
annakata
+13  A: 

BCrypt - Strong Password Hashing for .NET and Mono

Svish
+1 Best answer by an order of magnitude. Read http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/ and you'll know why this is the correct answer.
joeforker
A: 

Briefly:

Get a big random number which you will keep private and only your application code will have access to.

Encrypt the password + random number with an ancryption algorithm like SHA1, most programming languages have a cryptography framework.

Store the hashed password.

Later when you want to check inputted passwords, you can rehash the user input and compare to the "virtually" undecipherable stored passwords.

Matthew
+19  A: 

StackOverflow readers don't know how to write secure password schemes and neither do you. If you're going to do that, save time by sticking with plain text. From Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes:

Rainbow tables are easy to beat. For each password, generate a random number (a nonce). Hash the password with the nonce, and store both the hash and the nonce. The server has enough information to verify passwords (the nonce is stored in the clear). But even with a small random value, say, 16 bits, rainbow tables are infeasible: there are now 65,536 “variants” of each hash, and instead of 300 billion rainbow table entries, you need quadrillions. The nonce in this scheme is called a “salt”.

Cool, huh? Yeah, and Unix crypt —- almost the lowest common denominator in security systems —- has had this feature since 1976. If this is news to you, you shouldn’t be designing password systems. Use someone else’s good one.

Use BCrypt - Strong Password Hashing for .NET and Mono. It's a single cleanly written .cs file that will continue to meet your needs as password cracking computers get faster.

joeforker
+8  A: 

Use Data Protection API either with the user or machine store (e.g. different key per account your program/database server runs under vs. one key per machine). This will help you decode the passwords later and you don't have to remember or store any encryption keys. The downside of it is that when you reinstall the system/delete the account you won't be able to recover the data, I believe.

liggett78
+2  A: 

Based on your question I can see two approaches depending on why you are storing the password.

A. if you only need to authenticate using their password and nothing else.

In that case, going using an algorithm that is not reversible (Hashing) would be your best choice. You will need to make sure of a couple of things:

  1. Make sure that the connection is encrypted when transmitting the password from the client to the server. This will prevent it from being sniffed out. This is pretty trivial to do with web applications since the web server is doing the heavy lifting for you. If not it gets a lot tricker and is the subject of an whole other question.

  2. Choose a solid hashing algorithm to prevent collision. I would recommend SHA-256 even if it does provide a larger result than SHA1 or MD5. The reference from Microsoft on using their implementation of the algorythm is here.

  3. Salt the password to prevent attacks using rainbowtable (i.e. looking up the password in large table with the precomputed hash and the associated password in clear text). The answer here (sited in your question) gives good pseudo code in Python on how to do it. There is also a good example of .NET code here.

B. if you need to be able to read the password for each user for other purposes than authenticating the user.

This case is easy if we are only talking about storing a password (or any kind of sensitive information) on a single computer (server). If that's the case, using the Microsoft Data Protection API would be a good solution since it is tied to that computer and (depending on the way you work) the user under which you application runs and takes care of the worst of the job for you (creating, storing, and using keys). You can find some code reference from Microsoft here. If you need it on more than one system and are not willing to enter the password on each system you install on your application then things get a lot more complex because you need to implement a lot of it from scratch. That would be the subject for another question I would think.

Pierre-Luc Simard
A: 

Here's a string encryption article with example code .NET

http://www.devarticles.com/c/a/VB.Net/String-Encryption-With-Visual-Basic-.NET/3/

There is no need to use anything fancy, because anyone with a little bit of skill and determination will break it anyway.

abababa22
A: 

Personally, I would use something that has one-way encryption - MD5, SHA1, etc...

You can use the FormsAuthentication class with it's HashPasswordForStoringInConfigFile method. When validating the user, encrypt the entered password and compare it with the stored version.

Kieron
+2  A: 

If you need to decrypt the password for later use and it doesn't have to be SUPER secure, then use the method here:

http://support.microsoft.com/kb/307010

It's well documented, and easy to understand.

Craig O
A: 

there is a library that does that: http://encrypto.codeplex.com/

Omu