MD5 and SHA1 hashes.
DIRS+=ucw/doc
-UCW_DOCS=fastbuf index basecode
+UCW_DOCS=fastbuf index basecode hash
UCW_INDEX=$(o)/ucw/doc/def_index.html
$(UCW_INDEX): DOC_HEAD=$(s)/ucw/doc/def_index.txt
--- /dev/null
+Hashing routines
+================
+
+Libucw contains two hash algorithms, MD5 (RFC 1321) and SHA1 (RFC
+3174).
+
+- <<md5,MD5>>
+- <<sha1,SHA1>>
+- <<usage,Usage>>
+
+[[md5]]
+MD5
+---
+!!ucw/md5.h
+
+[[sha1]]
+SHA1
+----
+!!ucw/sha1.h
+
+[[usage]]
+Usage
+-----
+
+There are two ways you can use the hashing routines.
+
+- Single-shot interface. If you have an in-memory buffer of the whole
+ message you want to hash, you can use this.
+
+ char *message = "Hello world";
+ byte output[MD5_SIZE];
+ md5_hash_buffer(output, message, strlen(message));
+
+- Multi-shot interface. If you have the message scattered in many
+ buffers or you get it by parts, you do not need to concatenate the
+ parts together.
+
+ byte buffer[MAX_BUFFER];
+ uns buffer_len;
+ md5_context c;
+ md5_init(&c);
+ while(buffer_len = get_chunk(buffer, MAX_BUFFER)) {
+ md5_update(&c, buffer, buffer_len);
+ }
+ byte output[MD5_SIZE];
+ memcpy(output, md5_final(&c), MD5_SIZE);
+
+SHA1 has the same interface, so both ways work to it as well.
+
+See also <<string:mem_to_hex()>>.
-------
- <<fastbuf:,Fastbufs>>
- <<basecode:,Base64 and Base224 encoding>>
+- <<hash:,Hashing routines>>
#ifndef _UCW_MD5_H
#define _UCW_MD5_H
+/**
+ * Internal MD5 hash state.
+ * You can use it just as a opaque handle.
+ */
typedef struct {
u32 buf[4];
u32 bits[2];
byte in[64];
} md5_context;
-void md5_init(md5_context *context);
+void md5_init(md5_context *context); /** Initialize the MD5 hashing algorithm in @context. **/
+/**
+ * Push another @len bytes of data from @buf to the MD5 hash
+ * represented by @context. You can call it multiple time on the same
+ * @context without reinitializing it and the result will be the same
+ * as you concatenated all the data together and fed them here all at
+ * once.
+ */
void md5_update(md5_context *context, const byte *buf, uns len);
-/* The data are stored inside the context */
+/**
+ * Call this after the last md5_update(). It will terminate the
+ * algorithm and return pointer to the result.
+ *
+ * Note that the data it points to are stored inside the @context, so
+ * if you use it to compute another hash or it ceases to exist, the
+ * pointer becomes invalid.
+ */
byte *md5_final(md5_context *context);
+/**
+ * This is the core routine of MD5 algorithm. It takes 16 longwords of
+ * data in @in and transforms the hash in @buf according to them.
+ *
+ * You probably do not want to call this one directly.
+ */
void md5_transform(u32 buf[4], const u32 in[16]);
-/* One-shot interface */
+/**
+ * MD5 one-shot convenience method. It takes @length bytes from
+ * @buffer, creates the hash from them and returns it in @output.
+ *
+ * It is equivalent to this code:
+ * md5_context c;
+ * md5_init(&c);
+ * md5_update(&c, buffer, length);
+ * memcpy(outbuf, md5_final(&c), MD5_SIZE);
+ */
void md5_hash_buffer(byte *outbuf, const byte *buffer, uns length);
-#define MD5_HEX_SIZE 33
-#define MD5_SIZE 16
+#define MD5_HEX_SIZE 33 /** How many bytes a string buffer for MD5 in hexadecimal format should have. **/
+#define MD5_SIZE 16 /** Number of bytes the MD5 hash takes in the binary form. **/
#endif /* !_UCW_MD5_H */
#ifndef _UCW_SHA1_H
#define _UCW_SHA1_H
+/**
+ * Internal SHA1 state.
+ * You can consider it an opaque handle, if you want just hash
+ * functions.
+ */
typedef struct {
u32 h0,h1,h2,h3,h4;
u32 nblocks;
int count;
} sha1_context;
-void sha1_init(sha1_context *hd);
+void sha1_init(sha1_context *hd); /** Initialize new algorithm run in the @hd context. **/
+/**
+ * Push another @inlen bytes of data pointed to by @inbuf onto the
+ * SHA1 hash currently in @hd. You can call this any times you want on
+ * the same hash (and you do not need to reinitialize it by
+ * sha1_init()). It has the same effect as concatenating all the data
+ * together and passing them at once.
+ */
void sha1_update(sha1_context *hd, const byte *inbuf, uns inlen);
+/**
+ * No more sha1_update() calls will be done. This terminates the hash
+ * and returns pointer to it.
+ *
+ * Note the pointer points into data in the @hd context. If it ceases
+ * to exist, the pointer becomes invalid.
+ */
byte *sha1_final(sha1_context *hd);
-/* One-shot interface */
+/**
+ * Convenience one-shot function for SHA1 hash.
+ * It is equivalent to this snippet of code:
+ *
+ * sha1_context hd;
+ * sha1_init(&hd);
+ * sha1_update(&hd, buffer, length);
+ * memcpy(outbuf, sha1_final(&hd), 20);
+ */
void sha1_hash_buffer(byte *outbuf, const byte *buffer, uns length);
-/* HMAC */
+/**
+ * SHA1 HMAC message authentication. If you provide @key and @data,
+ * the result will be stored in @outbuf.
+ */
void sha1_hmac(byte *outbuf, const byte *key, uns keylen, const byte *data, uns datalen);
-#define SHA1_SIZE 20
-#define SHA1_HEX_SIZE 41
-#define SHA1_BLOCK_SIZE 64
+#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. **/
#endif