C言語実現HMACアルゴリズム

2665 ワード

実装リファレンス:https://en.wikipedia.org/wiki/HMACこのサイトのテスト例でテストに合格しました.
HMACアルゴリズムはかなり分かりやすい.
Function hmac
   Inputs:
      key:        Bytes     array of bytes
      message:    Bytes     array of bytes to be hashed
      hash:       Function  the hash function to use (e.g. SHA-1)
      blockSize:  Integer   the block size of the underlying hash function (e.g. 64 bytes for SHA-1)
      outputSize: Integer   the output size of the underlying hash function (e.g. 20 bytes for SHA-1)
 
   Keys longer than blockSize are shortened by hashing them
   if (length(key) > blockSize) then
      key ← hash(key) //Key becomes outputSize bytes long
   
   Keys shorter than blockSize are padded to blockSize by padding with zeros on the right
   if (length(key) < blockSize) then
      key ← Pad(key, blockSize)  //pad key with zeros to make it blockSize bytes long
    
   o_key_pad = key xor [0x5c * blockSize]   //Outer padded key
   i_key_pad = key xor [0x36 * blockSize]   //Inner padded key
    
   return hash(o_key_pad ∥ hash(i_key_pad ∥ message)) //Where ∥ is concatenation

C言語実現hmac.h
// hmac.h
#ifndef hmac_h
#define hmac_h

#include 

void hmac_sha256(const unsigned char *data, size_t len, const unsigned char *key, int len_key, unsigned char *out);

#endif /* hmac_h */

hmac.c
// hmac.c
#include 
#include "hmac.h"
#include "sha256.h"

void hmac_sha256(const unsigned char *data, size_t len, const unsigned char *key, int len_key, unsigned char *out) {
    int block_size = 64;
    int hash_size = 32;
    int key_size = block_size;
    unsigned char buf[block_size];
    unsigned char buf2[block_size];
    bzero(buf, block_size);
    bzero(buf2, block_size);
    if (len_key > block_size) {
        key_size = hash_size;
        sha256(data, len, buf);
        memcpy(buf2, buf, key_size);
    } else {
        memcpy(buf, key, len_key);
        memcpy(buf2, key, len_key);
    }
    for (int i = 0; i < key_size; i++) {
        *(buf + i) = *(buf + i) ^ 0x5c;
        *(buf2 + i) = *(buf2 + i) ^ 0x36;
    }
    size_t hash_buf_size = key_size + (len < hash_size ? hash_size : len);
    unsigned char hash_buf[hash_buf_size];
    memcpy(hash_buf, buf2, key_size);
    memcpy(hash_buf + key_size, data, len);
    unsigned char hash_out[hash_size];
    sha256(hash_buf, key_size + len, hash_out);
    memcpy(hash_buf, buf, key_size);
    memcpy(hash_buf + key_size, hash_out, hash_size);
    sha256(hash_buf, key_size + hash_size, out);
}

関連記事
暗号学基礎のメッセージ要約関数C言語実現SHA 256アルゴリズム暗号学基礎シリーズ