5

Is it enough to use this method with SHA256 or it is better to use Rfc2898DeriveBytes (which orginally uses SHA1)?

    public static byte[] ComputeHash(byte[] data, byte[] salt, int iterations)
    {
        if (data == null)
            throw new ArgumentNullException(nameof(data));

        if (salt == null)
            throw new ArgumentNullException(nameof(salt));

        if (iterations <= 0)
            throw new ArgumentOutOfRangeException(nameof(iterations));

        using (SHA256CryptoServiceProvider provider = new SHA256CryptoServiceProvider())
        {
            byte[] output = provider.ComputeHash(data.Concat(salt).ToArray());

            for (int iteration = 1; iteration < iterations; iteration++)
            {
                output = provider.ComputeHash(output.Concat(data).Concat(salt).ToArray());
            }
            return output;
        }
    }

Can above code be used instead of Rfc2898DeriveBytes from point of view of security? Will hashes have more or less entropy? Will it have more or less complexity (CPU/GPU/ASIC time) if I will use significantly big iterations parameter?

Maxim
  • 193
  • 1
  • 7
  • 1
    The context of your question is missing. Without this context it is unknown what you are trying to achieve and what "better" would mean in relation to your unknown goal. – Steffen Ullrich Sep 08 '16 at 06:23
  • "data" is byte-array converted from string meaning password, "salt" is RNGCryptoServiceProvider value (32 bytes), "iterations" is 65 535... I mean does it enough to get the same entropy as Rfc2898DeriveBytes and will it be OK to control complexity with big count of iterations. – Maxim Sep 08 '16 at 06:33
  • Information essential to understand the question belong in the question itself and not in a comment. Apart from that I don't mean context in terms of data structures but what you want to do, i.e. password check, key derivation... – Steffen Ullrich Sep 08 '16 at 06:42
  • Hash will be computed to be saved in database (initial key derivation when account is just created). And during password check it will be generated from string which is typed by user who attempts to login. Maybe I misunderstood something but for me it looks pretty clear as well as parameters of this method ))) – Maxim Sep 08 '16 at 06:55
  • Maxim: your question is probably obvious to you since you know the context. We don't know the context and it does not help much if you offer some glimpse to it in the comments. Remember: since you want others to help you your aim should be to make it easy for them to understand the question and not just easy for you to write it. – Steffen Ullrich Sep 08 '16 at 06:57
  • In comments I am trying to clarify things which are not clear for you in my question, because it looks that you can give some answer if I will provide more details.. nothing else... but you just said how much I am "bad" because from your point of view my explanation is not enough clear... do you mean that my question is absolutely not clear for community? – Maxim Sep 08 '16 at 07:03
  • I mean that you just dumped some code without context (i.e. for what security relevant part if this code used for) and asked is one thing better than one other in this unknown context. But is impossible to say what is better without knowing what it is used for. – Steffen Ullrich Sep 08 '16 at 07:05
  • Which context do you want? Maybe I need to copy here login form?. I am asking only if it can be replacement for Rfc2898DeriveBytes from point of view of security. Will it have more or less entropy? will it have more or less complexity (CPU/GPU/ASIC time)? Looks like I need to include it in my question to be more clear.. – Maxim Sep 08 '16 at 07:32
  • 1
    @Maxim You mentioned in in passing in a comment that this was going to be used for hashing passwords, but that's nowhere in the question. This is quite important, as that's not the primary purpose of Rfc2898DeriveBytes, which is password-based key derivation. Password hashing is a secondary use, and different security properties and considerations apply. – Xander Sep 08 '16 at 11:46

2 Answers2

7

Use the known, trusted algorithm over one that you've made yourself.**

I can't speak for the entropy, but of course it will take more time if you have a sufficiently large number of iterations. It's just a matter of finding that number. That being said, I personally would not use your SHA256-based code.

As has been said in what is probably my favourite answer on security.SE: Complexity is bad. Homemade is bad. New is bad. From that same answer, Rfc2898DeriveBytes is PBKDF2, and PBKDF2:

  • Has been specified for a long time, seems unscathed for now.
  • Is already implemented in various framework (e.g. it is provided with .NET).
  • Highly configurable (although some implementations do not let you choose the hash function, e.g. the one in .NET is for SHA-1 only).
  • Received NIST blessings (modulo the difference between hashing and key derivation; see later on).

Why would you want to write your own - potentially buggy, potentially vulnerable, definitely unnecessary - crypto code when there is already code written for you that has been tested, attacked, and demonstrated to be good?

Further reading:

Richard Ward
  • 194
  • 9
  • I think you are arguing really good. I will mark it as answer )) But I still do not see any mathematical analyzing which says why SHA256 & salt with feedback is bad. Your attempt to offer standard algorithms of course makes sense... But most likely I need to look at Argon2. But there are no pure .Net implementation. Still think that is bad to port it from C++ to C#? )) – Maxim Sep 09 '16 at 03:30
  • Since version 4.7.2 it is possible to specify the algorithm through [HashAlgorithmName](https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.hashalgorithmname?view=netframework-4.7.2) -> [constructor](https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rfc2898derivebytes.-ctor?view=netframework-4.7.2#System_Security_Cryptography_Rfc2898DeriveBytes__ctor_System_String_System_Byte___System_Int32_System_Security_Cryptography_HashAlgorithmName_) – Francesco Milani Feb 08 '20 at 11:26
1

It seems you want SHA256 because it is more secure than SHA1, but you also want PBKDF2 because it is more secure than a single hash. Solution: use PBKDF2 with SHA256.

Sjoerd
  • 28,897
  • 12
  • 76
  • 102
  • Yes, most likely it can be an option.. and I considered that already... But original idea is not single hash.. it is multiple hashes with salt and feedback, when output is used on input during next iteration... with salt and password. So I am trying to figure if it is enough to be secure... – Maxim Sep 08 '16 at 06:47