3

Is AES a good choice for protecting a key stored on the computer of a user of my application? I have seen threads on hashing passwords that suggest using slow algorithms for defending against brute force attacks.

Also, any recommendations on what parameters I should use for RijnadealManaged, such as padding algorithm, ciphermode or key size?

Casebash
  • 601
  • 1
  • 7
  • 16

3 Answers3

5

You're better off using DPAPI.

While AES-256 / CBC / PKCS7 / etc is a good choice of cipher+params, that still won't solve your problem: After you encrypt the encryption key, what do you do with the Key Encrypting Key (KEK)? You'll still be stuck having to encrypt the encryption key...

DPAPI provides an excellent solution, allowing you to punt off the responsibility of key management onto the OS. (Sort of.)

You can use the ProtectedData class, from the System.Security.Cryptography namespace, it is very simple and straightforward - just make sure you set USER_MODE to make sure that only that user has access to decrypt the key.

Going back for a moment, depending on the application, you might be better off using DPAPI to protect the KEK (key encrypting key), and not the encryption key itself - sharing and distributing keys becomes easier, as does rekeying (if necessary).

AviD
  • 72,138
  • 22
  • 136
  • 218
  • We actually encrypt using both DPAPI and AES. As for the KEK, well that isn't stored on the system. We generate the KEK from the user's password, which is not stored on the system – Casebash Jul 27 '11 at 13:46
1

I'm new to crypto as well, so take this with a grain of salt, but using AES in CBC mode is probably a good choice, although it really depends on what/how you are encrypting). AES with 128bit keys is sufficient for SECRET level documents; 192 or 256bit keys are required for TOP SECRET documents according to the NSA. As for padding, I believe the standard is PKCS7 Padding, so you should probably just stick with that. If you decide to use CBC, ensure you generate a random IV (same length as your key) each and every time you encrypt any data with that key. You need to ensure that as long as you are using the same key that you never use the same IV to encrypt another message. The IV is considered public, so you can simply store it along with your encrypted data so it can be used to initialize the cipher during decryption.

Having said all that, probably the safest thing to do is to see if .NET has a library similar to Jasypt or KeyCzar. These libraries will take care of all of the dangerous little details for you so you dont end up creating security holes you didnt even know were possible.

Hope that points in the right direction at least!

senecaso
  • 782
  • 6
  • 14
  • I took a quick look, and the closest thing I could find to one of those libraries is an attempt to make a [.NET assembly](http://code.google.com/p/keyczar/wiki/KeyczarDotNet) out of the KeyCzar implementation. It doesnt look like much fun though. – senecaso Jul 27 '11 at 03:47
  • I've fully ported [Keyczar to C#](http://jbtule.github.com/keyczar-dotnet/) for that reason. – jbtule Feb 20 '13 at 16:37
1

In general, you shouldn't be doing this yourself, but following the guidelines for the system you are using.

The "correct" way of storing passwords is with a "one-way" hash, with "salt" and "key strengthening".

The term "one-way" means just that. Once you hash it, you can never recover the password yourself. There's no way to ever recover the password. But, you can still check if the user has entered the correct password by repeating the hash on what they typed in, and see if it matches the one stored in the database.

If hackers steal your password hashes, they can crack them offline.

The most common crack is to pre-calculate a zillion password hashes. When they steal hashes from your site, they look them up in a table, and instantly find the original password.

To defeat that, you "salt" the password. You generate some random text, and hash that text with the password. You then store that salt+hash in your database.

This forces the hackers to "brute-force" your passwords instead of using a "table lookup". Hacker desktops can calculate 1-billion hashes per second, so they will quickly discover small passwords.

To defeat that, you simply repeatedly hash the value. If you repeat the hash a thousand times, the hacker can now only test a million per second.

Unfortunately, the more expensive you make it for the hacker, the more expensive you make testing passwords for yourself. Repeating the hash a 1000 times is a good compromise between slowing down the hacker and impacting the performance of your server.

Another way of slowing down the hacker are applying rules to passwords, such as demanding that they be at least 8 characters long and containing numbers and symbols. Most passwords are words, in all lower case letters. That means the hacker needs only test 26 combinations per letter. If passwords are composed of upper and lower case, numbers, and symbols, that becomes around 100 combinations per letter.

The point of the above is to teach you all the complications of how hackers attacks passwords, and the things administrators go through in order to defend those passwords. Usually, you don't need to worry about it: you just choose the solution the underlying system you are using has chosen for you.

Robert David Graham
  • 3,883
  • 1
  • 15
  • 14
  • 2
    Hi @Robert, welcome to [security.se]! Thanks for the good information, but it's not really relevant to the question - the question specifically is asking about protecting an *ecnryption key*, not a password. As such, it of course cannot be stored using a one-way hash, it needs to be retrievable. – AviD Jul 27 '11 at 21:12