4

Why do the following two methods of calling ComputeHash result in different result lengths? Seems like the code should produce equivalent results.

byte[] KeyBytes = Convert.FromBase64String("KgMLuq+k1oCUv5bzTlKAJf/mGo0T07jTogbi6apcqLa114CCPH3rlK4c0RktY30xLEQ49MZ+C2bMyFOVQO4PyA==");
byte[] MessageBytes = System.Text.Encoding.UTF8.GetBytes("ae06fcd3-6447-4356-afaa-813aa4f2ba41;70aa7c25-c74f-48be-8ca8-cbf73627c05f1418068667");

// works
byte[] HashBytes1 = new System.Security.Cryptography.HMACSHA256(KeyBytes).ComputeHash(MessageBytes); // correct - 32 bytes

// doesn't work
System.Security.Cryptography.HMAC hmac2 = System.Security.Cryptography.HMACSHA256.Create();
hmac2.Key = KeyBytes;
byte[] HashBytes2 = hmac2.ComputeHash(MessageBytes); // wrong - only 20 bytes
BSalita
  • 8,420
  • 10
  • 51
  • 68

2 Answers2

2

That's simple: look at the remarks of the static HMAC.Create method:

By default, this overload uses the SHA-1 implementation of HMAC. If you want to specify a different implementation, use the Create(String) overload, which lets you specify an algorithm name, instead.

Now HMACSHA256 inherits from HMAC, but it doesn't define it's own static Create method. So you would still have to use HMAC.Create("HMACSHA256").

It's probably better to use the HMAC.Create(String) than using HMACSHA256.Create(String) class here, as not to confuse matters.

Note that the SHA-1 outputs 160 bits or 20 bytes, so this indeed explains the odd output size...

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • In Java using a *static* method on anything else than the class that it is defined in can toss a compiler warning. Does anybody know if this is also configurable for C# (and Visual Studio)? Or would this require some kind of static code analysis tool? – Maarten Bodewes Nov 23 '15 at 22:10
  • Ah, found it! [ReSharper seems to do this](http://stackoverflow.com/questions/660132/using-a-classs-static-member-on-a-derived-type). Not for free though. – Maarten Bodewes Nov 23 '15 at 22:17
0

From MSDN: System.Security.Cryptography.HMACSHA256.Create()

By default, this overload uses the SHA-1 implementation of HMAC. If you want to specify a different implementation, use the Create(String) overload, which lets you specify an algorithm name, instead.

When you call Create currently you are really calling the base class' Create function.

Try:

System.Security.Cryptography.HMAC hmac2 = System.Security.Cryptography.HMACSHA256.Create("System.Security.Cryptography.HMACSHA256");

Yes, I realize how dumb this looks in code form... just trying to answer the question.

As an alternative:

System.Security.Cryptography.HMAC hmac2 = System.Security.Cryptography.HMAC.Create("System.Security.Cryptography.HMACSHA256");
Clay Ver Valen
  • 1,033
  • 6
  • 10