/*
* HMAC-SHA1 Message Authentication Code (RFC 2202)
*
- * (c) 2008 Martin Mares <mj@ucw.cz>
+ * (c) 2008--2009 Martin Mares <mj@ucw.cz>
*
* This software may be freely distributed and used according to the terms
* of the GNU Lesser General Public License.
#include <string.h>
void
-sha1_hmac(byte *outbuf, const byte *key, uns keylen, const byte *data, uns datalen)
+sha1_hmac_init(sha1_hmac_context *hd, const byte *key, uns keylen)
{
- sha1_context ictx, octx;
byte keybuf[SHA1_BLOCK_SIZE], buf[SHA1_BLOCK_SIZE];
// Hash the key if necessary
bzero(keybuf + SHA1_SIZE, SHA1_BLOCK_SIZE - SHA1_SIZE);
}
- // The inner digest
- sha1_init(&ictx);
+ // Initialize the inner digest
+ sha1_init(&hd->ictx);
for (int i=0; i < SHA1_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x36;
- sha1_update(&ictx, buf, SHA1_BLOCK_SIZE);
- sha1_update(&ictx, data, datalen);
- byte *isha = sha1_final(&ictx);
+ sha1_update(&hd->ictx, buf, SHA1_BLOCK_SIZE);
- // The outer digest
- sha1_init(&octx);
+ // Initialize the outer digest
+ sha1_init(&hd->octx);
for (int i=0; i < SHA1_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x5c;
- sha1_update(&octx, buf, SHA1_BLOCK_SIZE);
- sha1_update(&octx, isha, SHA1_SIZE);
- byte *osha = sha1_final(&octx);
+ sha1_update(&hd->octx, buf, SHA1_BLOCK_SIZE);
+}
- // Copy the result
+void
+sha1_hmac_update(sha1_hmac_context *hd, const byte *data, uns datalen)
+{
+ // Just update the inner digest
+ sha1_update(&hd->ictx, data, datalen);
+}
+
+byte *sha1_hmac_final(sha1_hmac_context *hd)
+{
+ // Finish the inner digest
+ byte *isha = sha1_final(&hd->ictx);
+
+ // Finish the outer digest
+ sha1_update(&hd->octx, isha, SHA1_SIZE);
+ return sha1_final(&hd->octx);
+}
+
+void
+sha1_hmac(byte *outbuf, const byte *key, uns keylen, const byte *data, uns datalen)
+{
+ sha1_hmac_context hd;
+ sha1_hmac_init(&hd, key, keylen);
+ sha1_hmac_update(&hd, data, datalen);
+ byte *osha = sha1_hmac_final(&hd);
memcpy(outbuf, osha, SHA1_SIZE);
}
/*
* SHA-1 Hash Function (FIPS 180-1, RFC 3174)
*
- * (c) 2008 Martin Mares <mj@ucw.cz>
+ * (c) 2008--2009 Martin Mares <mj@ucw.cz>
*
* Based on the code from libgcrypt-1.2.3, which was:
*
*/
void sha1_hmac(byte *outbuf, const byte *key, uns keylen, const byte *data, uns datalen);
+/**
+ * The HMAC also exists in a stream version in a way analogous to the
+ * plain SHA1. Pass this as a context.
+ */
+typedef struct {
+ sha1_context ictx;
+ sha1_context octx;
+} sha1_hmac_context;
+
+void sha1_hmac_init(sha1_hmac_context *hd, const byte *key, uns keylen); /** Initialize HMAC with context @hd and the given key. See sha1_init(). */
+void sha1_hmac_update(sha1_hmac_context *hd, const byte *data, uns datalen); /** Hash another @datalen bytes of data. See sha1_update(). */
+byte *sha1_hmac_final(sha1_hmac_context *hd); /** Terminate the HMAC and return a pointer to the allocated hash. See sha1_final(). */
+
#define SHA1_SIZE 20 /** Size of the SHA1 hash in its binary representation **/
#define SHA1_HEX_SIZE 41 /** Buffer length for a string containing SHA1 in hexadecimal format. **/
#define SHA1_BLOCK_SIZE 64 /** SHA1 splits input to blocks of this size. **/