HMAC

Another algorithm (CALG_HMAC) implemented by Microsoft providers is known as HMAC. This algorithm also uses a secret symmetric key to create the hash, but is more complex than the simple CBC MAC algorithm. It can be used with any iterated cryptographic hash algorithm, such as MD5 or SHA-1.

The following expression is used to calculate an HMAC:

H( K XOR OuterString, H( K XOR InnerString, text ))

Where:

H
Denotes the cryptographic hash algorithm to be used. It must be of a type where data is hashed by iterating a basic compression function on blocks of data.
K
The secret (symmetric) key that is to be used.
InnerString
A fixed byte string.
OuterString
A fixed byte string.
text
The data that is to have the HMAC applied to it.
    To compute an HMAC by using the CryptoAPI
  1. Get a pointer to the Microsoft Cryptographic Provider by calling CryptAcquireContext.
  2. Create a handle to an HMAC hash object by calling CryptCreateHash. CALG_HMAC should be passed in the Algid argument and the handle of a symmetric key in the hKey argument. This is the key that is used in computing the HMAC.
  3. Specify the the type of hash to be used by calling CryptSetHashParam with the dwParam argument set to the value HP_HMAC_INFO. The pbData argument must point to an initialized HMAC_INFO structure.
  4. Call CryptHashData to begin computing the HMAC of the data. The first call to CryptHashData causes the key value to be XORed with the inner string and the data. The result of the XOR is hashed and then the target data for the HMAC (pointed to by the pbData argument passed in the call to CryptHashData) is hashed. If necessary, subsequent calls to CryptHashData may then be made to finish the hashing of the target data.
  5. Call to CryptGetHashParam with the dwParam argument set to HP_HASHVAL. This call causes the inner hash to be finished and the outer string to be XORed with the key. The result of the XOR is hashed and then the result of the inner hash (completed in the previous step) is hashed. The outer hash is then finished and returned in the pbData argument and the length in the pdwDataLen argument.

Warning  The same symmetric (session) key should not be used for both message encryption and MAC generation. Doing so greatly increases the risk of your messages being decoded by attackers.