HMAC与Hash算法——C语言实现
hash算法是HMac的Mac
hmacsha256.h
1 /** 2 * @file hmacsha256.h 3 * @author your name (you@domain.com) 4 * @brief 5 * @version 0.1 6 * @date 2024-06-20 7 * 8 * @copyright Copyright (c) 2024 9 * 10 */ 11 12 #ifndef _HMAC_SHA_256_H_ 13 #define _HMAC_SHA_256_H_ 14 15 #define SHA256_BLOCKLEN 64ul //size of message block buffer 16 #define SHA256_DIGESTLEN 32ul //size of digest in uint8_t 17 #define SHA256_DIGESTINT 8ul //size of digest in uint32_t 18 19 #include <stdint.h> 20 #include <string.h> 21 22 typedef struct sha256_ctx_t 23 { 24 uint64_t len; // processed message length 25 uint32_t h[SHA256_DIGESTINT]; // hash state 26 uint8_t buf[SHA256_BLOCKLEN]; // message block buffer 27 } SHA256_CTX; 28 29 void sha256_init(SHA256_CTX *ctx); 30 void sha256_update(SHA256_CTX *ctx, const uint8_t *m, uint32_t mlen); 31 // resets state: calls sha256_init 32 void sha256_final(SHA256_CTX *ctx, uint8_t *md); 33 34 typedef struct hmac_sha256_ctx_t 35 { 36 uint8_t buf[SHA256_BLOCKLEN]; // key block buffer, not needed after init 37 uint32_t h_inner[SHA256_DIGESTINT]; 38 uint32_t h_outer[SHA256_DIGESTINT]; 39 SHA256_CTX sha; 40 } HMAC_SHA256_CTX; 41 42 void hmac_sha256_init(HMAC_SHA256_CTX *hmac, const uint8_t *key, uint32_t keylen); 43 void hmac_sha256_update(HMAC_SHA256_CTX *hmac, const uint8_t *m, uint32_t mlen); 44 void hmac_sha256_final(HMAC_SHA256_CTX *hmac, uint8_t *md); 45 46 void pbkdf2_sha256(HMAC_SHA256_CTX *ctx,const uint8_t *key, uint32_t keylen, const uint8_t *salt, uint32_t saltlen, uint32_t rounds,uint8_t *dk, uint32_t dklen); 47 48 #endif // _HMAC_SHA_256_H_
hmachas256.c
1 /** 2 * @file hmacsha256.c 3 * @author your name (you@domain.com) 4 * @brief 5 * @version 0.1 6 * @date 2024-06-20 7 * 8 * @copyright Copyright (c) 2024 9 * 10 */ 11 12 #include "hmacsha256.h" 13 14 static uint32_t ror(uint32_t n, uint32_t k) 15 { 16 return (n >> k) | (n << (32 - k)); 17 } 18 19 #define ROR(n,k) ror(n,k) 20 21 #define CH(x,y,z) (z ^ (x & (y ^ z))) 22 #define MAJ(x,y,z) ((x & y) | (z & (x | y))) 23 #define S0(x) (ROR(x, 2) ^ ROR(x,13) ^ ROR(x,22)) 24 #define S1(x) (ROR(x, 6) ^ ROR(x,11) ^ ROR(x,25)) 25 #define R0(x) (ROR(x, 7) ^ ROR(x,18) ^ (x>>3)) 26 #define R1(x) (ROR(x,17) ^ ROR(x,19) ^ (x>>10)) 27 28 static const uint32_t K[64] = 29 { 30 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 31 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 32 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 33 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 34 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 35 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 36 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 37 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 38 }; 39 40 static void sha256_transform(SHA256_CTX *s, const uint8_t *buf) 41 { 42 uint32_t t1, t2, a, b, c, d, e, f, g, h, m[64]; 43 uint32_t i, j; 44 45 for (i = 0, j = 0; i < 16; i++, j += 4) 46 { 47 m[i] = (uint32_t) buf[j] << 24 | (uint32_t) buf[j + 1] << 16 | 48 (uint32_t) buf[j + 2] << 8 | (uint32_t) buf[j + 3]; 49 } 50 for (; i < 64; i++) 51 { 52 m[i] = R1(m[i - 2]) + m[i - 7] + R0(m[i - 15]) + m[i - 16]; 53 } 54 a = s->h[0]; 55 b = s->h[1]; 56 c = s->h[2]; 57 d = s->h[3]; 58 e = s->h[4]; 59 f = s->h[5]; 60 g = s->h[6]; 61 h = s->h[7]; 62 for (i = 0; i < 64; i++) 63 { 64 t1 = h + S1(e) + CH(e, f, g) + K[i] + m[i]; 65 t2 = S0(a) + MAJ(a, b, c); 66 h = g; 67 g = f; 68 f = e; 69 e = d + t1; 70 d = c; 71 c = b; 72 b = a; 73 a = t1 + t2; 74 } 75 s->h[0] += a; 76 s->h[1] += b; 77 s->h[2] += c; 78 s->h[3] += d; 79 s->h[4] += e; 80 s->h[5] += f; 81 s->h[6] += g; 82 s->h[7] += h; 83 } 84 85 void sha256_init(SHA256_CTX *s) 86 { 87 s->len = 0; 88 89 s->h[0] = 0x6a09e667; 90 s->h[1] = 0xbb67ae85; 91 s->h[2] = 0x3c6ef372; 92 s->h[3] = 0xa54ff53a; 93 s->h[4] = 0x510e527f; 94 s->h[5] = 0x9b05688c; 95 s->h[6] = 0x1f83d9ab; 96 s->h[7] = 0x5be0cd19; 97 } 98 99 void sha256_final(SHA256_CTX *s, uint8_t *md) 100 { 101 uint32_t r = s->len % SHA256_BLOCKLEN; 102 int i; 103 104 //pad 105 s->buf[r++] = 0x80; 106 if (r > 56) 107 { 108 memset(s->buf + r, 0, SHA256_BLOCKLEN - r); 109 r = 0; 110 sha256_transform(s, s->buf); 111 } 112 memset(s->buf + r, 0, 56 - r); 113 s->len *= 8; 114 s->buf[56] = s->len >> 56; 115 s->buf[57] = s->len >> 48; 116 s->buf[58] = s->len >> 40; 117 s->buf[59] = s->len >> 32; 118 s->buf[60] = s->len >> 24; 119 s->buf[61] = s->len >> 16; 120 s->buf[62] = s->len >> 8; 121 s->buf[63] = s->len; 122 sha256_transform(s, s->buf); 123 124 for (i = 0; i < SHA256_DIGESTINT; i++) 125 { 126 md[4 * i ] = s->h[i] >> 24; 127 md[4 * i + 1] = s->h[i] >> 16; 128 md[4 * i + 2] = s->h[i] >> 8; 129 md[4 * i + 3] = s->h[i]; 130 } 131 sha256_init(s); 132 } 133 134 void sha256_update(SHA256_CTX *s, const uint8_t *m, uint32_t len) 135 { 136 const uint8_t *p = m; 137 uint32_t r = s->len % SHA256_BLOCKLEN; 138 139 s->len += len; 140 if (r) 141 { 142 if (len + r < SHA256_BLOCKLEN) 143 { 144 memcpy(s->buf + r, p, len); 145 return; 146 } 147 memcpy(s->buf + r, p, SHA256_BLOCKLEN - r); 148 len -= SHA256_BLOCKLEN - r; 149 p += SHA256_BLOCKLEN - r; 150 sha256_transform(s, s->buf); 151 } 152 for (; len >= SHA256_BLOCKLEN; len -= SHA256_BLOCKLEN, p += SHA256_BLOCKLEN) 153 { 154 sha256_transform(s, p); 155 } 156 memcpy(s->buf, p, len); 157 } 158 159 #define INNER_PAD '\x36' 160 #define OUTER_PAD '\x5c' 161 162 void hmac_sha256_init(HMAC_SHA256_CTX *hmac, const uint8_t *key, uint32_t keylen) 163 { 164 SHA256_CTX *sha = &hmac->sha; 165 uint32_t i; 166 167 if (keylen <= SHA256_BLOCKLEN) 168 { 169 memcpy(hmac->buf, key, keylen); 170 memset(hmac->buf + keylen, '\0', SHA256_BLOCKLEN - keylen); 171 } 172 else 173 { 174 sha256_init(sha); 175 sha256_update(sha, key, keylen); 176 sha256_final(sha, hmac->buf); 177 memset(hmac->buf + SHA256_DIGESTLEN, '\0', SHA256_BLOCKLEN - SHA256_DIGESTLEN); 178 } 179 180 for (i = 0; i < SHA256_BLOCKLEN; i++) 181 { 182 hmac->buf[ i ] = hmac->buf[ i ] ^ OUTER_PAD; 183 } 184 185 sha256_init(sha); 186 sha256_update(sha, hmac->buf, SHA256_BLOCKLEN); 187 // copy outer state 188 memcpy(hmac->h_outer, sha->h, SHA256_DIGESTLEN); 189 190 for (i = 0; i < SHA256_BLOCKLEN; i++) 191 { 192 hmac->buf[ i ] = (hmac->buf[ i ] ^ OUTER_PAD) ^ INNER_PAD; 193 } 194 195 sha256_init(sha); 196 sha256_update(sha, hmac->buf, SHA256_BLOCKLEN); 197 // copy inner state 198 memcpy(hmac->h_inner, sha->h, SHA256_DIGESTLEN); 199 } 200 201 void hmac_sha256_update(HMAC_SHA256_CTX *hmac, const uint8_t *m, uint32_t mlen) 202 { 203 sha256_update(&hmac->sha, m, mlen); 204 } 205 206 void hmac_sha256_final(HMAC_SHA256_CTX *hmac, uint8_t *md) 207 { 208 SHA256_CTX *sha = &hmac->sha; 209 sha256_final(sha, md); 210 211 // reset sha to outer state 212 memcpy(sha->h, hmac->h_outer, SHA256_DIGESTLEN); 213 sha->len = SHA256_BLOCKLEN; 214 215 sha256_update(sha, md, SHA256_DIGESTLEN); 216 sha256_final(sha, md); // md = D(outer || D(inner || msg)) 217 218 // reset sha to inner state -> reset hmac 219 memcpy(sha->h, hmac->h_inner, SHA256_DIGESTLEN); 220 sha->len = SHA256_BLOCKLEN; 221 } 222 223 void pbkdf2_sha256(HMAC_SHA256_CTX *hmac, 224 const uint8_t *key, uint32_t keylen, const uint8_t *salt, uint32_t saltlen, uint32_t rounds, 225 uint8_t *dk, uint32_t dklen) 226 { 227 uint8_t *U; 228 uint8_t *T; 229 uint8_t count[4]; 230 uint32_t i, j, k; 231 uint32_t len; 232 233 uint32_t hlen = SHA256_DIGESTLEN; 234 uint32_t l = dklen / hlen + ((dklen % hlen) ? 1 : 0); 235 uint32_t r = dklen - (l - 1) * hlen; 236 237 hmac_sha256_init(hmac, key, keylen); 238 239 U = hmac->buf; 240 T = dk; 241 242 len = hlen; 243 for (i = 1; i <= l; i++) 244 { 245 if (i == l) { len = r; } 246 count[0] = (i >> 24) & 0xFF; 247 count[1] = (i >> 16) & 0xFF; 248 count[2] = (i >> 8) & 0xFF; 249 count[3] = (i) & 0xFF; 250 hmac_sha256_update(hmac, salt, saltlen); 251 hmac_sha256_update(hmac, count, 4); 252 hmac_sha256_final(hmac, U); 253 memcpy(T, U, len); 254 for (j = 1; j < rounds; j++) 255 { 256 hmac_sha256_update(hmac, U, hlen); 257 hmac_sha256_final(hmac, U); 258 for (k = 0; k < len; k++) 259 { 260 T[k] ^= U[k]; 261 } 262 } 263 T += len; 264 } 265 266 }
main.c
1 /** 2 * @file main.c 3 * @author your name (you@domain.com) 4 * @brief 5 * @version 0.1 6 * @date 2024-06-20 7 * 8 * @copyright Copyright (c) 2024 9 * 10 */ 11 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include "hmacsha256.h" 16 17 /** 18 * @brief 计算hmac值,基于sha256 19 * 20 * @param key 输入数据 21 * @param value 加盐数据 22 * @param out 输出数据 23 */ 24 void hmac(const char* key, const char* value, unsigned char* out) 25 { 26 int keyLen = strlen((char *)key); 27 int valueLen = strlen((char *)value); 28 HMAC_SHA256_CTX hmac; 29 hmac_sha256_init(&hmac, key, keyLen); 30 hmac_sha256_update(&hmac, value, valueLen); 31 hmac_sha256_final(&hmac, out); 32 return; 33 } 34 35 /** 36 * @brief 计算哈希值,基于sha256 37 * 38 * @param key 输入数据 39 * @param out 输出数据 40 */ 41 void hash(const unsigned char *key, unsigned char *out) { 42 SHA256_CTX sha; 43 sha256_init(&sha); 44 sha256_update(&sha, key, strlen(key)); 45 sha256_final(&sha, out); 46 return; 47 } 48 49 int main() 50 { 51 uint8_t hexData[65] = {0}; // 十六进制形式的字符串用作打印输出 52 unsigned char md[32] = {0}; 53 unsigned char test_val[] = "where am i"; 54 unsigned char test_key[] = "who am i"; 55 hmac(test_val, test_key, md); 56 for(int i = 0; i < 32; i++) 57 { 58 sprintf(hexData + 2 * i, "%02x", md[i]); 59 } 60 hexData[64] = '\0'; 61 printf("HmacDate:\n%s\n",hexData); 62 63 hash(test_key, md); 64 for(int i = 0; i < 32; i++) 65 { 66 sprintf(hexData + 2 * i, "%02x", md[i]); 67 } 68 hexData[64] = '\0'; 69 printf("HashDate:\n%s\n",hexData); 70 71 return 0; 72 } 73 74 75 // HmacDate: 76 // 476eb8bdb7b96a9f229d7123703910c3e8d11f26d09c4b9867a05e6d52370df9 77 // HashDate: 78 // 73d7b7288d31175792d8a1f51b63936d5683718082f5a401b4e9d6829de967d3
在线HMAC和哈希值计算:
参考自: