MAC Generation Algorithm
The specified MAC encryption function to be used with NECP is the HMAC with MD5 hashing. The specification for HMAC, authored by Krawczyk, Bellare and Canetti is found in RFC2104.[1] While HMAC describes the procedure for message authentication using a cryptographic hash function, it does not define the specific cryptographic hash function. NECP uses MD5 as its hashing algorithm because MD5 has been well researched, has benefited from successfully identified weaknesses in its predecessors (notably MD4), and has been rigorously tested and yet appears secure. It is readily available as a library function on many platforms and in many languages and results in a 16-byte hash.
One important question is whether the MD5 hashes, produced by different libraries for different languages on different platforms are consistent. Because the MAC values for NECP will be generated on one machine and then verified on another, this is an important concern. Because the hashing algorithm operates on a byte-level representation of the data to be hashed, the actual representation of the data can affect the resulting hash value. For these reasons, NECP resolves these ambiguities by invoking the following specifications:
- The data to be encoded must be in Unicode representation.[2] Alternatively, the resulting hash must be identical to a hash generated from the same data in Unicode representation.
- All encryption keys will be 16 byte keys. If the first byte of an encryption key is 0, then the first byte of resulting key array will be stored as zero. If the first byte of an encryption key is less than 16 decimal (f hex), but greater than zero, then the first hexadecimal digit stored in the key’s byte array will be zero.[3]
- All keys will be distributed as hexadecimal digits and all MACs will be represented as hexadecimal digits.
The algorithm to compute the HMAC value as specified in RFC2104 is as follows:
MD5(K XOR opad, MD5(K XOR ipad, text))
Where ipad is the byte 0x36 repeated B times and opad is the byte 0x5C repeated B times.
- append zeros to the end of K to create a B byte string (e.g., if K is of length 20) bytes and B=64, then K will be appended with 44 zero bytes 0x00)
- XOR (bitwise exclusive-OR) the B byte string computed in step (1) with ipad
- append the stream of data 'text' to the B byte string resulting from step (2)
- apply H to the stream generated in step (3)
- XOR (bitwise exclusive-OR) the B byte string computed in step (1) with opad
- append the H result from step (4) to the B byte string resulting from step (5)
- apply H to the stream generated in step (6) and output the result
[3] This step removes the ambiguity of what to do if the key is something like “0x00d7….” Some algorithms will truncate any leading zeros from a number regardless of its radix base, thereby rendering the number as a 15 byte key instead of 16 bytes. This step prevents such truncation.