When I choose password encryption, I have found that Rijndael algorithm is one of the best encryption which cannot be cracked through brute force attack.
So I have choosen Rijndael algorithm for user's password encryption.
Now I have identified that, hashing (Irreversible) is more secure than encryption (Reversible) [Please correct me if I am wrong]
Here my question is,
Can I go with the existing implementation Rijndael algorithm
If I should not do encryption, Which one should be a best hashing algorithm.
I have referred the following website when implementing Rijndael algorithm.
http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael(v=vs.110).aspx
How to generate Rijndael KEY and IV using a passphrase?
http://www.obviex.com/samples/encryption.aspx
OWASP lists some good practices for password storage.
You basically apply a protection_function to convert the credential to a protected form:
[protected form] = [salt] + protect([protection func], [salt] + [credential]);
You also add a salt so two versions of the same credential have a different stored form.
They also list the order in which you should choose hashing functions (yes, hashing is better than encrypting so that the password cannot be reverse engineered, even by the website owner). Argon2 and PBKDF are generally good choices for a protection_function.
Read the rest of the guide too. Also this related Security SE post about why AES (i.e. Rijndael) encrypted password storage is worse than even a not-so-strong hash (#Salvador's comment).
The problem with encryption is, that when an attacker get the key, he can decrypt all passwords of the database in no time, and therefore knows the original passwords which can be tried on other sites.
Since hashing is irreversible (there is no way to get back the original password), an attacker cannot use the hashes, even if he has control over the server. The same goes for the owner of the site.
Today recommended algorithms are BCrypt, PBKDF2 and SCrypt, all of them have a cost factor which controls the necessary time to calculate a single hash. The longer it needs, the more difficult it will be to brute-force.
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 have an encoding application written in C# where users can optionally encrypt messages. I had been using the class in this answer, and it turns out I'm in good company because I found several places online that use the exact same code (one of which is Netflix's Open Source Platform).
However, comments to that answer (as well as later edits to that answer) led me to believe that this method was insecure. I opted to use the class in this answer to the same question instead.
How secure is AES encryption if you use a constant salt? How easily can this method be broken? I admit that I have very little experience in this area.
AES is a block cipher. A block cipher's input is a key and a block of plaintext. A block cipher is usually used in a block cipher mode of operation. All secure modes of operation use an Initialization Vector or IV. Otherwise identical plaintext would encrypt to identical ciphertext (for the same key), and this is leaking information.
Salt is not used by AES or modes of operation. It's usually used as input for Key Derivation Functions (KDFs), especially Password Based Key Derivation Functions (PBKDFs). Dot NET's Rfc2898DeriveBytes implements the PBKDF2 function as defined in - you'd guess it - RFC 2898: "PKCS #5: Password-Based Cryptography Specification Version 2.0".
If you use a static salt in a PBKDF2 then you would get the same key as output (for the same number of iterations). Now if you would ever leak the resulting key then all your ciphertext would be vulnerable. And if you would use multiple passwords then an attacker would be able to build a rainbow table; the PBKDF2 work factor would become less important; the attacker can simply build one table and then try all the resulting keys on all possible ciphertexts.
So, as the salt is not actually used for AES it doesn't make much of a difference for the security. It is however still a horrible sin, even worse than using the default iteration count for PBKDF2 / Rfc2898DeriveBytes.
Note that horrible security sins are committed by a large number of people on a daily basis. That there are many many many persons that get it wrong doesn't tell you that you are in "good company". That there are 289 upvotes just tells you that SO answers about cryptography should not be trusted based on vote count.
Salt is there for a reason.
This enables same input to be encrypted differently.
If an attacker would really insist, he can find some patterns that repeat themselves in encryption without salt, and eventually can get to your key more easily.
Still the attcker would have to work very hard.
Using constant salt equals to not using salt at all.
And it is highly recommended to use it, as it has no effect on the decryption process.
What is considered "best practice" for encrypting certain sensitive or personally identifiable data in a SQL database (under PCI, HIPAA, or other applicable compliance standards)?
There are many questions here regarding individual aspects of a solution, but I have not seen any that discuss the approach at a high level.
After looking around for quite some time, I came up with the following:
Use CryptoAPI and Rijndael
Generate IV and store it with the encrypted data
Use DPAPI (Machine scope) to "protect" the symmetric key
Store the symmetric key in the registry or a file or the database, split the key and store parts in multiple places for added protection
do not decrypt the data unless it is really needed, i.e. not upon read from the database. Instead, hold cipher text in memory.
Is this adequate? Outdated? Audit-safe? Reckless?
Your approach is good, with a few adjustments in my eyes (I code for PCI compliance generally):
Use CryptoAPI and Rijndael
Use Rijndael/AES256 at a minimum, regardless of other APIs
Generate IV and store it with the encrypted data
Good
Use DPAPI (Machine scope) to "protect" the symmetric key
Not sure if it matters. I'd just keep the IV next to the data that's encrypted, or if you're really paranoid on some other medium. Ensure that the IV is not accessible to the public.
Store the symmetric key in the registry or a file or the database, split the key and store parts in multiple places for added protection
Storing in multiple places will not help you if someone steals your media. It's a bit overkill to split the key up all over heck, but definitely do NOT store it with your IV and/or ciphertext. That'd be bad.
do not decrypt the data unless it is really needed, i.e. not upon read from the database. Instead, hold cipher text in memory.
Definitely. Holding cipher text in memory in fine, but don't pass it around anywhere, and don't decrypt except when you absolutely must, and even then don't EXPOSE the entire unencrypted dataset - only what is needed from it at the minimum. Also, do not hold the key in memory if possible - a memory dump could expose it.
Additions:
Whatever database you store your cipher text in, restrict read access entirely to the proc(s) that select for a given identifier. Do not allow read access to the tables that store this data to ANYONE, even the SA account. This way, a person who breaks into your system will have a hard time pulling down your cipher texts without knowing what IDs to look for. Do the same for any table(s) referencing the identifier on the ciphertext table. DO NOT ALLOW BLANKET READS OF THESE TABLES!
Restrict database access by IP
Never persist any unencrypted plaintext in memory over state. Allow it to be dereferenced/garbage collected as soon as the request is completed.
Restrict the server(s) running this code to as few users as possible.
Possibly combine encryption methods for a stronger ciphertext (AES + Blowfish for example)
Hope these help. Some of them are my personal opinions but remain PCI compliant to the best of my knowledge.
I saw that one of the previous comments mentioned that it doesn't matter if you use CryptoAPI. I just wanted to point out that CryptoAPI is FIPS 140-2 compliant, while Bouncy Castle and the built-in managed classes (all the ones with "Managed" at the end of their names in the System.Security.Cryptography namespace) are not. If you have a requirement for FIPS compliance, it's probably easiest to for you to use CryptoAPI.
I would add:
Keeping the IV hidden is not important. It's OK if the IV is public. Just use good IVs, which means, use a cryptographic-strong random number generator so that your IVs are indistinguishable from random.
Storing the encryption key separate from the data that it encrypts.
Add authentication to your encryption. For example, add an HMAC keyed with a second symmetric encryption key, covering the ciphertext. If you don't use some form of authenticated encryption, then your ciphertext could be modified, and you have no way of knowing (AES will decrypt garbage just fine.) You want any tampering of the ciphertext to be noticed.
Taken more generic list of best practices, from OWASP (Cryptographic Storage Cheat Sheet):
Use strong approved cryptographic algorithms
Do not implement an existing cryptographic algorithm on your own
Only use approved public algorithms such as AES, RSA public key cryptography, and SHA-256 or better for hashing
Do not use weak algorithms, such as MD5 or SHA1
Avoid hashing for password storage, instead use Argon2, PBKDF2, bcrypt or scrypt
Use approved cryptographic modes
In general, you should not use AES, DES or other symmetric cipher primitives directly. NIST approved modes should be used instead. Quote from Nist: "The approved algorithms for encryption/decryption are symmetric key algorithms: AES and TDEA."
Use strong random numbers
Ensure that any secret key is protected from unauthorized access
Also, according to this Cisco article:
DES is to be avoided and so is RSA-768, -1024
RSA-2048 and RSA-3072 are acceptable
AES-CBC mode is acceptable, while
AES-GCM mode is part of the Next Generation Encription.
After reading this post regarding the use ECC to implement the hashing using aa private key I set about trying to find an implementation of ECDH and came across BoucyCastle.
Unfortunately documentation is minimal (as in zerow!) and I'm unsure what I'm about to accomplish is completely correct/valid.
We want to simply hash 4 strings which will be the users registration information (Name, Company, their company ID and their account ID which are both 12 characters long) which will then compute a serial they can use to activate our software.
I have generated a key pair using PUTTYGEN.exe but I cannot workout how to apply this with BouncyCastle, which class can I use to get started? Are there any examples out there?
So far I've concatenated the information and computed a MD5 hash of it (using the .NET classes) I cannot use the new VISTA enhanced API functions as we target XP still - .NET 3.5.
Anyone have any ideas?
I think .NET has the RSACryptoServiceProvider class which is a full RSA implementation.
There's sample code for your particular application here:
http://www.codeproject.com/KB/security/xmldsiglic.aspx
In this example they use MS's sn.exe tool to create the key.
So far I've concatenated the information and computed a MD5 hash of it (using the .NET classes).....
That statement in itself worries me. MD5 is seriously crackable - not just theoretically but practically. Please, please don't use MD5 for secure hashing. Use SHA-256 or SHA-512 and here's why
Also the post you linked is not quite true - yes symmetric algorithms use the same key to encrypt/decrypt but public/private key is not a magic bullet.
1) Public/private key is slow
2) Most publicc/private algorithms just encrypt the symmetric key and then use symmetric encryption for the data because it's much faster
The point is that a good hashing algorithm is non-reversible and hence very difficult to crack so is perfectly fine for your purposes. However, I'd suggest using a SALT, which is a cryptographically random number to add to your user data then hash that data as it makes your data much safer against dictionary attacks ( where hackers use well know terms and variants to crack passwords )
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/