]> mj.ucw.cz Git - libucw.git/blob - ucw/sha1-hmac.c
Merge branch 'master' into dev-lib
[libucw.git] / ucw / sha1-hmac.c
1 /*
2  *      HMAC-SHA1 Message Authentication Code (RFC 2202)
3  *
4  *      (c) 2008--2009 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_init(sha1_hmac_context *hd, const byte *key, uns keylen)
17 {
18   byte keybuf[SHA1_BLOCK_SIZE], buf[SHA1_BLOCK_SIZE];
19
20   // Hash the key if necessary
21   if (keylen <= SHA1_BLOCK_SIZE)
22     {
23       memcpy(keybuf, key, keylen);
24       bzero(keybuf + keylen, SHA1_BLOCK_SIZE - keylen);
25     }
26   else
27     {
28       sha1_hash_buffer(keybuf, key, keylen);
29       bzero(keybuf + SHA1_SIZE, SHA1_BLOCK_SIZE - SHA1_SIZE);
30     }
31
32   // Initialize the inner digest
33   sha1_init(&hd->ictx);
34   for (int i=0; i < SHA1_BLOCK_SIZE; i++)
35     buf[i] = keybuf[i] ^ 0x36;
36   sha1_update(&hd->ictx, buf, SHA1_BLOCK_SIZE);
37
38   // Initialize the outer digest
39   sha1_init(&hd->octx);
40   for (int i=0; i < SHA1_BLOCK_SIZE; i++)
41     buf[i] = keybuf[i] ^ 0x5c;
42   sha1_update(&hd->octx, buf, SHA1_BLOCK_SIZE);
43 }
44
45 void
46 sha1_hmac_update(sha1_hmac_context *hd, const byte *data, uns datalen)
47 {
48   // Just update the inner digest
49   sha1_update(&hd->ictx, data, datalen);
50 }
51
52 byte *sha1_hmac_final(sha1_hmac_context *hd)
53 {
54   // Finish the inner digest
55   byte *isha = sha1_final(&hd->ictx);
56
57   // Finish the outer digest
58   sha1_update(&hd->octx, isha, SHA1_SIZE);
59   return sha1_final(&hd->octx);
60 }
61
62 void
63 sha1_hmac(byte *outbuf, const byte *key, uns keylen, const byte *data, uns datalen)
64 {
65   sha1_hmac_context hd;
66   sha1_hmac_init(&hd, key, keylen);
67   sha1_hmac_update(&hd, data, datalen);
68   byte *osha = sha1_hmac_final(&hd);
69   memcpy(outbuf, osha, SHA1_SIZE);
70 }
71
72 #ifdef TEST
73
74 #include <stdio.h>
75 #include "ucw/string.h"
76
77 static uns rd(char *dest)
78 {
79   char buf[1024];
80   fgets(buf, sizeof(buf), stdin);
81   *strchr(buf, '\n') = 0;
82   if (buf[0] == '0' && buf[1] == 'x')
83     {
84       const char *e = hex_to_mem(dest, buf+2, 1024, 0);
85       ASSERT(!*e);
86       return (e-buf-2)/2;
87     }
88   else
89     {
90       strcpy(dest, buf);
91       return strlen(dest);
92     }
93 }
94
95 int main(void)
96 {
97   char key[1024], data[1024];
98   byte hmac[SHA1_SIZE];
99   uns kl = rd(key);
100   uns dl = rd(data);
101   sha1_hmac(hmac, key, kl, data, dl);
102   mem_to_hex(data, hmac, SHA1_SIZE, 0);
103   puts(data);
104   return 0;
105 }
106
107 #endif