Hashing problem
Page 1 of 1

Author:  florian [ Tue May 23, 2006 12:41 pm ]
Post subject:  Hashing problem


i have a problem with building the MIC for encrypted KLVs. I'm using the HashHMACSHA1 class like this:


UInt8 hash_key[16] =
{ 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56,
0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56 };

DataChunkPtr HashKey = BuildHashKey(16, hash_key);
HashPtr Hasher = new HashHMACSHA1();
Hasher->HashData(size, buf);
DataChunkPtr Hash = Hasher->GetHash();


size is:
length of the encrypted source value (IV+Check+SourceValue+Padding)
+ 20 (Byte) for length & value of the TrackFileID
+ 12 (Byte) for length & value of the SequenceNumber
+ 4 (Byte) for the length of the MIC

buf holds the associated data.

The calculated MIC is not identical to the MIC in the given encrypted KLV.
So, is this the right approach in principle?


Author:  Matt Beard [ Tue May 23, 2006 1:40 pm ]
Post subject: 

A couple of points:

1) The 2nd parameter of the BuildHaskKey() method is the encryption key used for the encrypted KLV - this is unlikely to be "VVVVVVVVVVVVVVVV" as used in your example (are you actually replacing this with the cipher key?)

2) The lengths are BER and so may not be constant!

Otherwise it sounds OK

Author:  florian [ Tue May 23, 2006 1:47 pm ]
Post subject: 

Thanks for your reply.

The key is correct, its for testing only.
I also considered the BER coded length, these are the concrete values in my case only, sorry.

Author:  Matt Beard [ Tue May 23, 2006 3:30 pm ]
Post subject: 

Are you hashing the encrypted data, or the plaintext?

Author:  florian [ Tue May 23, 2006 4:21 pm ]
Post subject: 

I'm hashing the encrypted data. Is this wrong?

Author:  Matt Beard [ Tue May 23, 2006 4:24 pm ]
Post subject: 

Yes - you should be hashing the encrypted data (otherwise the hash of the plaintext gives an extra vector to attack the encryption!)

Author:  florian [ Tue May 30, 2006 8:32 am ]
Post subject: 

I took a look at the asdcplib and i think i found some problems in your hashing procedure.

I think BuildHashKey() generates a false key, because the MICKey shall be generated this way:

MICKey = trunc( HMAC-SHA-1( CipherKey, 0x00112233445566778899aabbccddeeff ) )

where trunc selects the first 128-bits of the output.

BuildHashKey() doesn't use the CipherKey directly, but instead CipherKey^=0x36 via SetKey().

Also i think SetKey() should call SHA1_Update(&Context, KeyBuffer_i, 64) with Size instead of 64. Same thing in GetHash() with KeyBuffer_o.

What do you think?

Author:  Matt Beard [ Sat Jun 03, 2006 3:33 pm ]
Post subject: 

I think that you are misunderstanding the way SetKey works - if you look in RFC 2104 ("HMAC: Keyed-Hashing for Message Authentication") you will see that the 0x36 value you see in SetKey is the initialization of ipad. (opad is also initialized to 64 * 0x5c here).

The code you quoted from section 7.10 of the AS-DCP spec shows that setting the MICkey involves a pass through the entire HMAC-SHA-1 algorithm - including the setting of ipad and opad.

The reason that 64 bytes are set into SHA1_Update in SetKey is that this is the size of ipad which gets included in the hash at the start of the HMAC calculation (opad is included at the end)

I hope that asdcplib calculates its HMAC in the same way as MXFLib. If you add the following test function to mxfcrypt.cpp, then try this with the HMAC-SHA-1 test cases from RFC 2202 ("Test Cases for HMAC-MD5 and HMAC-SHA-1") you will find that the results are correct.

bool TestHMAC(DataChunkPtr Key, DataChunkPtr Data, DataChunkPtr ExpectedResult)
   ASSERT(ExpectedResult->Size == 20);

   printf("Key =%s\nData=%s\nHash=%s\n", Key->GetString().c_str(), Data->GetString().c_str(), ExpectedResult->GetString().c_str());

   HashPtr Hasher = new HashHMACSHA1();

   DataChunkPtr Result = Hasher->GetHash();

   bool Ret = true;

   if(Result->Size != 20)
      error("Result not 20 bytes\n");
      error("Actual Result=%s\n", Result->GetString().c_str());
      Ret = false;
      if(memcmp(ExpectedResult->Data, Result->Data, 20) != 0)
         error("Actual Result=%s\n", Result->GetString().c_str());

   if(!Ret) printf("*FAILED*\n\n");
   else printf("OK\n\n");

   return Ret;

Author:  florian [ Tue Jun 06, 2006 7:34 am ]
Post subject: 

I knew how ipad and opad are used, but i thought that they are not needed to generate the key. The asdcplib (AS_DCP_AES.cpp,v 1.11) works this way:

void SetKey(const byte_t* key)
    static byte_t key_nonce[KeyLen] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
               0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
    byte_t sha_buf[SHA_DIGEST_LENGTH];

    // 7.10: MICKey = trunc( SHA1 ( key, key_nonce ) )
    SHA1_Update(&SHA, key, KeyLen);
    SHA1_Update(&SHA, key_nonce, KeyLen);
    SHA1_Final(sha_buf, &SHA);
    memcpy(m_key, sha_buf, KeyLen);


I took a closer look at the documents, and now i think you are right. The HMAC-procedure is missing in the asdcplib SetKey function.

The file i'm working with was generated with the asdcplib and i think the MICs are probably incorrect.

Thanks for your help!

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group