views:

110

answers:

3

I have an edge case. I'm building code that reads binary datafiles produced by a commercial, closed source tool. The information on the data format is specified in a document.

For data integrity checks, the vendor's spec calls for an HMAC based on SHA1, using a key derived from a password as per RFC2898. Many programming environments have a class called HMACSHA1 to produce these hashes.

For data streams of non-zero length, I can successfully calculate the Hash, and the calculation in my code agrees with the vendor's implementation. In other words, my code can read and authenticate files written by the vendor, and vice versa.

However, when the length of the data stream is zero, the vendor's tool emits a Hash which is NOT all zeroes. I don't know where it comes from, if there is no message to run through the HMACSHA1.

For HMACSHA1, or for any HMAC, is the MAC defined for the edge case of "a null message"?

I am using .NET, and the class System.Security.Cryptography.HMACSHA1, although I believe my question is platform-agnostic.


There is one platform-specific bit: When I try to get the Hash property on an instance of that type, if I have not run any data through the instance, I get

Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Security.Cryptography.HashAlgorithm.get_Hash()

This isn't surprising to me at all, since there is nothing to hash.

any hints?

+3  A: 

Bumbling around in the dark, I found what I needed. Not sure if HMACSHA1 is defined for the case of a zero-length message, BUT

I did find that on .NET, if I call HMACSHA1.ComputeHash() and pass a byte array of length zero, I get the expected, desired hash.

Sorry for the noise, we now return you to your previously scheduled programming.

Cheeso
This implies that HMACSHA1 is defined for a message of zero length, but not for an un defined (null) message. As expected.
pb
A: 

Have to tried to add a zero length array to the hash? The underlying object is likely created during the first call.

Using several implementations hashing a zero length file gives:

MD5   : d41d8cd98f00b204e9800998ecf8427e
SHA-1 : da39a3ee5e6b4b0d3255bfef95601890afd80709
devstuff
The HMACSHA1 requires a key, which you haven't specified. Also the implementation I'm complying with, uses a Salt. So the actual hashes you are giving, aren't really useful.
Cheeso
Oops, half asleep and didn't read the question properly. These are straight MD5/SHA1 hash values, not HMACs.
devstuff
+2  A: 

HMACSHA1 is defined for all inputs of n bits, where 0 <= n < 2^20 - 160.

HMACSHA1 is defined as SHA1( K* || SHA1( K** || text ) ), where K* and K** are 20 bytes long values derived from the key (see FIPS 198a).

So HMACSHA1( "empty string" ) = SHA1( K* || SHA1( K** ) ), which is very well-defined.

Rasmus Faber
Thank you, very very useful.
Cheeso