nostril

A C cli tool for creating nostr events
git clone git://jb55.com/nostril
Log | Files | Refs | Submodules | README | LICENSE

hmac_sha256.c (4847B)


      1 /* MIT (BSD) license - see LICENSE file for details */
      2 #include "hmac_sha256.h"
      3 #include <string.h>
      4 
      5 #define IPAD 0x3636363636363636ULL
      6 #define OPAD 0x5C5C5C5C5C5C5C5CULL
      7 
      8 #define BLOCK_U64S (HMAC_SHA256_BLOCKSIZE / sizeof(uint64_t))
      9 
     10 static inline void xor_block(uint64_t block[BLOCK_U64S], uint64_t pad)
     11 {
     12 	size_t i;
     13 
     14 	for (i = 0; i < BLOCK_U64S; i++)
     15 		block[i] ^= pad;
     16 }
     17 
     18 void hmac_sha256_init(struct hmac_sha256_ctx *ctx,
     19 		      const void *k, size_t ksize)
     20 {
     21 	struct sha256 hashed_key;
     22 	/* We use k_opad as k_ipad temporarily. */
     23 	uint64_t *k_ipad = ctx->k_opad;
     24 
     25 	/* (keys longer than B bytes are first hashed using H) */
     26 	if (ksize > HMAC_SHA256_BLOCKSIZE) {
     27 		sha256(&hashed_key, k, ksize);
     28 		k = &hashed_key;
     29 		ksize = sizeof(hashed_key);
     30 	}
     31 
     32 	/* From RFC2104:
     33 	 *
     34 	 * (1) append zeros to the end of K to create a B byte string
     35 	 *  (e.g., if K is of length 20 bytes and B=64, then K will be
     36 	 *   appended with 44 zero bytes 0x00)
     37 	 */
     38 	if (ksize != 0)
     39 		memcpy(k_ipad, k, ksize);
     40 	memset((char *)k_ipad + ksize, 0, HMAC_SHA256_BLOCKSIZE - ksize);
     41 
     42 	/*
     43 	 * (2) XOR (bitwise exclusive-OR) the B byte string computed
     44 	 * in step (1) with ipad
     45 	 */
     46 	xor_block(k_ipad, IPAD);
     47 
     48 	/*
     49 	 * We start (4) here, appending text later:
     50 	 *
     51 	 * (3) append the stream of data 'text' to the B byte string resulting
     52 	 * from step (2)
     53 	 * (4) apply H to the stream generated in step (3)
     54 	 */
     55 	sha256_init(&ctx->sha);
     56 	sha256_update(&ctx->sha, k_ipad, HMAC_SHA256_BLOCKSIZE);
     57 
     58 	/*
     59 	 * (5) XOR (bitwise exclusive-OR) the B byte string computed in
     60 	 * step (1) with opad
     61 	 */
     62 	xor_block(ctx->k_opad, IPAD^OPAD);
     63 }
     64 
     65 void hmac_sha256_update(struct hmac_sha256_ctx *ctx, const void *p, size_t size)
     66 {
     67 	/* This is the appending-text part of this:
     68 	 *
     69 	 * (3) append the stream of data 'text' to the B byte string resulting
     70 	 * from step (2)
     71 	 * (4) apply H to the stream generated in step (3)
     72 	 */
     73 	sha256_update(&ctx->sha, p, size);
     74 }
     75 
     76 void hmac_sha256_done(struct hmac_sha256_ctx *ctx,
     77 		      struct hmac_sha256 *hmac)
     78 {
     79 	/* (4) apply H to the stream generated in step (3) */
     80 	sha256_done(&ctx->sha, &hmac->sha);
     81 
     82 	/*
     83 	 * (6) append the H result from step (4) to the B byte string
     84 	 * resulting from step (5)
     85 	 * (7) apply H to the stream generated in step (6) and output
     86 	 * the result
     87 	 */
     88 	sha256_init(&ctx->sha);
     89 	sha256_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad));
     90 	sha256_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha));
     91 	sha256_done(&ctx->sha, &hmac->sha);
     92 }
     93 
     94 #if 1
     95 void hmac_sha256(struct hmac_sha256 *hmac,
     96 		 const void *k, size_t ksize,
     97 		 const void *d, size_t dsize)
     98 {
     99 	struct hmac_sha256_ctx ctx;
    100 
    101 	hmac_sha256_init(&ctx, k, ksize);
    102 	hmac_sha256_update(&ctx, d, dsize);
    103 	hmac_sha256_done(&ctx, hmac);
    104 }
    105 #else
    106 /* Direct mapping from MD5 example in RFC2104 */
    107 void hmac_sha256(struct hmac_sha256 *hmac,
    108 		 const void *key, size_t key_len,
    109 		 const void *text, size_t text_len)
    110 {
    111 	struct sha256_ctx context;
    112         unsigned char k_ipad[65];    /* inner padding -
    113                                       * key XORd with ipad
    114                                       */
    115         unsigned char k_opad[65];    /* outer padding -
    116                                       * key XORd with opad
    117                                       *//* start out by storing key in pads */
    118 	unsigned char tk[32];
    119         int i;
    120 
    121         /* if key is longer than 64 bytes reset it to key=MD5(key) */
    122         if (key_len > 64) {
    123 
    124                 struct sha256_ctx      tctx;
    125 
    126                 sha256_init(&tctx);
    127                 sha256_update(&tctx, key, key_len);
    128                 sha256_done(&tctx, tk);
    129 
    130                 key = tk;
    131                 key_len = 32;
    132         }
    133         bzero( k_ipad, sizeof k_ipad);
    134         bzero( k_opad, sizeof k_opad);
    135         bcopy( key, k_ipad, key_len);
    136         bcopy( key, k_opad, key_len);
    137 
    138         /* XOR key with ipad and opad values */
    139         for (i=0; i<64; i++) {
    140                 k_ipad[i] ^= 0x36;
    141                 k_opad[i] ^= 0x5c;
    142         }
    143         /*
    144          * perform inner MD5
    145          */
    146         sha256_init(&context);                   /* init context for 1st
    147                                               * pass */
    148         sha256_update(&context, k_ipad, 64);      /* start with inner pad */
    149         sha256_update(&context, text, text_len); /* then text of datagram */
    150         sha256_done(&context, &hmac->sha);          /* finish up 1st pass */
    151         /*
    152          * perform outer MD5
    153          */
    154         sha256_init(&context);                   /* init context for 2nd
    155                                               * pass */
    156         sha256_update(&context, k_opad, 64);     /* start with outer pad */
    157         sha256_update(&context, &hmac->sha, 32);     /* then results of 1st
    158                                               * hash */
    159         sha256_done(&context, &hmac->sha);          /* finish up 2nd pass */
    160 }
    161 #endif