├── README.md ├── hmac-sha256.c ├── hmac-sha256.h └── package.json /README.md: -------------------------------------------------------------------------------- 1 | hmac-sha256 2 | =========== 3 | 4 | HMAC-SHA256 implemented in C. 5 | 6 | Installation 7 | ------------ 8 | 9 | Install with [clib](https://github.com/clibs/clib): 10 | 11 | ```sh 12 | clib install aperezdc/hmac-sha256 --save 13 | ``` 14 | 15 | API 16 | --- 17 | 18 | ```c 19 | #define HMAC_SHA256_DIGEST_SIZE 32 20 | 21 | void hmac_sha256 (uint8_t out[HMAC_SHA256_DIGEST_SIZE], 22 | const uint8_t *data, size_t data_len, 23 | const uint8_t *key, size_t key_len); 24 | ``` 25 | 26 | 27 | License 28 | ------- 29 | 30 | Distributed under the terms of the [MIT/X11 31 | license](https://opensource.org/licenses/MIT) 32 | -------------------------------------------------------------------------------- /hmac-sha256.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hmac-sha256.c 3 | * Copyright (C) 2017 Adrian Perez 4 | * 5 | * Distributed under terms of the MIT license. 6 | */ 7 | 8 | #include "hmac-sha256.h" 9 | #include "sha256/sha256.h" 10 | #include "apicheck/apicheck.h" 11 | 12 | /* 13 | * HMAC(H, K) == H(K ^ opad, H(K ^ ipad, text)) 14 | * 15 | * H: Hash function (sha256) 16 | * K: Secret key 17 | * B: Block byte length 18 | * L: Byte length of hash function output 19 | * 20 | * https://tools.ietf.org/html/rfc2104 21 | */ 22 | 23 | #define B 64 24 | #define L (SHA256_DIGEST_SIZE) 25 | #define K (SHA256_DIGEST_SIZE * 2) 26 | 27 | #define I_PAD 0x36 28 | #define O_PAD 0x5C 29 | 30 | void 31 | hmac_sha256 (uint8_t out[HMAC_SHA256_DIGEST_SIZE], 32 | const uint8_t *data, size_t data_len, 33 | const uint8_t *key, size_t key_len) 34 | { 35 | api_check_return (out); 36 | api_check_return (data); 37 | api_check_return (key); 38 | api_check_return (key_len <= B); 39 | 40 | sha256_t ss; 41 | uint8_t kh[SHA256_DIGEST_SIZE]; 42 | 43 | /* 44 | * If the key length is bigger than the buffer size B, apply the hash 45 | * function to it first and use the result instead. 46 | */ 47 | if (key_len > B) { 48 | sha256_init (&ss); 49 | sha256_update (&ss, key, key_len); 50 | sha256_final (&ss, kh); 51 | key_len = SHA256_DIGEST_SIZE; 52 | key = kh; 53 | } 54 | 55 | /* 56 | * (1) append zeros to the end of K to create a B byte string 57 | * (e.g., if K is of length 20 bytes and B=64, then K will be 58 | * appended with 44 zero bytes 0x00) 59 | * (2) XOR (bitwise exclusive-OR) the B byte string computed in step 60 | * (1) with ipad 61 | */ 62 | uint8_t kx[B]; 63 | for (size_t i = 0; i < key_len; i++) kx[i] = I_PAD ^ key[i]; 64 | for (size_t i = key_len; i < B; i++) kx[i] = I_PAD ^ 0; 65 | 66 | /* 67 | * (3) append the stream of data 'text' to the B byte string resulting 68 | * from step (2) 69 | * (4) apply H to the stream generated in step (3) 70 | */ 71 | sha256_init (&ss); 72 | sha256_update (&ss, kx, B); 73 | sha256_update (&ss, data, data_len); 74 | sha256_final (&ss, out); 75 | 76 | /* 77 | * (5) XOR (bitwise exclusive-OR) the B byte string computed in 78 | * step (1) with opad 79 | * 80 | * NOTE: The "kx" variable is reused. 81 | */ 82 | for (size_t i = 0; i < key_len; i++) kx[i] = O_PAD ^ key[i]; 83 | for (size_t i = key_len; i < B; i++) kx[i] = O_PAD ^ 0; 84 | 85 | /* 86 | * (6) append the H result from step (4) to the B byte string 87 | * resulting from step (5) 88 | * (7) apply H to the stream generated in step (6) and output 89 | * the result 90 | */ 91 | sha256_init (&ss); 92 | sha256_update (&ss, kx, B); 93 | sha256_update (&ss, out, SHA256_DIGEST_SIZE); 94 | sha256_final (&ss, out); 95 | } 96 | -------------------------------------------------------------------------------- /hmac-sha256.h: -------------------------------------------------------------------------------- 1 | /* 2 | * hmac-sha256.h 3 | * Copyright (C) 2017 Adrian Perez 4 | * 5 | * Distributed under terms of the MIT license. 6 | */ 7 | 8 | #ifndef HMAC_SHA256_H 9 | #define HMAC_SHA256_H 10 | 11 | #include 12 | #include 13 | 14 | #define HMAC_SHA256_DIGEST_SIZE 32 /* Same as SHA-256's output size. */ 15 | 16 | void 17 | hmac_sha256 (uint8_t out[HMAC_SHA256_DIGEST_SIZE], 18 | const uint8_t *data, size_t data_len, 19 | const uint8_t *key, size_t key_len); 20 | 21 | #endif /* !HMAC_SHA256_H */ 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hmac-sha256", 3 | "version": "0.1.1", 4 | "repo": "aperezdc/hmac-sha256", 5 | "description": "No-frills HMAC-SHA256 implementation in C", 6 | "keywords": [ "hmac", "sha256", "sha2" ], 7 | "src": [ "hmac-sha256.h", "hmac-sha256.c" ], 8 | "dependencies": { 9 | "aperezdc/apicheck": "0.1.1", 10 | "jb55/sha256.c": "0.0.2" 11 | } 12 | } 13 | --------------------------------------------------------------------------------