source: lib/sha1.c @ aef2077

Last change on this file since aef2077 was e0a0a42, checked in by Wilmer van der Gaast <wilmer@…>, at 2012-02-10T13:37:08Z

Added sha1_random_uuid function, which I will use later to generate random
Jabber roomnames.

  • Property mode set to 100644
File size: 11.2 KB
RevLine 
[77bfd07]1/*
2 * SHA1 hashing code copied from Lepton's crack <http://usuarios.lycos.es/reinob/>
3 *
4 * Adapted to be API-compatible with the previous (GPL-incompatible) code.
5 */
6
7/*
8 *  sha1.c
9 *
10 *  Description:
11 *      This file implements the Secure Hashing Algorithm 1 as
12 *      defined in FIPS PUB 180-1 published April 17, 1995.
13 *
14 *      The SHA-1, produces a 160-bit message digest for a given
15 *      data stream.  It should take about 2**n steps to find a
16 *      message with the same digest as a given message and
17 *      2**(n/2) to find any two messages with the same digest,
18 *      when n is the digest size in bits.  Therefore, this
19 *      algorithm can serve as a means of providing a
20 *      "fingerprint" for a message.
21 *
22 *  Portability Issues:
23 *      SHA-1 is defined in terms of 32-bit "words".  This code
24 *      uses <stdint.h> (included via "sha1.h" to define 32 and 8
25 *      bit unsigned integer types.  If your C compiler does not
26 *      support 32 bit unsigned integers, this code is not
27 *      appropriate.
28 *
29 *  Caveats:
30 *      SHA-1 is designed to work with messages less than 2^64 bits
31 *      long.  Although SHA-1 allows a message digest to be generated
32 *      for messages of any number of bits less than 2^64, this
33 *      implementation only works with messages with a length that is
34 *      a multiple of the size of an 8-bit character.
35 *
36 */
37
[523fb23]38#include <string.h>
[e0a0a42]39#include <stdio.h>
[77bfd07]40#include "sha1.h"
41
42/*
43 *  Define the SHA1 circular left shift macro
44 */
45#define SHA1CircularShift(bits,word) \
46       (((word) << (bits)) | ((word) >> (32-(bits))))
47
48/* Local Function Prototyptes */
49static void sha1_pad(sha1_state_t *);
50static void sha1_process_block(sha1_state_t *);
51
52/*
53 *  sha1_init
54 *
55 *  Description:
56 *      This function will initialize the sha1_state_t in preparation
57 *      for computing a new SHA1 message digest.
58 *
59 *  Parameters:
60 *      context: [in/out]
61 *          The context to reset.
62 *
63 *  Returns:
64 *      sha Error Code.
65 *
66 */
67int sha1_init(sha1_state_t * context)
68{
69        context->Length_Low = 0;
70        context->Length_High = 0;
71        context->Message_Block_Index = 0;
72
73        context->Intermediate_Hash[0] = 0x67452301;
74        context->Intermediate_Hash[1] = 0xEFCDAB89;
75        context->Intermediate_Hash[2] = 0x98BADCFE;
76        context->Intermediate_Hash[3] = 0x10325476;
77        context->Intermediate_Hash[4] = 0xC3D2E1F0;
78
79        context->Computed = 0;
80        context->Corrupted = 0;
81       
82        return shaSuccess;
83}
84
85/*
86 *  sha1_finish
87 *
88 *  Description:
89 *      This function will return the 160-bit message digest into the
90 *      Message_Digest array  provided by the caller.
91 *      NOTE: The first octet of hash is stored in the 0th element,
92 *            the last octet of hash in the 19th element.
93 *
94 *  Parameters:
95 *      context: [in/out]
96 *          The context to use to calculate the SHA-1 hash.
97 *      Message_Digest: [out]
98 *          Where the digest is returned.
99 *
100 *  Returns:
101 *      sha Error Code.
102 *
103 */
104int sha1_finish(sha1_state_t * context, uint8_t Message_Digest[sha1_hash_size])
105{
106        int i;
107
108        if (!context || !Message_Digest) {
109                return shaNull;
110        }
111
112        if (context->Corrupted) {
113                return context->Corrupted;
114        }
115
116        if (!context->Computed) {
117                sha1_pad(context);
118                for (i = 0; i < 64; ++i) {
119                        /* message may be sensitive, clear it out */
120                        context->Message_Block[i] = 0;
121                }
122                context->Length_Low = 0;        /* and clear length */
123                context->Length_High = 0;
124                context->Computed = 1;
125
126        }
127
128        for (i = 0; i < sha1_hash_size; ++i) {
129                Message_Digest[i] = context->Intermediate_Hash[i >> 2]
130                    >> 8 * (3 - (i & 0x03));
131        }
132
133        return shaSuccess;
134}
135
136/*
137 *  sha1_append
138 *
139 *  Description:
140 *      This function accepts an array of octets as the next portion
141 *      of the message.
142 *
143 *  Parameters:
144 *      context: [in/out]
145 *          The SHA context to update
146 *      message_array: [in]
147 *          An array of characters representing the next portion of
148 *          the message.
149 *      length: [in]
150 *          The length of the message in message_array
151 *
152 *  Returns:
153 *      sha Error Code.
154 *
155 */
156int
157sha1_append(sha1_state_t * context,
158          const uint8_t * message_array, unsigned length)
159{
160        if (!length) {
161                return shaSuccess;
162        }
163
164        if (!context || !message_array) {
165                return shaNull;
166        }
167
168        if (context->Computed) {
169                context->Corrupted = shaStateError;
170
171                return shaStateError;
172        }
173
174        if (context->Corrupted) {
175                return context->Corrupted;
176        }
177        while (length-- && !context->Corrupted) {
178                context->Message_Block[context->Message_Block_Index++] =
179                    (*message_array & 0xFF);
180
181                context->Length_Low += 8;
182                if (context->Length_Low == 0) {
183                        context->Length_High++;
184                        if (context->Length_High == 0) {
185                                /* Message is too long */
186                                context->Corrupted = 1;
187                        }
188                }
189
190                if (context->Message_Block_Index == 64) {
191                        sha1_process_block(context);
192                }
193
194                message_array++;
195        }
196
197        return shaSuccess;
198}
199
200/*
201 *  sha1_process_block
202 *
203 *  Description:
204 *      This function will process the next 512 bits of the message
205 *      stored in the Message_Block array.
206 *
207 *  Parameters:
208 *      None.
209 *
210 *  Returns:
211 *      Nothing.
212 *
213 *  Comments:
214 *      Many of the variable names in this code, especially the
215 *      single character names, were used because those were the
216 *      names used in the publication.
217 *
218 *
219 */
220static void sha1_process_block(sha1_state_t * context)
221{
222        const uint32_t K[] = {  /* Constants defined in SHA-1   */
223                0x5A827999,
224                0x6ED9EBA1,
225                0x8F1BBCDC,
226                0xCA62C1D6
227        };
228        int t;                  /* Loop counter                */
229        uint32_t temp;          /* Temporary word value        */
230        uint32_t W[80];         /* Word sequence               */
231        uint32_t A, B, C, D, E; /* Word buffers                */
232
233        /*
234         *  Initialize the first 16 words in the array W
235         */
236        for (t = 0; t < 16; t++) {
237                W[t] = context->Message_Block[t * 4] << 24;
238                W[t] |= context->Message_Block[t * 4 + 1] << 16;
239                W[t] |= context->Message_Block[t * 4 + 2] << 8;
240                W[t] |= context->Message_Block[t * 4 + 3];
241        }
242
243        for (t = 16; t < 80; t++) {
244                W[t] =
245                    SHA1CircularShift(1,
246                                      W[t - 3] ^ W[t - 8] ^ W[t -
247                                                              14] ^ W[t -
248                                                                      16]);
249        }
250
251        A = context->Intermediate_Hash[0];
252        B = context->Intermediate_Hash[1];
253        C = context->Intermediate_Hash[2];
254        D = context->Intermediate_Hash[3];
255        E = context->Intermediate_Hash[4];
256
257        for (t = 0; t < 20; t++) {
258                temp = SHA1CircularShift(5, A) +
259                    ((B & C) | ((~B) & D)) + E + W[t] + K[0];
260                E = D;
261                D = C;
262                C = SHA1CircularShift(30, B);
263
264                B = A;
265                A = temp;
266        }
267
268        for (t = 20; t < 40; t++) {
269                temp =
270                    SHA1CircularShift(5,
271                                      A) + (B ^ C ^ D) + E + W[t] + K[1];
272                E = D;
273                D = C;
274                C = SHA1CircularShift(30, B);
275                B = A;
276                A = temp;
277        }
278
279        for (t = 40; t < 60; t++) {
280                temp = SHA1CircularShift(5, A) +
281                    ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
282                E = D;
283                D = C;
284                C = SHA1CircularShift(30, B);
285                B = A;
286                A = temp;
287        }
288
289        for (t = 60; t < 80; t++) {
290                temp =
291                    SHA1CircularShift(5,
292                                      A) + (B ^ C ^ D) + E + W[t] + K[3];
293                E = D;
294                D = C;
295                C = SHA1CircularShift(30, B);
296                B = A;
297                A = temp;
298        }
299
300        context->Intermediate_Hash[0] += A;
301        context->Intermediate_Hash[1] += B;
302        context->Intermediate_Hash[2] += C;
303        context->Intermediate_Hash[3] += D;
304        context->Intermediate_Hash[4] += E;
305
306        context->Message_Block_Index = 0;
307}
308
309/*
310 *  sha1_pad
311 *
312 *  Description:
313 *      According to the standard, the message must be padded to an even
314 *      512 bits.  The first padding bit must be a '1'.  The last 64
315 *      bits represent the length of the original message.  All bits in
316 *      between should be 0.  This function will pad the message
317 *      according to those rules by filling the Message_Block array
318 *      accordingly.  It will also call the ProcessMessageBlock function
319 *      provided appropriately.  When it returns, it can be assumed that
320 *      the message digest has been computed.
321 *
322 *  Parameters:
323 *      context: [in/out]
324 *          The context to pad
325 *      ProcessMessageBlock: [in]
326 *          The appropriate SHA*ProcessMessageBlock function
327 *  Returns:
328 *      Nothing.
329 *
330 */
331
332static void sha1_pad(sha1_state_t * context)
333{
334        /*
335         *  Check to see if the current message block is too small to hold
336         *  the initial padding bits and length.  If so, we will pad the
337         *  block, process it, and then continue padding into a second
338         *  block.
339         */
340        if (context->Message_Block_Index > 55) {
341                context->Message_Block[context->Message_Block_Index++] =
342                    0x80;
343                while (context->Message_Block_Index < 64) {
344                        context->Message_Block[context->
345                                               Message_Block_Index++] = 0;
346                }
347
348                sha1_process_block(context);
349
350                while (context->Message_Block_Index < 56) {
351                        context->Message_Block[context->
352                                               Message_Block_Index++] = 0;
353                }
354        } else {
355                context->Message_Block[context->Message_Block_Index++] =
356                    0x80;
357                while (context->Message_Block_Index < 56) {
358
359                        context->Message_Block[context->
360                                               Message_Block_Index++] = 0;
361                }
362        }
363
364        /*
365         *  Store the message length as the last 8 octets
366         */
367        context->Message_Block[56] = context->Length_High >> 24;
368        context->Message_Block[57] = context->Length_High >> 16;
369        context->Message_Block[58] = context->Length_High >> 8;
370        context->Message_Block[59] = context->Length_High;
371        context->Message_Block[60] = context->Length_Low >> 24;
372        context->Message_Block[61] = context->Length_Low >> 16;
373        context->Message_Block[62] = context->Length_Low >> 8;
374        context->Message_Block[63] = context->Length_Low;
375
376        sha1_process_block(context);
377}
[523fb23]378
379#define HMAC_BLOCK_SIZE 64
380
381/* BitlBee addition: */
382void sha1_hmac(const char *key_, size_t key_len, const char *payload, size_t payload_len, uint8_t Message_Digest[sha1_hash_size])
383{
384        sha1_state_t sha1;
385        uint8_t hash[sha1_hash_size];
386        uint8_t key[HMAC_BLOCK_SIZE+1];
387        int i;
388       
389        if( key_len == 0 )
390                key_len = strlen( key_ );
391        if( payload_len == 0 )
392                payload_len = strlen( payload );
393       
394        /* Create K. If our current key is >64 chars we have to hash it,
395           otherwise just pad. */
396        memset( key, 0, HMAC_BLOCK_SIZE + 1 );
397        if( key_len > HMAC_BLOCK_SIZE )
398        {
399                sha1_init( &sha1 );
400                sha1_append( &sha1, (uint8_t*) key_, key_len );
401                sha1_finish( &sha1, key );
402        }
403        else
404        {
405                memcpy( key, key_, key_len );
406        }
407       
408        /* Inner part: H(K XOR 0x36, text) */
409        sha1_init( &sha1 );
410        for( i = 0; i < HMAC_BLOCK_SIZE; i ++ )
411                key[i] ^= 0x36;
412        sha1_append( &sha1, key, HMAC_BLOCK_SIZE );
413        sha1_append( &sha1, (const uint8_t*) payload, payload_len );
414        sha1_finish( &sha1, hash );
415       
416        /* Final result: H(K XOR 0x5C, inner stuff) */
417        sha1_init( &sha1 );
418        for( i = 0; i < HMAC_BLOCK_SIZE; i ++ )
419                key[i] ^= 0x36 ^ 0x5c;
420        sha1_append( &sha1, key, HMAC_BLOCK_SIZE );
421        sha1_append( &sha1, hash, sha1_hash_size );
422        sha1_finish( &sha1, Message_Digest );
423}
[e0a0a42]424
425/* I think this follows the scheme described on:
426   http://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29
427   My random data comes from a SHA1 generator but hey, it's random enough for
428   me, and RFC 4122 looks way more complicated than I need this to be.
429   
430   Returns a value that must be free()d. */
431char *sha1_random_uuid( sha1_state_t * context )
432{
433        uint8_t dig[sha1_hash_size];
434        char *ret = g_new0( char, 40 ); /* 36 chars + \0 */
435        int i, p;
436       
437        sha1_finish(context, dig);
438        for( p = i = 0; i < 16; i ++ )
439        {
440                if( i == 4 || i == 6 || i == 8 || i == 10 )
441                        ret[p++] = '-';
442                if( i == 6 )
443                        dig[i] = ( dig[i] & 0x0f ) | 0x40;
444                if( i == 8 )
445                        dig[i] = ( dig[i] & 0x30 ) | 0x80;
446               
447                sprintf( ret + p, "%02x", dig[i] );
448                p += 2;
449        }
450        ret[p] = '\0';
451       
452        return ret;
453}
Note: See TracBrowser for help on using the repository browser.