I am storing user logon encrypted passwords in a database (SQL Server). Because of an API restriction, the passwords need to be encrypted on the C# end of things, so I can't use the database's built-in encryption. what is the fastest/easiest way to encrypt these passwords so I can compare them to what the user would have typed in to a third-party service later?
I am new to C# and I understand that passwords should never be in plain text so that's why I want to make sure I have the highest security. I have tried using the RSA.EncryptValue() function but I'm pretty lost as to how to use it correctly.
Any help is appreciated - thanks in advance.
-Jimmy
You don't want to encrypt and store passwords. You want to generate a hash and store that. Then, when a user is logging in, you regenerate the hash and compare it to the one stored in the database.
The answers to this question provide examples of how one might hash a password in c# (one answer includes information on doing a "salted" hash).
Firstly dont encrypt; hash.
Secondly dont encrypt; hash.
A password should never be recoverable.
I'd advise reading...
http://www.troyhunt.com/2010/05/owasp-top-10-for-net-developers-part-1.html
front to back.
You should salt your passwords and hash using a decent hashing algorithm; take SHA512 for the low end, or if your serious about protecting that data look at something more along the lines of BCrypt http://code.google.com/p/bcryptnet/
The point in hashing rather than encrypting isn't to secure your site against brute force attacks, but more importantly, is to secure your users against data loss.
i.e.
http://www.bbc.co.uk/news/technology-11998648 - Gawker
https://www.google.co.uk/search?sourceid=chrome&ie=UTF-8&q=sony+hacked
People put allot of trust in the hands of web developers taking care of their, often pathetic, passwords. Taking good care of them can make a hell of a lot of difference.
With BCrypt you set a workfactor to the salting; I would also add a database salt (see the troy hunt membership provider article on how MSFT does it) to increase the original password value.
Example from the BCrypt site (BCrypt.net is also a NUGET package)
// Pass a logRounds parameter to GenerateSalt to explicitly specify the
// amount of resources required to check the password. The work factor
// increases exponentially, so each increment is twice as much work. If
// omitted, a default of 10 is used.
string hashed = BCrypt.HashPassword(password);
// Check the password.
bool matches = BCrypt.CheckPassword(candidate, hashed);
Hope thats been of use.
You can of course use the built in forms authentication encryption system to encrypt/decrypt your data. Though it's somewhere between daft and dangerous to encrypt passwords.
http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.encrypt.aspx
http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.decrypt.aspx
You'd also need to add a machineKey tag to your web config, microsoft provides a generator for this; http://aspnetresources.com/tools/machineKey The tool creates a 256-bit decryption key and a 512-bit validation key, with Rijndael as the data validation algorithm.
And if you DO NEED (as in you'll be shot if you don't) to start throwing plaintext passwords around, for all that is holy, check the service is restricting by IP (IPSec) and please, dear god, use SSL.
Like Steve Wellens mentioned generate a hash.
Hope this gives some insight on the different ones available
Related
The current top-voted to this question states:
Another one that's not so much a security issue, although it is security-related, is complete and abject failure to grok the difference between hashing a password and encrypting it. Most commonly found in code where the programmer is trying to provide unsafe "Remind me of my password" functionality.
What exactly is this difference? I was always under the impression that hashing was a form of encryption. What is the unsafe functionality the poster is referring to?
Hashing is a one way function (well, a mapping). It's irreversible, you apply the secure hash algorithm and you cannot get the original string back. The most you can do is to generate what's called "a collision", that is, finding a different string that provides the same hash. Cryptographically secure hash algorithms are designed to prevent the occurrence of collisions. You can attack a secure hash by the use of a rainbow table, which you can counteract by applying a salt to the hash before storing it.
Encrypting is a proper (two way) function. It's reversible, you can decrypt the mangled string to get original string if you have the key.
The unsafe functionality it's referring to is that if you encrypt the passwords, your application has the key stored somewhere and an attacker who gets access to your database (and/or code) can get the original passwords by getting both the key and the encrypted text, whereas with a hash it's impossible.
People usually say that if a cracker owns your database or your code he doesn't need a password, thus the difference is moot. This is naïve, because you still have the duty to protect your users' passwords, mainly because most of them do use the same password over and over again, exposing them to a greater risk by leaking their passwords.
Hashing is a one-way function, meaning that once you hash a password it is very difficult to get the original password back from the hash. Encryption is a two-way function, where it's much easier to get the original text back from the encrypted text.
Plain hashing is easily defeated using a dictionary attack, where an attacker just pre-hashes every word in a dictionary (or every combination of characters up to a certain length), then uses this new dictionary to look up hashed passwords. Using a unique random salt for each hashed password stored makes it much more difficult for an attacker to use this method. They would basically need to create a new unique dictionary for every salt value that you use, slowing down their attack terribly.
It's unsafe to store passwords using an encryption algorithm because if it's easier for the user or the administrator to get the original password back from the encrypted text, it's also easier for an attacker to do the same.
As shown in the above image, if the password is encrypted it is always a hidden secret where someone can extract the plain text password. However when password is hashed, you are relaxed as there is hardly any method of recovering the password from the hash value.
Extracted from Encrypted vs Hashed Passwords - Which is better?
Is encryption good?
Plain text passwords can be encrypted using symmetric encryption algorithms like DES, AES or with any other algorithms and be stored inside the database. At the authentication (confirming the identity with user name and password), application will decrypt the encrypted password stored in database and compare with user provided password for equality. In this type of an password handling approach, even if someone get access to database tables the passwords will not be simply reusable. However there is a bad news in this approach as well. If somehow someone obtain the cryptographic algorithm along with the key used by your application, he/she will be able to view all the user passwords stored in your database by decryption. "This is the best option I got", a software developer may scream, but is there a better way?
Cryptographic hash function (one-way-only)
Yes there is, may be you have missed the point here. Did you notice that there is no requirement to decrypt and compare? If there is one-way-only conversion approach where the password can be converted into some converted-word, but the reverse operation (generation of password from converted-word) is impossible. Now even if someone gets access to the database, there is no way that the passwords be reproduced or extracted using the converted-words. In this approach, there will be hardly anyway that some could know your users' top secret passwords; and this will protect the users using the same password across multiple applications. What algorithms can be used for this approach?
I've always thought that Encryption can be converted both ways, in a way that the end value can bring you to original value and with Hashing you'll not be able to revert from the end result to the original value.
Hashing algorithms are usually cryptographic in nature, but the principal difference is that encryption is reversible through decryption, and hashing is not.
An encryption function typically takes input and produces encrypted output that is the same, or slightly larger size.
A hashing function takes input and produces a typically smaller output, typically of a fixed size as well.
While it isn't possible to take a hashed result and "dehash" it to get back the original input, you can typically brute-force your way to something that produces the same hash.
In other words, if a authentication scheme takes a password, hashes it, and compares it to a hashed version of the requires password, it might not be required that you actually know the original password, only its hash, and you can brute-force your way to something that will match, even if it's a different password.
Hashing functions are typically created to minimize the chance of collisions and make it hard to just calculate something that will produce the same hash as something else.
Hashing:
It is a one-way algorithm and once hashed can not rollback and this is its sweet point against encryption.
Encryption
If we perform encryption, there will a key to do this. If this key will be leaked all of your passwords could be decrypted easily.
On the other hand, even if your database will be hacked or your server admin took data from DB and you used hashed passwords, the hacker will not able to break these hashed passwords. This would actually practically impossible if we use hashing with proper salt and additional security with PBKDF2.
If you want to take a look at how should you write your hash functions, you can visit here.
There are many algorithms to perform hashing.
MD5 - Uses the Message Digest Algorithm 5 (MD5) hash function. The output hash is 128 bits in length. The MD5 algorithm was designed by Ron Rivest in the early 1990s and is not a preferred option today.
SHA1 - Uses Security Hash Algorithm (SHA1) hash published in 1995. The output hash is 160 bits in length. Although most widely used, this is not a preferred option today.
HMACSHA256, HMACSHA384, HMACSHA512 - Use the functions SHA-256, SHA-384, and SHA-512 of the SHA-2 family. SHA-2 was published in 2001. The output hash lengths are 256, 384, and 512 bits, respectively,as the hash functions’ names indicate.
Ideally you should do both.
First Hash the pass password for the one way security. Use a salt for extra security.
Then encrypt the hash to defend against dictionary attacks if your database of password hashes is compromised.
As correct as the other answers may be, in the context that the quote was in, hashing is a tool that may be used in securing information, encryption is a process that takes information and makes it very difficult for unauthorized people to read/use.
Here's one reason you may want to use one over the other - password retrieval.
If you only store a hash of a user's password, you can't offer a 'forgotten password' feature.
I am trying to a pretty simple task here. I have a server that I am running which has a MySQL instance running on it, which my rails app uses to populate. Unfortunately for me I used devise to do all my user management and now am a little stuck.
So I have a C# application that I am writing. I want to simply verify the user and password through the MySQL database that I have already in place.
Right now here is what I know (or think I know):
Devise uses Bycrypt to do a one way encryption on their passwords which are then stored in the database. The problem is that I am not sure how to implement bycrypt properly to produce the proper encrypted passwords to validate.
Here is my current process for generating my hashed password:
string pass = password.Text;
string mySalt = BCrypt.Net.BCrypt.GenerateSalt();
string myHash = BCrypt.Net.BCrypt.HashPassword(pass, mySalt);
I think that this must be really wrong. I just don't quite know what I am missing here or what I am doing wrong. I will keep googling around and if I come up with an answer I will post back. Also if I broke any editting rules or something just let me know so I can fix them right quick.
Thanks in advance for your time :)
I think your problem is your generating the Salt each time you are hashing the password to verify against the database. You need to use the same Salt value that was used when the password was initially generated.
Alright so my question was actually pretty silly but for anyone else with the same logical fallacy as me I'll explain.
By default Devise does it's encryption using BCrypt, which is typically done with Blowfish, when they do this they always use BCrypts generate salt function which produces a random salt for each hashing of the password.
Because of the random salt BCrypt includes a utility function called Verify(password, hashed_pass). This function allows the testing of a non encrypted password and hashed pass to be compared. Nifty and very useful
Firefox has to store passwords. That is totally unsafe, but it has to do it, that's all.
My C# app has the same requirement (it is a kind of browser).
Rather than storing passwords in plaintext, Firefox obfuscates them a bit.
What is the best practice for this kind of obfuscation?
For instance, here is Firefox's strategy, if I understand well:
Create a salt for the app's user
For each password, use the salt in a symmetric transformation when storing/retrieving
Store the passwords file in a directory named after the salt.
Is my understanding correct?
Is there any better strategy, or even a C# library for this?
Similar questions for other programming languages have unsatisfying answers, they don't not go as far as Firefox, just suggesting rot13 or base64, which makes it easy for automated malware to identify obfuscated passwords in unknown software. (just searching for the base64 value of common passwords)
Once again: it will not resist to any attacker, I know. But if Firefox cares I should too.
You should use the ProtectedData class to encrypt the passwords.
You can specify DataProtectionScope.CurrentUser to encrypt data using the current user's Windows login password, so that no other user can decrypt it (this also works if the user has no password)
It would probably be easiest to use an encryption rather than obfuscating. Obfuscating code generally makes it harder for someone to identify what is what in code if they viewed the source. If you don't encrypt the information however, people can still figure it out.
My advice would be is to use AES-256 or Tripple DES-128 Encryption.
Easily, you could have the passwords stored in a text file and then encrypted. Only then through your browsers can the file be decrypted.
I'm writing a program that, using Rijndael, will encrypt and decrypt files/folders using a user chosen password. Currently, when the user wants to encrypt something, they have to enter a password, that password is used to encrypt and when the user is ready to, decrypt the file/folder.
However, I would like to have a "master password" that will allow the user to only enter the password once in a "preferences" portion of the program, and then the program will automatically use that password for all encryption/decryption. This way they don't have to put in a password every time they want to encrypt/decrypt.
Now, since programs like this are prone to many different kinds of attacks, how do I safely store the user's "master password" so someone couldn't get a hold of it? Storing it in the program in plain text is obviously not a good idea, so I could encrypt/decrypt the password with another password, chosen by me, and stored in the program.
However, again, if someone gets access to the password chosen by me to encrypt/decrypt the master password, then they could decrypt the master password and again, that wouldn't be good.
SO! How do programs safely do this?
Currently I'm saving the "master password" by encrypting it using my own, chosen password, and storing it in a User-scoped setting. If you think this isn't a good idea, please tell me why and what would you change about the process I currently have implemented?
Thank you!
Review this:
http://www.redkestrel.co.uk/Articles/StoringSecrets.html
It's a great article on your options.
That said, I think your use case is already pretty well natively covered by windows itself through EFS....
http://technet.microsoft.com/en-us/library/cc700811.aspx
Just wanted to add one thing:
It is fundamentally impossible to protect a "secret" from those who have physical access to the machine. This has been proven time and again even for hard drives that support native encryption schemes.
All you can do is make it somewhat difficult for those that have no idea what they are doing.
The fundamental problem is that something has to have access to the decryption key. Whether it's the BIOS of the machine, Firmware of the Harddrive, or even if it's stored in some folder hidden through DPAPI. Which means the only effective way is to force the user to supply the necessary credentials when it's time to encrypt / decrypt the files.
If those credentials are sufficiently short then it's possible to use brute force to get to them. Right now the recommendation is to use minimum key lengths of 128 bits or greater. Of course, if you are limited to use common letters then the number of bits to test goes down dramatically. And if you allow values such as those found in hacking dictionaries then the time to crack goes down further.
Another wrinkle are keyloggers. If one's installed (and they can be hidden from most users) then all an attacker has to do is wait for the user to type their decryption password in and forward that to an interested party.
Heck, for the truly paranoid, there are devices that can detect what you typed based solely on the sound your keyboard makes as you type. For others, RAM maintains state for a certain period of time even after the machine has been shut off...
So, what does all this mean? First, you have to ask them to provide the credentials on each encrypt / decrypt request. Second, they have to be sure that no keyloggers are installed. Third, the credentials can't be something easily remembered. Fourth, the computer cannot be in a physically accessible location. Fifth, even the keyboard has to be secured...
All of which adds up to a situation that says if its on a computer, someone else can get it.
Do you know why websites won't tell you your password when you lost it and they ask for a new one?
Because they don't know it. Yes, they don't know it. They hash it and hash it good so they can only check your input password's hash against the one in the database.
Why all that?
Because they cannot store it safely.
They cannot encrypt it safely.
This is a similar case.
The best way is not to use a master password.
When you encrypt a file, ask for a password and encrypt with the hash of the password.
When decrypting, do ask for a password and attempt to decrypt.
If it fails then it's wrong.
If it's okay then it's the right one.
You can add some (shorter) dummy data before the file's contents that you can use to check the key.
If you try to use that to store the master password, you will enter an infinite loop of security, which is not a good idea.
You'll encrypt the password, and then encrypt the key used and then encrypt the key used to encrypt the first key etc.
Edit: I am sorry about the discouraging nature of this answer but what you need to do is truly impossible.
Consider storing you master password in memory using the SecureString Class.
I'll be frank about this. Leave security to security experts. Security is not easy, and is very very hard to get right even for people who are supposedly experts in the area.
If you really have to store sensitive data that your users are expecting to be secure then asking in SO on how to do it is definitely NOT a good sign and not the way to go. You should seek professional guidance or consider using well tested implementations available in the market or in Windows itself.
Don't persist the user's password, take a hash and be sure to salt it. Use the hash to encrypt and decrypt the files. Beware if the user forgets their password you will not be able to recover it for them however you could still decrypt the files for them. This also means your app would be vulnerable to somebody hacking/patching it to get it to decrypt files without providing the password.
If the encryption method is standard, documented, obvious and/or well-known then to prevent hackers from just reading the hash and using it to decrypt the files themselves you could do this: use the stored hash along with some other info to generate a new hash that you then use to encrypt/decrypt the files and never persist. The other info could be made up of the size of the file, the created date, etc. Hackers could use this info but they would have to hack/reverse engineer your app before they know they need it. Technically it's security through obscurity since those keys are hidden in plain view.
How can I encrypt and decrypt passwords in C#? Thanks for any help.
First, you're not actually going to save the encrypted password anywhere, rather you'd perform a one-way hash (e.g., SHA) store that hash. Then when you challenge a user for his password, you perform the same hash. If the new hash matches the stored hash, you've got a match.
The difference between a hash and encryption is that with encryption, you can recover the original text, where with a hash you cannot.
Read up on SHA (Secure Hashing Algorithm) and other hashing algorithms. This should give you a good start.
Even better, learn about the built in Membership API in .NET. It's almost trivial to implement and it manages all that unpleasantness about userid's, passwords, logging in, logging out and a lot more for you.
UPDATED
See this answer: C# Password Encryption
-- or --
Read this post: http://csharptest.net/470/another-example-of-how-to-store-a-salted-password-hash/
There is lots of good and bad information on the internet about storing passwords. You need to know two things:
You should use a 'salted' hash to prevent dictionary attacks
You use at minimal the SHA256 hash provider
A quick search gave me this sample code:
http://www.obviex.com/samples/hash.aspx
and I'd go with this SaltedHash utility class (looks fairly complete at a glance):
http://www.dijksterhuis.org/creating-salted-hash-values-in-c/