]> mj.ucw.cz Git - libucw.git/commitdiff
SHA1: Added stream interface for the HMAC, too.
authorMartin Mares <mj@ucw.cz>
Sun, 25 Jan 2009 12:55:14 +0000 (13:55 +0100)
committerMartin Mares <mj@ucw.cz>
Sun, 25 Jan 2009 12:55:14 +0000 (13:55 +0100)
ucw/sha1-hmac.c
ucw/sha1.h

index 2c4ee1247e5e4e75077a8d54d12628d39fa88ea5..182c891a0de17ce2262ce48176968327f99dce71 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     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.
@@ -13,9 +13,8 @@
 #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
@@ -30,23 +29,43 @@ sha1_hmac(byte *outbuf, const byte *key, uns keylen, const byte *data, uns datal
       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);
 }
 
index 2527e09a72f5e5204bef389aca83d1dda956428f..4b17da548c97c6eaf98b158dddd2a28f7e6a43b4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     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:
  *
@@ -63,6 +63,19 @@ void sha1_hash_buffer(byte *outbuf, const byte *buffer, uns length);
  */
 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. **/