| 1 | Cryptographic hash functions |
| 2 | |
| 3 | |
| 4 | Hash functions are very useful cryptographic primitives. |
| 5 | Catacomb provides a few of the best-known cryptographic hashes. |
| 6 | |
| 7 | |
| 8 | Hash function interface |
| 9 | |
| 10 | Hash functions share a regular interface. I'll take Ron |
| 11 | Rivest's MD5 as an example. |
| 12 | |
| 13 | Using a hash function is a three-stage process. You initialize |
| 14 | a context, you hash some data, and you get the result out of the |
| 15 | end. The data to be hashed need not be contiguous, and you |
| 16 | don't have to have it all before you start. Hash function |
| 17 | contexts don't use up lots of memory. |
| 18 | |
| 19 | An MD5 context is called `md5_ctx'. You initialize it with |
| 20 | `md5_init'. You hash a block of data using `md5_hash' giving it |
| 21 | the context, the pointer to the data and its length. Finally, |
| 22 | you extract the data using `md5_done', giving it the address of |
| 23 | a buffer of MD5_HASHSZ bytes for it to write the result. |
| 24 | |
| 25 | There are some other standard operations as well, but they're |
| 26 | not often used: see the header files for details. |
| 27 | |
| 28 | The hash functions supported are: |
| 29 | |
| 30 | MD4 By Ron Rivest -- returns a 128-bit hash. MD4 is |
| 31 | not collision-resistant, and may not even be |
| 32 | second-preimage-resistant. Don't depend on its |
| 33 | security. On the other hand, MD4 is *very* |
| 34 | fast. |
| 35 | |
| 36 | MD5 Also by Rivest, also returns a 128-bit hash. |
| 37 | MD5 is slower than MD4, and more conservative, |
| 38 | but there are still grave doubts about its |
| 39 | security. |
| 40 | |
| 41 | SHA1 Designed by the US National Security Agency. |
| 42 | Returns a 160-bit hash. Slower than MD5. Looks |
| 43 | strong. Fixes a problem in the earlier SHA. |
| 44 | |
| 45 | RIPEMD-160 Designed by the people who broke MD4 and MD5. |
| 46 | Returns a 160-bit hash. Slower than SHA1. My |
| 47 | personal preference. |
| 48 | |
| 49 | |
| 50 | HMAC interface |
| 51 | |
| 52 | It's possible to construct a `keyed hash' or `message |
| 53 | authentication code' from a hash function. Most methods for |
| 54 | doing this are insecure. HMAC is a good method, with rigorously |
| 55 | proven security properties. |
| 56 | |
| 57 | Each hash function above has an HMAC mode defined for it. This |
| 58 | works much the same way as block cipher modes. |
| 59 | |
| 60 | Using HMAC is a two-step process. First, you initialize a MAC |
| 61 | key block `mackey' to contain the key you'll use, and then you |
| 62 | initialize MAC contexts `macctx' which to actually hash the |
| 63 | data. Hashing works just the same as the basic hash function, |
| 64 | except that you use `macinit', `machash' and `macdone' functions |
| 65 | rather than the plain `init', `hash' and `done'. |
| 66 | |
| 67 | |
| 68 | Generic interfaces |
| 69 | |
| 70 | Generic interfaces to hash functions and MACs are provided. See |
| 71 | README.cipher to get an idea for how a similar generic interface |
| 72 | works -- I'll only explain the differences here. |
| 73 | |
| 74 | The generic hash object, `ghash' contains an `ops' member |
| 75 | referring to: |
| 76 | |
| 77 | h->ops->b->name The name of the hash function. |
| 78 | |
| 79 | h->ops->b->hashsz The output size of the hash function. |
| 80 | |
| 81 | h->ops->hash(h, p, sz) Hash sz bytes of data starting at |
| 82 | address p. |
| 83 | |
| 84 | h->ops->done(h, b) Stop hashing, write the result to buffer |
| 85 | b with size `hashsz'. |
| 86 | |
| 87 | h->ops->destroy(h) Destroy the generic hash object. |
| 88 | |
| 89 | The generic hash class, `gchash', contains a base which has the |
| 90 | same members as `ops->b' above, and an `init' function which |
| 91 | takes no arguments and returns a pointer to a `ghash'. |
| 92 | |
| 93 | There's a generic MAC interface too. A MAC class, `gcmac' |
| 94 | contains a hash base (exactly the same, but with a different |
| 95 | name), and a function `key' which takes a pointer to some key |
| 96 | data and the key size, and returns a pointer to a `generic mac' |
| 97 | object, `gmac'. |
| 98 | |
| 99 | A `gmac' contains an `ops' member: |
| 100 | |
| 101 | m->ops->b->name, m->ops->b->hashsz |
| 102 | As above. |
| 103 | |
| 104 | m->ops->init(m) Returns a generic *hash* object to |
| 105 | actually compute a MAC over some data. |
| 106 | |
| 107 | m->ops->destroy(m) Destroys the generic MAC block. |
| 108 | |
| 109 | |
| 110 | That was quite complex. Here's an example of using a generic |
| 111 | MAC. |
| 112 | |
| 113 | void compute_mac(gcmac *gcm, const void *k, size_t ksz, |
| 114 | const void *p, size_t sz, |
| 115 | void *hash) |
| 116 | { |
| 117 | gmac *m = gcm->init(k, ksz); |
| 118 | ghash *h = m->ops->init(m); |
| 119 | m->ops->destroy(m); |
| 120 | h->ops->hash(h, p, sz); |
| 121 | h->ops->done(h, hash); |
| 122 | h->ops->destroy(h); |
| 123 | } |
| 124 | |
| 125 | Note that the hash doesn't depend on the MAC object continuing |
| 126 | to exist. |
| 127 | |
| 128 | -- [mdw] |
| 129 | |
| 130 | \f |
| 131 | Local variables: |
| 132 | mode: text |
| 133 | End: |