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.

closed as off-topic by Jens Erat, RoraΖ, Steve, D.W., schroeder Jan 16 '15 at 20:23

  • This question does not appear to be about Information security within the scope defined in the help center.
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 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 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. 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
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.

  • 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
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.

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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.