MAC (Message authentication code, messaging authentication Code algorithm) is a key hash function algorithm that is compatible with the features of the MD and SHA algorithms, and adds a key on this basis. So Mac algorithms are often called HMAC algorithms.

**1** **,** **HMAC** **Overview**

The HMAC algorithm first is based on the Information Digest algorithm. At present, the main collection of MD and SHA Two series of Message digest algorithm. Among them, the MD series algorithm has HmacMD2, HmacMD4, HmacMD5 Three kinds of algorithms, the SHA Series algorithm has HmacSHA1, HmacSHA224, HmacSHA256, HmacSHA384, HmacSHA512 five kinds of algorithms.

In addition to the Information Digest algorithm, the HMAC algorithm requires a key. The key of an HMAC can be any length, and if the length of the key exceeds the length of the Digest algorithm information grouping, the digest algorithm is used first to calculate the digest of the key as the new key. It is generally not recommended to use a key that is too short because the length of the key is related to the security intensity. The length of the information digest that is not less than the output of the selected digest algorithm is usually selected.

**2** **,** **HMAC** **Algorithm Analysis**

The HMAC algorithm itself is not complex and requires a hash function, which we remember as H. We also need to have a key, which we remember as K. Each information digest function groups The information, the length of each block is fixed, and we remember B (for example: SHA1 is 512 bits, or 64 bytes). Each information digest algorithm outputs a fixed-length summary of information, and we record the length of the Information Digest as L (for example, MD5 is 16 bytes and SHA-1 is 20 bytes). As mentioned above, the length of k is theoretically arbitrary, generally for the sake of safety strength, choose not less than L length.

The HMAC algorithm actually uses the key and plaintext to perform two rounds of hashing, and the formula can be expressed as follows:

HMAC (k,m) =h (K⊕opad∣h (k⊕ipad∣m)), Where:

ipad repeats B for 0x36

Opad Repeat B for 0x5c

M represents a message input

Based on the above algorithm representation formula, we can describe the operation steps of the HMAC algorithm:

(1), check the length of the key K. If the length of k is greater than B, a new key with a length of L is calculated first using the digest algorithm. If the length of the post-K is less than B, the length of the latter is appended to the B.

(2), the key string of the B-word length generated in the previous step is different or operation with the ipad.

(3), the data stream that needs to be processed is populated with the text of the second step in the result string.

(4), use the hash function h to calculate the information digest value of the data stream generated in the previous step.

(5), the first step to generate the B-word length key string and Opad do the XOR operation.

(6), and then the result of the fourth step is filled to the result of fifth step.

(7), using the hash function h to calculate the information digest value of the data stream generated in the previous step, the output is the final HMAC value.

From the above described process, we know that the algorithm of the HMAC process is actually done two times the original text is similar to the salt processing of the hash process.

**3** **, code implementation**

Earlier we described the HMAC algorithm and its implementation, and then we implemented it. First we define a structure to hold the context of the calculation process:

/** the structure will save the context information for the HMAC key hash operation */

typedef struct HMACCONTEXT {

int Whichsha; /* The SHA algorithm used */

int hashsize; /* The size of the SHA used for the hash value */

int blockSize; /* The size of the SHA block used */

Shacontext Shacontext; /* SHA Context */

unsigned char k_opad[sha_max_message_block_size];/* outer padding-key xord with Opad */

int Computed; /* is the MAC computed? */

int corrupted; /* Cumulative Corruption code */

} Hmaccontext;

The HMAC initialization function is then implemented. This function initializes the hmaccontext to prepare for the calculation of a new HMAC message digest.

int Hmacreset (Hmaccontext *context, enum shaversion whichsha,const unsigned char *key, int key_len)

{

int I, blocksize, hashsize, ret;

unsigned char k_ipad[sha_max_message_block_size];/* inner padding-key xord with ipad */

unsigned char tempkey[shamaxhashsize];/* temporary buffer when Keylen > blocksize * *

if (!context) return shanull;

context->computed = 0;

context->corrupted = shasuccess;

BlockSize = Context->blocksize = Shablocksize (Whichsha);

Hashsize = Context->hashsize = Shahashsize (Whichsha);

Context->whichsha = Whichsha;

/* If the key is longer than the hash block size, reset it to key = hash (key). */

if (Key_len > BlockSize) {

Shacontext Tcontext;

int err = Shareset (&tcontext, Whichsha) | |

Shainput (&tcontext, Key, Key_len) | |

Sharesult (&tcontext, Tempkey);

if (err! = shasuccess) return err;

key = Tempkey;

Key_len = hashsize;

}

/* Place key in the same position as ipad and opad or */

for (i = 0; i < Key_len; i++) {

K_ipad[i] = key[i] ^ 0x36;

Context->k_opad[i] = key[i] ^ 0x5c;

}

/* Populate key 0 until blocksize and with ipad and Opad bitwise XOR */

for (; i < blocksize; i++) {

K_ipad[i] = 0x36;

Context->k_opad[i] = 0x5c;

}

/* Start Inner hash operation */

ret = Shareset (&context->shacontext, Whichsha) | |

Shainput (&context->shacontext, K_ipad, blocksize);

return context->corrupted = ret;

}

Next, enter the information that will be processed, which takes a byte array as the next processing part of the message.

int Hmacinput (hmaccontext *context, const unsigned char *text,int text_len)

{

if (!context) return shanull;

if (context->corrupted) return context->corrupted;

if (context->computed) return context->corrupted = Shastateerror;

/* Message content */

Return context->corrupted =shainput (&context->shacontext, text, Text_len);

}

The final processing completes the entire process and returns a summary of the information. This function returns a message digest of the corresponding size, depending on how long the information digest is determined by the specific SHA algorithm.

int Hmacresult (Hmaccontext *context, uint8_t *digest)

{

int ret;

if (!context) return shanull;

if (context->corrupted) return context->corrupted;

if (context->computed) return context->corrupted = Shastateerror;

/* Complete INNER hash Operation */

RET =sharesult (&context->shacontext, digest) | |

/* Perform outer hash operation */

Shareset (&context->shacontext, Context->whichsha) | |

Shainput (&context->shacontext, context->k_opad,context->blocksize) | |

Shainput (&context->shacontext, Digest, context->hashsize) | |

Sharesult (&context->shacontext, Digest);

context->computed = 1;

return context->corrupted = ret;

}

**4** **, Results**

We have implemented the HMAC algorithm, and then we validate it. We use a simple test, take the encrypted text as Text = "ABCD", set the key to Key= "123456", based on the SHA-1 HMAC results are as follows:

The results of the HMAC operation based on SHA-256 are as follows:

The results of the SHA-512-based operation are as follows:

We tested three cases of HMAC-SHA1, hmac-sha256 and HMAC-512, and compared with the online HMAC encryption algorithm, the demerit was exactly the same.

Welcome attention:

Information Digest algorithm: Analysis and implementation of HMAC algorithm