]> mj.ucw.cz Git - libucw.git/blob - ucw/sha1-hmac.c
ucw docs: base64 & base224
[libucw.git] / ucw / sha1-hmac.c
1 /*
2  *      HMAC-SHA1 Message Authentication Code (RFC 2202)
3  *
4  *      (c) 2008 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include "ucw/lib.h"
11 #include "ucw/sha1.h"
12
13 #include <string.h>
14
15 void
16 sha1_hmac(byte *outbuf, const byte *key, uns keylen, const byte *data, uns datalen)
17 {
18   sha1_context ictx, octx;
19   byte keybuf[SHA1_BLOCK_SIZE], buf[SHA1_BLOCK_SIZE];
20
21   // Hash the key if necessary
22   if (keylen <= SHA1_BLOCK_SIZE)
23     {
24       memcpy(keybuf, key, keylen);
25       bzero(keybuf + keylen, SHA1_BLOCK_SIZE - keylen);
26     }
27   else
28     {
29       sha1_hash_buffer(keybuf, key, keylen);
30       bzero(keybuf + SHA1_SIZE, SHA1_BLOCK_SIZE - SHA1_SIZE);
31     }
32
33   // The inner digest
34   sha1_init(&ictx);
35   for (int i=0; i < SHA1_BLOCK_SIZE; i++)
36     buf[i] = keybuf[i] ^ 0x36;
37   sha1_update(&ictx, buf, SHA1_BLOCK_SIZE);
38   sha1_update(&ictx, data, datalen);
39   byte *isha = sha1_final(&ictx);
40
41   // The outer digest
42   sha1_init(&octx);
43   for (int i=0; i < SHA1_BLOCK_SIZE; i++)
44     buf[i] = keybuf[i] ^ 0x5c;
45   sha1_update(&octx, buf, SHA1_BLOCK_SIZE);
46   sha1_update(&octx, isha, SHA1_SIZE);
47   byte *osha = sha1_final(&octx);
48
49   // Copy the result
50   memcpy(outbuf, osha, SHA1_SIZE);
51 }
52
53 #ifdef TEST
54
55 #include <stdio.h>
56 #include "ucw/string.h"
57
58 static uns rd(char *dest)
59 {
60   char buf[1024];
61   fgets(buf, sizeof(buf), stdin);
62   *strchr(buf, '\n') = 0;
63   if (buf[0] == '0' && buf[1] == 'x')
64     {
65       const char *e = hex_to_mem(dest, buf+2, 1024, 0);
66       ASSERT(!*e);
67       return (e-buf-2)/2;
68     }
69   else
70     {
71       strcpy(dest, buf);
72       return strlen(dest);
73     }
74 }
75
76 int main(void)
77 {
78   char key[1024], data[1024];
79   byte hmac[SHA1_SIZE];
80   uns kl = rd(key);
81   uns dl = rd(data);
82   sha1_hmac(hmac, key, kl, data, dl);
83   mem_to_hex(data, hmac, SHA1_SIZE, 0);
84   puts(data);
85   return 0;
86 }
87
88 #endif