source: lib/sha1.c @ 34afea7

Last change on this file since 34afea7 was 34afea7, checked in by dequis <dx@…>, at 2015-01-31T23:58:57Z

Use glib's GChecksum for md5/sha1

This changes behavior slightly:

  • md5_init()/sha1_init() allocate a GChecksum
  • md5_finish()/sha1_finish() close and free() it
  • md5_digest_keep() was added (no sha1 equivalent needed)

And yes, glib has this concept of "closing" the GChecksum, which means
it can't be used anymore after g_checksum_get_digest().

jabber_cache_add() actually seems to need to do that to generate some
random-ish values, so i kept that working by adding a md5_digest_keep()
function that copies the GChecksum before it gets closed

GChecksum was introduced in glib 2.16, so the configure script version
was bumped. We were already depending on glib 2.16 accidentally
(some post-3.2.2 code uses GHashTableIter)

  • Property mode set to 100644
File size: 2.4 KB
Line 
1#include "sha1.h"
2#include <string.h>
3#include <stdio.h>
4
5
6void sha1_init(sha1_state_t *ctx)
7{
8        *ctx = g_checksum_new(G_CHECKSUM_SHA1);
9}
10
11void sha1_append(sha1_state_t *ctx, const guint8 * message_array, guint len)
12{
13        g_checksum_update(*ctx, message_array, len);
14}
15
16void sha1_finish(sha1_state_t *ctx, guint8 digest[SHA1_HASH_SIZE])
17{
18        gsize digest_len = SHA1_HASH_SIZE;
19        g_checksum_get_digest(*ctx, digest, &digest_len);
20        g_checksum_free(*ctx);
21}
22
23#define HMAC_BLOCK_SIZE 64
24
25/* BitlBee addition: */
26void sha1_hmac(const char *key_, size_t key_len, const char *payload, size_t payload_len, guint8 digest[SHA1_HASH_SIZE])
27{
28        sha1_state_t sha1;
29        guint8 hash[SHA1_HASH_SIZE];
30        guint8 key[HMAC_BLOCK_SIZE+1];
31        int i;
32       
33        if( key_len == 0 )
34                key_len = strlen( key_ );
35        if( payload_len == 0 )
36                payload_len = strlen( payload );
37       
38        /* Create K. If our current key is >64 chars we have to hash it,
39           otherwise just pad. */
40        memset( key, 0, HMAC_BLOCK_SIZE + 1 );
41        if( key_len > HMAC_BLOCK_SIZE )
42        {
43                sha1_init( &sha1 );
44                sha1_append( &sha1, (guint8*) key_, key_len );
45                sha1_finish( &sha1, key );
46        }
47        else
48        {
49                memcpy( key, key_, key_len );
50        }
51       
52        /* Inner part: H(K XOR 0x36, text) */
53        sha1_init( &sha1 );
54        for( i = 0; i < HMAC_BLOCK_SIZE; i ++ )
55                key[i] ^= 0x36;
56        sha1_append( &sha1, key, HMAC_BLOCK_SIZE );
57        sha1_append( &sha1, (const guint8*) payload, payload_len );
58        sha1_finish( &sha1, hash );
59       
60        /* Final result: H(K XOR 0x5C, inner stuff) */
61        sha1_init( &sha1 );
62        for( i = 0; i < HMAC_BLOCK_SIZE; i ++ )
63                key[i] ^= 0x36 ^ 0x5c;
64        sha1_append( &sha1, key, HMAC_BLOCK_SIZE );
65        sha1_append( &sha1, hash, SHA1_HASH_SIZE );
66        sha1_finish( &sha1, digest );
67}
68
69/* I think this follows the scheme described on:
70   http://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29
71   My random data comes from a SHA1 generator but hey, it's random enough for
72   me, and RFC 4122 looks way more complicated than I need this to be.
73   
74   Returns a value that must be free()d. */
75char *sha1_random_uuid( sha1_state_t * context )
76{
77        guint8 dig[SHA1_HASH_SIZE];
78        char *ret = g_new0( char, 40 ); /* 36 chars + \0 */
79        int i, p;
80       
81        sha1_finish(context, dig);
82        for( p = i = 0; i < 16; i ++ )
83        {
84                if( i == 4 || i == 6 || i == 8 || i == 10 )
85                        ret[p++] = '-';
86                if( i == 6 )
87                        dig[i] = ( dig[i] & 0x0f ) | 0x40;
88                if( i == 8 )
89                        dig[i] = ( dig[i] & 0x30 ) | 0x80;
90               
91                sprintf( ret + p, "%02x", dig[i] );
92                p += 2;
93        }
94        ret[p] = '\0';
95       
96        return ret;
97}
Note: See TracBrowser for help on using the repository browser.