22

I've been told by a CISSP that the .NET class Rfc2898DeriveBytes would not pass a security audit today because it still uses SHA1. It's reliance on SHA1 - even with the iterations - leaves it too vulnerable to brute-force cracking. For my own understanding and for anyone else who stumbles across this question, is Rfc2898DeriveBytes still considered a secure method for hashing passwords? Along the same lines, is HMAC SHA256 with a salt but no iterations sufficient?

For the record, since I've been mandated to use anything other than Rfc2898DeriveBytes and since I know better than to roll my own from scratch, I intend to disassemble Rfc2898DeriveBytes and duplicate the code using SHA256 instead of SHA1.

schroeder
  • 125,553
  • 55
  • 289
  • 326
TheOtherTimDuncan
  • 323
  • 1
  • 2
  • 4
  • The biggest weakness of Rfc2898DeriveBytes is that its implementation is slow, so you can only use a relatively low iteration count. – CodesInChaos Jul 08 '15 at 19:34
  • @CodesInChaos That's not necessarily a weakness, a slower to generate hash can make brute force attacks and rainbow tables a lot less efficient, especially if you're using different salts for each password. – johnc Feb 26 '17 at 23:50
  • 3
    @johnc My point is that the .net implementation is slow compared to a good implementation, widening the gap between the defenders performance and the attackers performance. Thus lowering security compared to a defender that uses a good implementation that allows them to choose a higher iteration count. – CodesInChaos Feb 26 '17 at 23:53
  • 2
    The nuget package `Microsoft.AspNetCore.Cryptography.KeyDerivation` contains `KeyDerivation.Pbkdf2` which implements exactly the same algorithm as `Rfc2898DeriveBytes`, but runs several times faster. It's usuable just fine outside of asp.net (core or otherwise). The api is also more convenient, and it adds support for HMAC-SHA-512 and HMAC-SHA-256, which let you additionally slightly decrease the advantage of a gpu cracker. – Eamon Nerbonne May 11 '17 at 13:00
  • Note that in later versions of this class you **can** specify a hash algorithm using specific constructors. Note that it is a bad idea to ask for more than the hash output of bytes from this class *as it will repeat all iterations* and may therefore give advantage to an adversary (besides slowing down your server more than you expect). Also note that SHA-512 is often faster than SHA-256 if implemented in software (note that Intel has created special opcodes for SHA-256, so speeds may vary). – Maarten Bodewes May 28 '18 at 23:23

1 Answers1

25

Rfc2898DeriveBytes implements the standard algorithm known as PBKDF2 and defined in RFC 2898 (hence the name). That algorithm uses a configurable underlying pseudorandom function, which is usually HMAC, and HMAC itself relies on a configurable underlying hash function, usually SHA-1. While all of this is configurable, a given implementation might not be as flexible, and, indeed, Rfc2898DeriveBytes always uses HMAC and always uses SHA-1 as underlying function for SHA-1.

Nowadays, the people collectively known as "auditors" tend to wail, whine, scream, mock and run in circles when they see anything that involves SHA-1. This is scientifically unwarranted. Right now, among all the published Science, there is not the slightest indication that SHA-1 when used in HMAC would be weak. Known weaknesses in SHA-1 are about collisions which do not impact HMAC (and these are still theoretical anyway). If some guy with a CISSP insists that SHA-1 actually makes PBKDF2 more vulnerable to brute-force, then that guy should go relearn his lessons.

Nevertheless, switching the SHA-256 is not a bad idea, so if shunning SHA-1 is what it takes to get rid of auditors, so be it.

However, the following must still be said:

  • Disassembling then modifying is a rather crude method and tends to lead to unmaintainable code. You could simply start from the actual source code (e.g. from here), or, even more simply (and with a cleaner legal status), reimplement it from scratch. .NET provides a HMAC/SHA-256 implementation; using it to do a PBKDF2 code is not hard.

  • Alternatively, you may try to reuse some other existing implementation, like this one.

  • You use PBKDF2 when you want to "hash a password", and not all functions are equal in that respect. A hashing function is any good only insofar as it is expensive for attackers to compute. In that respect, PBKDF2 with SHA-1 or SHA-256 is not the best choice; arguably, PBKDF2 with SHA-512 is a better deal (because existing GPU have a harder time optimizing SHA-512 than SHA-256), but other solutions may be preferable, in particular bcrypt. For more on this subject, read this, and more generally this.

    This means that while SHA-1 "weaknesses" do not make PBKDF2 weaker, it still is a function that can be very well optimized on GPU, which is, in that case, a problem -- but, and that's the important point here, SHA-256 fares no better.

  • In any case, by using a pure C# implementation, you accept that this specifically CPU-intensive will run with the inherent slowdown of that technology, which can be estimated to a factor of 2 to 3 when compared with optimized C code (or assembly). In other words, you give an advantage of 2x or 3x to attackers. Therefore, you might want to use some native code here, not pure C#.

Thomas Pornin
  • 322,884
  • 58
  • 787
  • 955
  • 1
    "when used in HMAC" is a bit misleading in this context. With PBKDF2 the use of HMAC is useless at best (and costs a factor 2 with many implementations, including `Rfc2898DeriveBytes`). The reason why SHA-1 is fine in PBKDF2 is that collisions don't matter against password hashes. – CodesInChaos Jul 08 '15 at 19:40
  • 1
    Thank you. What you said makes sense and fits with what I've found in my research. I think I'm pretty experienced - and have the arrogance to go with it - but when it comes to hashing/cryptography I'm never quite certain when I've crossed the line to idiocy. I definitely don't have the experience - or seniority - to call out the CISSP on his statements. I had found the existing implementation as well and will probably use it as a reference. Some of my concern with the question you pointed to was it's age and how things may have changed since then. – TheOtherTimDuncan Jul 08 '15 at 19:51