7

I work for an online shop and since I worked here we have stored customer passwords in plaintext. I joined the company as a data inputter and when I discovered that we did this I flagged it up with management but they didn't seem interested or concerned. Several years later I am in charge of the website and I now want to encrypt all our customer's passwords.

What is the quickest and easiest way of encrypting all customer passwords on a .NET ecommerce website? Are there .NET libraries we can make use of?

Edit

I currently know next to nothing about encryption or password security. I have been accused of doing no research before posting this question. I have actually begun researching this topic today and this question is part of my research. I'm sorry if people are offended with my lack of knowledge but it isn't through laziness. I simply don't know anything about this field and I am now trying to find out. This question is part of that. I would really appreciate any help you can give me.

Mike
  • 87
  • 3
  • 4
    You want to use a password hash (like PBKDF2), not encryption. `Rfc2898DeriveBytes` in .net. Use a per user salt and at least 10000 iterations. – CodesInChaos Jan 16 '15 at 13:16
  • 7
    I'm not the downvoter, but it is obvious that you haven't done any research at all before asking or you wouldn't be talking about "encrypting" passwords. – Bob Brown Jan 16 '15 at 13:17
  • 2
    Read [this post](http://security.stackexchange.com/questions/211/how-to-securely-hash-passwords/31846#31846) about passwords. – Lawtonfogle Jan 16 '15 at 14:49
  • Also remember when you get round to encrypting all the passwords, you will need to update the login/register and any other user related code to implement the hashing choice you make. – Ryan McDonough Jan 16 '15 at 15:18
  • Take a look at this [answer](http://security.stackexchange.com/a/71938/36971). It has a nice in depth description of each step used for password hashing and why you shouldn't roll your own. Rely on a pre-existing implementation (written by experts) – dberm22 Jan 16 '15 at 15:27
  • I agree that in this case hashing is the superior choice compared to encryption, but you always have to check that you don't need the password for challenge response schemes like CHAP. They don't work with hashed password (or are cheating like MS-CHAP where the password hash is as good for logging in as the password itself). – Drunix Jan 16 '15 at 18:01
  • Didn't see this mentioned anywhere. But you may want to consider forcing user password resets. Can you be sure that the plain text passwords aren't already exposed somewhere? Or do you have data backups that will have these plain text passwords? It's a risk to customer experience I know, but not nearly as big as having their password stolen. – CLo Jan 16 '15 at 18:37

3 Answers3

5

Passwords should be salted and hashed, not encrypted. You should use a slow hash to mitigate precomputation attacks. There is .NET code here: https://crackstation.net/hashing-security.htm

Edited to add: If your number of accounts is low, you might be able to simply block login attempts while the hashing code runs. However, it's designed to be slow, so you may have to allow logins while passwords are being hashed. That's no problem. Compare the plaintext password first; if there's no match, hash the offered password and compare again.

Do not forget that you have to store the salt as well as the hash. If you're not changing your database schema, those can be concatenated and stored in the existing password field, assuming it's varchar. Otherwise, you may have to add columns to the database and clear the plaintext column after the hash computation is complete and committed.

Check your password recovery mechanism. When you've done this, you won't be able to tell users what their passwords are. You'll need some other recovery mechanism.

Not relevant to the question, but if you're not using TLS for the login, you need to.

Bob Brown
  • 5,283
  • 1
  • 19
  • 28
  • Not exactly the best implementation. 1) It's using a hash size of 24 bytes, increasing the hashing cost for the defender by a factor 2 without costing the attacker anything. 2) 1000 iterations is very low. 3) The 24 byte salt size is silly but harmless. – CodesInChaos Jan 16 '15 at 13:33
  • @CodesInChaos: Both are constants defined in the code, and so easy to change. There is an extensive essay describing how to select appropriate values for a given application. – Bob Brown Jan 16 '15 at 13:37
  • 1
    @CodesInChaos: I should add, in defense of your own comment, that it is foolhardy to do cut-and-paste programming of crypto applications, including hashing, without understanding what's going on. That's why I linked to the long essay instead of something else. – Bob Brown Jan 16 '15 at 13:43
  • 1) Safe defaults are important. 2) Outputting 24 bytes from PBKDF2-HMAC-SHA1 for a login hash cannot be justified. It's simply a bad choice. – CodesInChaos Jan 16 '15 at 13:46
  • 2
    @CodesInChaos: Consider communicating your remark to Taylor Hornby. He is quite open to fixing things on that page. – Bob Brown Jan 16 '15 at 13:51
  • @BobBrown, if it's easy to change, their examples should be more correct. The PHP is fine, SHA-256 has a native 32 byte size. The Javascript is wrong, SHA-1 has a native 20 byte size. The C# is wrong, SHA-1 again. The Ruby is also wrong, SHA-1 again. SHA-1 should be capped at 20 bytes. I'd bump up the iteration count dramatically, and even more for the SHA-1 examples. I would also note that I have collected a variety of examples of PBKDF2 with test vectors at [my github page](https://github.com/Anti-weakpasswords) if you'd like to benchmark some against each other. – Anti-weakpasswords Jan 17 '15 at 03:38
3

The best option for password hashing provided out of the box by .Net is PBKDF2, which as CodesInChaos commented is implemented as System.Security.Cryptography.Rfc2898DeriveBytes.

The real choice you have to make is whether this is the only change your account/password management code needs. If it is, you can implement it directly, replacing your current password management, and be done with it.

If, however, there are other issues with the how you are managing credentials (and with plain-text password storage, I suspect this is likely) it may be a better idea to abstract account management entirely, and re-factor the application to use ASP.NET Identity instead. This will give you PBKDF2-based password hashing by default, and also provide you with ready made solutions for things like password reset, account locking mechanisms to prevent password brute-forcing, and many other security benefits.

Xander
  • 35,525
  • 27
  • 113
  • 141
0

It's better practice to hash a password rather than encrypt it. Very basically, hashing is a one-way mechanism whereas encryption is reversible.

Why's this important? Well, if a malicious entity (which could be an employee) finds how you've encrypted the data (either by brute force or just stealing the key etc.) they can decrypt it - and then (mis)use your customers passwords, most of which will have been re-used elsewhere (other sites, email, banking etc.). A breach like that would harm the reputation of your site / company.

With a hash, you can know how a hashed value has been generated, but you won't know the value (their password) that has generated it. Unless, of course, you're not securing the communication between the server at log on (HTTP instead of HTTPS web pages, for example). *

As part of this process, the password should also be salted:

In cryptography, a salt is random data that is used as an additional input to a one-way function that hashes a password or passphrase.[1] The primary function of salts is to defend against dictionary attacks versus a list of password hashes

Source: http://en.wikipedia.org/wiki/Salt_%28cryptography%29

Again, very basically, this would be where an attacker takes a list of known / common (pass)words, say "letmein" and hashes it. Know they'll know the Hash that corresponds to the password "letmein" and can quickly lookup to see if any of your users have the same password hash. Obviously, this is very easy to automate with a "dictionary" of possible / common (pass)words. Salting helps to prevent this scenario.

As for how to implement it in .NET, see this question (and answers) from Stack Overflow:

https://stackoverflow.com/questions/19957176/asp-net-identity-password-hashing

I'm not terribly familiar with .NET development, but according to the answer from @jd4u the default implementation uses a salt in addition to the user's password when producing a Hash.

* If your site pages (at least the log on) aren't already served over a secure connection, get this done too.

Michael
  • 101
  • 3