Rfc2898DeriveBytes with Sha2 in C# - c#

I have a password hashing mechanism based upon Rfc2898DeriveBytes (based on code detailed here: http://crackstation.net/hashing-security.htm). Internally, this class utilizes SHA1 which - the CrackStation link does indicate the SHA1 is "old", but also states that, although Rfc2898DeriveBytes uses it internally, Rfc2898DeriveBytes is still a good mechanism.
The security department of a customer of mine has heard that that "SHA1 has been compromised" (specifically, that, for purposes of signing a document for transmission across the internet, SHA1 has been defeated, under certain circumstances - the fact that this "vulnerability" does not apply to a password hash is immaterial to the security department). As a result, they have demanded that we alter our password hashing mechanism to employ SHA2.
Currently, the .Net framework has no equivalent of Rfc2898DeriveBytes that employs SHA2 (or SHA256, etc.) internally. I know that I can use reflection to get at the source code for this class and change it, but I've always been told that the first rule of encryption is "don't grow your own".
This is principally a political demand by my customer, not a technical one, which could be easily satisfied by running the password through a SHA2 hash prior to running it through Rfc2898DeriveBytes. However, I am not sufficiently knowledgeable about cryptography to know if this might be bad - might in fact result in an objectively less secure password hash.
Does anyone know of an Rfc2898DeriveBytes equivalent class that employs SHA2? Or, does anyone know if running the password through a SHA2 hash prior to Rfc2898DeriveBytes would be perfectly safe?

Download the free code samples from "SecurityDriven.NET" book. Find the PBKDF2 class which takes an HMAC factory. Available factories include SHA2 (256, 384, 512).
Running the password through SHA2 hash prior to Rfc2898DeriveBytes is not the right thing to do, even if this is unlikely to be the weakest part of whatever you're doing (you'd be losing password entropy).

Related

Why is crypto with .Net Framework so complicated?

In most cases I need to encrypt a string with a password and then send/save it somewhere. Later I want do decrypt it with the password. I am not encrypting nuclear missile codes or medical patient data! The ideal would be 2 functions:
string Encrypt(string plainText, string password);
string Decrypt(string cipherText, string password);
I had a look at the crypto documentation... Oh boy! So I try to code the above calls myself (see a proof of concept using AES Managed and Base64 encoded payload). I am no crypto expert, why do I have to code that? I probably did somethings wrong...
To derive the key from the password the interface requires a salt. Can I use the password as salt? Can I re-use the IV as salt? Maybe not, but I don't want to add another parameter.
Can I use a fixed IV? Same plaintext and password should result in different cipher text, so I have to supply the IV for decryption in the payload.
Can I use a salt for the key and keep the IV constant instead? Feels wrong.
Creating a nonce and deriving IV and key salt from it is a valid approach?
If .Net would support the GCM mode would I still have this problems?
The .NET crypto API exposes a general purpose encryption library, containing object oriented approaches to implement cryptographic algorithms. Of course, to use these algorithms and algorithm implementations you need to have a good grasp on cryptography, which you currently lack.
This general purpose library is required to implement the various protocols that exist out there. Usually a single algorithm doesn't fulfill a specific use case (encrypt a string using a password, returning a different string, in your case). So a protocol needs to be chosen or devised that does fulfill that use case. This protocol may e.g. define a container format such as CMS or PGP, which can for instance be used to encrypt emails (the use case).
You're directly trying to apply cryptographic algorithms to solve your use case. That's not going to work. You need a pre-made protocol, preferably with a pre-made API.
Note that there are many different use cases, many different protocols and even more opinions on how to create and implement those correctly. Libsodium / NaCl for instance defines a small container format called SecretBox that does take some of the work from you.
However, it would of course be rather impossible to implement TLS on top of NaCl, as the functionality / algorithms are just not there. Again, .NET needs a generic crypto library like the .NET API for others to implement their protocols.
So either you'll have to byte the bullet and try to create your own protocol or you take an existing one and take an educated guess if it is secure (hopefully the protocol has been reviewed / updated a few times). Stay away from single person projects without additional contributors (like the many sample codes out there without review).
For your own protocol, yes, there are mistakes such as not storing the salt with the ciphertext. You need a random - or at least unique - salt to be secure, reusing the password for that is certainly not secure. Don't let it become a single person project itself and either borrow a protocol or have it reviewed.
OK, quickly then:
To derive the key from the password the interface requires a salt. Can I use the password as salt? Can I re-use the IV as salt? Maybe not, but I don't want to add another parameter.
No, the salt needs to be unique and preferably random; the password / salt combination should be unique (it should not repeat, not even in time, or over different domains).
Can I use a fixed IV? Same plaintext and password should result in different cipher text, so I have to supply the IV for decryption in the payload.
No, unless the key changes value each time (see above). For CBC the IV should be unpredictable unless you use a fresh key each time.
Can I use a salt for the key and keep the IV constant instead? Feels wrong.
That's possible, as long as you don't repeat the salt.
Creating a nonce and deriving IV and key salt from it is a valid approach?
That depends on very specific details. In other words, I would not try it if you don't exactly know what you're doing.
If .Net would support the GCM mode would I still have this problems?
Absolutely, and in a sense your problems would be worse if you'd use GCM, as using GCM with the same key and IV is completely broken.
Remember, GCM is just an algorithm, not a protocol, it cannot solve your use case by itself.

Rijndael algorithm alternative for password hashing

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.

How to compute MD5 value as if you are using the System.Security.Cryptography.MD5 class

In my application a CRC value is computed for a file by using the System.Security.Cryptography.MD5 (C#). It is used as a compact digital fingerprint.
The MD5 class is declared non-FIPS compliant and "everything" works fine if the following Windows Local Policy is disabled:
"System Cryptography: Use FIPS compliant algorithms for encryption, hashing and signing".
Now, I need to enable the above System Policy, but the MD5 class fails when called..
Is there a way to compute the CRC value exactly as if you are using the System.Security.Cryptography.MD5?
Thanks in advance, regards
As Damien_The_Unbeliever mention above, your requirements are incompatible. But a slightly more detailed answer would be "yes and no".
No: MD5 should not be used any more as there are known collisions. It is broken for pretty much all cryptographic purposes. If those fingerprints are used in any security relevant context then you're well advised to change to a secure hash function. SHA2 and SHA3 are secure and FIPS certified. Switching an entire application to a different hash function may cause you some pain now but the alternative is more pain later.
Yes: It is possible - you could reimplement MD5 yourself or use a library that does not check for the Windows policy. All you'd have to do is ensure a correct data format. However, I would strongly advise against this option. MD5 is broken.
Since you've stated that you have to enable the policy for FIPS compliant cryptography, I would assume that this is either a customer or sales requirement which leaves you with no choice but to switch to SHA2 or SHA3.

Security of AES encryption with constant salt

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.

.NET: Difference between PasswordDeriveBytes and Rfc2898DeriveBytes

I'm trying to understand some C#-code, I have been handed, which deals with cryptography, and specifically uses PasswordDeriveBytes from System.Security.Cryptography.
In the .NET docs , it says that PasswordDeriveBytes uses "an extension of the PBKDF1 algorithm" which is later in the document specified as "the PKCS#5 v2.0 standard", which is PBKDF2 (as far as I can tell). Everywhere on the net I've found (including here on Stack Exchange), though, everyone says "use Rfc2898DeriveBytes, cause Password* is deprecated and uses PBKDF1". But the only difference in the docs at msdn.microsoft.com seems to be that the Rfc*-version specifically mentions PBKDF2, where Password* says "extension of PBKDF1" and "PKCS#5 v 2.0".
So, can anyone tell me what the difference is between the two classes (if any) and why I should use one rather than the other for PBKDF2 password key derivation?
Now, other code, that deals with the same data, explicitly uses PBKDF2, and works, so that would suggest that indeed PasswordDeriveBytes also uses PBKDF2, or that PBKDF2 is simply compatible with PBKDF1 under certain circumstances, but I want to know for sure that it's not some side effect of some random thing, and that things just magically works (and eventually probably will magically and spectacularly break) without anyone really understanding why.
If you instantiate PasswordDeriveBytes and make a single call to the GetBytes method passing a value which is smaller than the output size of the underlying digest algorithm then you get back a value from the PBKDF1 algorithm.
If you make two calls to GetBytes for the same object you may encounter a counting bug in the implementation.
PBKDF1 is only described to output up to the size of the hash algorithm (e.g. 20 bytes for SHA-1), but the PasswordDeriveBytes class has made up a formula to support up to 1000 times the hash output size. So a large value produced by this class may not be easily attainable in another platform.
If you instantiate Rfc2898DeriveBytes you get a streaming implementation of the PBKDF2 algorithm. The most obvious difference of PBKDF2 over PBKDF1 is that PBKDF2 allows the generation of an arbitrary amount of data (the limit is (2^32-1)*hashOutputSize; or for SHA-1 85,899,345,900 bytes). PBKDF2 also uses a more complex construction (in particular, HMAC over direct digest) to make recovering the input password from an output value more difficult.
The "streaming" in the implementation is that the concatenation of GetBytes(5) and GetBytes(3) is the same as GetBytes(8). Unlike in PasswordDeriveBytes, this works correctly in Rfc2898DeriveBytes.
PBKDF1 was originally created to generate DES keys, published in PKCS #5 v1.5 in 1993.
PBKDF2 was published in PKCS #5 v2.0 (which was republished as RFC2898) in 1999. A slide deck which should be found at ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-5v2/pkcs5v2-0.pdf (but seems to be having issues so ftp://ftp.dfn-cert.de/pub/pca/docs/PKCS/ftp.rsa.com/99workshop/pkcs5_v2.0.ppt may hve to do) further summarizes differences. (The slide deck was written by RSA Security, the creators of PBKDF1 and PBKDF2, and they are the people who recommend PBKDF2 over PBKDF1).
I think a great answer to this would be found here:
C# PasswordDeriveBytes Confusion
But to sumup:
Microsoft's implementation of original PKCS#5 (aka PBKDF1) include insecure extensions to provide more bytes than the hash function can provide (see bug reports here and here).
Even if it was not buggy you should avoid undocumented, proprietary extensions to standards (or you might never be able to decrypt your data in the future - at least not outside Windows.)
I strongly suggest you to use the newer Rfc2898DeriveBytes which implements PBKDF2 (PKCS#5 v2) which is available since .NET 2.0.
Here's a blog post detailing the differences:
http://blogs.msdn.com/b/shawnfa/archive/2004/04/14/generating-a-key-from-a-password.aspx
PBKDF2 can be used to generate keys of any length, which is very useful for password-based encryption (it can generate any key length as required by the symmetric cipher) but means less for secure password storage. It also applies the salt using HMAC instead of concatenation like PBKDF1, which has better security properties in cases of weak salts.
PKCS#5 v2.0 defines both PBKDF1 and PBKDF2, the former for reasons of backwards compatibility and also recommends you use PBKDF2 for new applications. I've no idea why the latter is better than the former, but the two .NET classes do seem to use different but interoperable algorithms. (Possibly because only the resulting key is being exchanged, not the inputs + KDF.)

Categories