COOPY » Guide  version 0.6.5
/home/paulfitz/cvs/coopy_scm/coopy/src/libcoopy_core/Sha1Generator.cpp
Go to the documentation of this file.
00001 
00002 // Duplicated from fossil, see ../ssfossil/fossil
00003 
00004 /*
00005 ** This implementation of SHA1 is adapted from the example implementation
00006 ** contained in RFC-3174.
00007 */
00008 /*
00009  * If you do not have the ISO standard stdint.h header file, then you
00010  * must typdef the following:
00011  *    name              meaning
00012  *  */
00013 #if defined(__DMC__) || defined(_MSC_VER)
00014   typedef  unsigned long uint32_t; //unsigned 32 bit integer
00015   typedef  unsigned char  uint8_t; //unsigned  8 bit integer (i.e., unsigned char)
00016 #else
00017 #  include <stdint.h>
00018 #endif
00019 #include <sys/types.h>
00020 //#include "config.h"
00021 #include <coopy/Sha1Generator.h>
00022 #include <string.h>
00023 
00024 #define SHA1HashSize 20
00025 #define shaSuccess 0
00026 #define shaInputTooLong 1
00027 #define shaStateError 2
00028 
00029 /*
00030  *  This structure will hold context information for the SHA-1
00031  *  hashing operation
00032  */
00033 typedef struct SHA1Context SHA1Context;
00034 struct SHA1Context {
00035     uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest  */
00036 
00037     uint32_t Length_Low;            /* Message length in bits      */
00038     uint32_t Length_High;           /* Message length in bits      */
00039 
00040     int Message_Block_Index;   /* Index into message block array   */
00041     uint8_t Message_Block[64];      /* 512-bit message blocks      */
00042 
00043     int Computed;               /* Is the digest computed?         */
00044     int Corrupted;             /* Is the message digest corrupted? */
00045 };
00046 
00047 /*
00048  *  sha1.c
00049  *
00050  *  Description:
00051  *      This file implements the Secure Hashing Algorithm 1 as
00052  *      defined in FIPS PUB 180-1 published April 17, 1995.
00053  *
00054  *      The SHA-1, produces a 160-bit message digest for a given
00055  *      data stream.  It should take about 2**n steps to find a
00056  *      message with the same digest as a given message and
00057  *      2**(n/2) to find any two messages with the same digest,
00058  *      when n is the digest size in bits.  Therefore, this
00059  *      algorithm can serve as a means of providing a
00060  *      "fingerprint" for a message.
00061  *
00062  *  Portability Issues:
00063  *      SHA-1 is defined in terms of 32-bit "words".  This code
00064  *      uses <stdint.h> (included via "sha1.h" to define 32 and 8
00065  *      bit unsigned integer types.  If your C compiler does not
00066  *      support 32 bit unsigned integers, this code is not
00067  *      appropriate.
00068  *
00069  *  Caveats:
00070  *      SHA-1 is designed to work with messages less than 2^64 bits
00071  *      long.  Although SHA-1 allows a message digest to be generated
00072  *      for messages of any number of bits less than 2^64, this
00073  *      implementation only works with messages with a length that is
00074  *      a multiple of the size of an 8-bit character.
00075  *
00076  */
00077 
00078 /*
00079  *  Define the SHA1 circular left shift macro
00080  */
00081 #define SHA1CircularShift(bits,word) \
00082                 (((word) << (bits)) | ((word) >> (32-(bits))))
00083 
00084 /* Local Function Prototyptes */
00085 static void SHA1PadMessage(SHA1Context *);
00086 static void SHA1ProcessMessageBlock(SHA1Context *);
00087 
00088 /*
00089  *  SHA1Reset
00090  *
00091  *  Description:
00092  *      This function will initialize the SHA1Context in preparation
00093  *      for computing a new SHA1 message digest.
00094  *
00095  *  Parameters:
00096  *      context: [in/out]
00097  *          The context to reset.
00098  *
00099  *  Returns:
00100  *      sha Error Code.
00101  *
00102  */
00103 static int SHA1Reset(SHA1Context *context)
00104 {
00105     context->Length_Low             = 0;
00106     context->Length_High            = 0;
00107     context->Message_Block_Index    = 0;
00108 
00109     context->Intermediate_Hash[0]   = 0x67452301;
00110     context->Intermediate_Hash[1]   = 0xEFCDAB89;
00111     context->Intermediate_Hash[2]   = 0x98BADCFE;
00112     context->Intermediate_Hash[3]   = 0x10325476;
00113     context->Intermediate_Hash[4]   = 0xC3D2E1F0;
00114 
00115     context->Computed   = 0;
00116     context->Corrupted  = 0;
00117 
00118     return shaSuccess;
00119 }
00120 
00121 /*
00122  *  SHA1Result
00123  *
00124  *  Description:
00125  *      This function will return the 160-bit message digest into the
00126  *      Message_Digest array  provided by the caller.
00127  *      NOTE: The first octet of hash is stored in the 0th element,
00128  *            the last octet of hash in the 19th element.
00129  *
00130  *  Parameters:
00131  *      context: [in/out]
00132  *          The context to use to calculate the SHA-1 hash.
00133  *      Message_Digest: [out]
00134  *          Where the digest is returned.
00135  *
00136  *  Returns:
00137  *      sha Error Code.
00138  *
00139  */
00140 static int SHA1Result( SHA1Context *context,
00141                 uint8_t Message_Digest[SHA1HashSize])
00142 {
00143     int i;
00144 
00145     if (context->Corrupted)
00146     {
00147         return context->Corrupted;
00148     }
00149 
00150     if (!context->Computed)
00151     {
00152         SHA1PadMessage(context);
00153         for(i=0; i<64; ++i)
00154         {
00155             /* message may be sensitive, clear it out */
00156             context->Message_Block[i] = 0;
00157         }
00158         context->Length_Low = 0;    /* and clear length */
00159         context->Length_High = 0;
00160         context->Computed = 1;
00161 
00162     }
00163 
00164     for(i = 0; i < SHA1HashSize; ++i)
00165     {
00166         Message_Digest[i] = context->Intermediate_Hash[i>>2]
00167                             >> 8 * ( 3 - ( i & 0x03 ) );
00168     }
00169 
00170     return shaSuccess;
00171 }
00172 
00173 /*
00174  *  SHA1Input
00175  *
00176  *  Description:
00177  *      This function accepts an array of octets as the next portion
00178  *      of the message.
00179  *
00180  *  Parameters:
00181  *      context: [in/out]
00182  *          The SHA context to update
00183  *      message_array: [in]
00184  *          An array of characters representing the next portion of
00185  *          the message.
00186  *      length: [in]
00187  *          The length of the message in message_array
00188  *
00189  *  Returns:
00190  *      sha Error Code.
00191  *
00192  */
00193 static
00194 int SHA1Input(    SHA1Context    *context,
00195                   const uint8_t  *message_array,
00196                   unsigned       length)
00197 {
00198     if (!length)
00199     {
00200         return shaSuccess;
00201     }
00202 
00203     if (context->Computed)
00204     {
00205         context->Corrupted = shaStateError;
00206 
00207         return shaStateError;
00208     }
00209 
00210     if (context->Corrupted)
00211     {
00212          return context->Corrupted;
00213     }
00214     while(length-- && !context->Corrupted)
00215     {
00216     context->Message_Block[context->Message_Block_Index++] =
00217                     (*message_array & 0xFF);
00218 
00219     context->Length_Low += 8;
00220     if (context->Length_Low == 0)
00221     {
00222         context->Length_High++;
00223         if (context->Length_High == 0)
00224         {
00225             /* Message is too long */
00226             context->Corrupted = 1;
00227         }
00228     }
00229 
00230     if (context->Message_Block_Index == 64)
00231     {
00232         SHA1ProcessMessageBlock(context);
00233     }
00234 
00235     message_array++;
00236     }
00237 
00238     return shaSuccess;
00239 }
00240 
00241 /*
00242  *  SHA1ProcessMessageBlock
00243  *
00244  *  Description:
00245  *      This function will process the next 512 bits of the message
00246  *      stored in the Message_Block array.
00247  *
00248  *  Parameters:
00249  *      None.
00250  *
00251  *  Returns:
00252  *      Nothing.
00253  *
00254  *  Comments:
00255  *      Many of the variable names in this code, especially the
00256  *      single character names, were used because those were the
00257  *      names used in the publication.
00258  *
00259  *
00260  */
00261 static void SHA1ProcessMessageBlock(SHA1Context *context)
00262 {
00263     const uint32_t K[] =    {       /* Constants defined in SHA-1   */
00264                             0x5A827999,
00265                             0x6ED9EBA1,
00266                             0x8F1BBCDC,
00267                             0xCA62C1D6
00268                             };
00269     int           t;                 /* Loop counter                */
00270     uint32_t      temp;              /* Temporary word value        */
00271     uint32_t      W[80];             /* Word sequence               */
00272     uint32_t      A, B, C, D, E;     /* Word buffers                */
00273 
00274     /*
00275      *  Initialize the first 16 words in the array W
00276      */
00277     for(t = 0; t < 16; t++)
00278     {
00279         W[t] = context->Message_Block[t * 4] << 24;
00280         W[t] |= context->Message_Block[t * 4 + 1] << 16;
00281         W[t] |= context->Message_Block[t * 4 + 2] << 8;
00282         W[t] |= context->Message_Block[t * 4 + 3];
00283     }
00284 
00285     for(t = 16; t < 80; t++)
00286     {
00287        W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
00288     }
00289 
00290     A = context->Intermediate_Hash[0];
00291     B = context->Intermediate_Hash[1];
00292     C = context->Intermediate_Hash[2];
00293     D = context->Intermediate_Hash[3];
00294     E = context->Intermediate_Hash[4];
00295 
00296     for(t = 0; t < 20; t++)
00297     {
00298         temp =  SHA1CircularShift(5,A) +
00299                 ((B & C) | ((~B) & D)) + E + W[t] + K[0];
00300         E = D;
00301         D = C;
00302         C = SHA1CircularShift(30,B);
00303 
00304         B = A;
00305         A = temp;
00306     }
00307 
00308     for(t = 20; t < 40; t++)
00309     {
00310         temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
00311         E = D;
00312         D = C;
00313         C = SHA1CircularShift(30,B);
00314         B = A;
00315         A = temp;
00316     }
00317 
00318     for(t = 40; t < 60; t++)
00319     {
00320         temp = SHA1CircularShift(5,A) +
00321                ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
00322         E = D;
00323         D = C;
00324         C = SHA1CircularShift(30,B);
00325         B = A;
00326         A = temp;
00327     }
00328 
00329     for(t = 60; t < 80; t++)
00330     {
00331         temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
00332         E = D;
00333         D = C;
00334         C = SHA1CircularShift(30,B);
00335         B = A;
00336         A = temp;
00337     }
00338 
00339     context->Intermediate_Hash[0] += A;
00340     context->Intermediate_Hash[1] += B;
00341     context->Intermediate_Hash[2] += C;
00342     context->Intermediate_Hash[3] += D;
00343     context->Intermediate_Hash[4] += E;
00344 
00345     context->Message_Block_Index = 0;
00346 }
00347 
00348 /*
00349  *  SHA1PadMessage
00350  *
00351 
00352  *  Description:
00353  *      According to the standard, the message must be padded to an even
00354  *      512 bits.  The first padding bit must be a '1'.  The last 64
00355  *      bits represent the length of the original message.  All bits in
00356  *      between should be 0.  This function will pad the message
00357  *      according to those rules by filling the Message_Block array
00358  *      accordingly.  It will also call the ProcessMessageBlock function
00359  *      provided appropriately.  When it returns, it can be assumed that
00360  *      the message digest has been computed.
00361  *
00362  *  Parameters:
00363  *      context: [in/out]
00364  *          The context to pad
00365  *      ProcessMessageBlock: [in]
00366  *          The appropriate SHA*ProcessMessageBlock function
00367  *  Returns:
00368  *      Nothing.
00369  *
00370  */
00371 static void SHA1PadMessage(SHA1Context *context)
00372 {
00373     /*
00374      *  Check to see if the current message block is too small to hold
00375      *  the initial padding bits and length.  If so, we will pad the
00376      *  block, process it, and then continue padding into a second
00377      *  block.
00378      */
00379     if (context->Message_Block_Index > 55)
00380     {
00381         context->Message_Block[context->Message_Block_Index++] = 0x80;
00382         while(context->Message_Block_Index < 64)
00383         {
00384             context->Message_Block[context->Message_Block_Index++] = 0;
00385         }
00386 
00387         SHA1ProcessMessageBlock(context);
00388 
00389         while(context->Message_Block_Index < 56)
00390         {
00391             context->Message_Block[context->Message_Block_Index++] = 0;
00392         }
00393     }
00394     else
00395     {
00396         context->Message_Block[context->Message_Block_Index++] = 0x80;
00397         while(context->Message_Block_Index < 56)
00398         {
00399 
00400             context->Message_Block[context->Message_Block_Index++] = 0;
00401         }
00402     }
00403 
00404     /*
00405      *  Store the message length as the last 8 octets
00406      */
00407     context->Message_Block[56] = context->Length_High >> 24;
00408     context->Message_Block[57] = context->Length_High >> 16;
00409     context->Message_Block[58] = context->Length_High >> 8;
00410     context->Message_Block[59] = context->Length_High;
00411     context->Message_Block[60] = context->Length_Low >> 24;
00412     context->Message_Block[61] = context->Length_Low >> 16;
00413     context->Message_Block[62] = context->Length_Low >> 8;
00414     context->Message_Block[63] = context->Length_Low;
00415 
00416     SHA1ProcessMessageBlock(context);
00417 }
00418 
00419 
00420 /*
00421 ** Convert a digest into base-16.  digest should be declared as
00422 ** "unsigned char digest[20]" in the calling function.  The SHA1
00423 ** digest is stored in the first 20 bytes.  zBuf should
00424 ** be "char zBuf[41]".
00425 */
00426 static void DigestToBase16(unsigned char *digest, char *zBuf){
00427   static char const zEncode[] = "0123456789abcdef";
00428   int i, j;
00429 
00430   for(j=i=0; i<20; i++){
00431     int a = digest[i];
00432     zBuf[j++] = zEncode[(a>>4)&0xf];
00433     zBuf[j++] = zEncode[a & 0xf];
00434   }
00435   zBuf[j] = 0;
00436 }
00437 
00438 /*
00439 ** The state of a incremental SHA1 checksum computation.  Only one
00440 ** such computation can be underway at a time, of course.
00441 */
00442 static SHA1Context incrCtx;
00443 static int incrInit = 0;
00444 
00445 static int hashLen = 0;
00446 
00447 /*
00448 ** Add more text to the incremental SHA1 checksum.
00449 */
00450 void sha1sum_step_text(const char *zText, int nBytes){
00451   if( !incrInit ){
00452     SHA1Reset(&incrCtx);
00453     incrInit = 1;
00454   }
00455   if( nBytes<=0 ){
00456     if( nBytes==0 ) return;
00457     nBytes = strlen(zText);
00458   }
00459   hashLen += nBytes;
00460   SHA1Input(&incrCtx, (unsigned char*)zText, nBytes);
00461 }
00462 
00463 /*
00464 ** Finish the incremental SHA1 checksum.  Store the result in blob pOut
00465 ** if pOut!=0.  Also return a pointer to the result.  
00466 **
00467 ** This resets the incremental checksum preparing for the next round
00468 ** of computation.  The return pointer points to a static buffer that
00469 ** is overwritten by subsequent calls to this function.
00470 */
00471 char *sha1sum_finish(){
00472   unsigned char zResult[20];
00473   static char zOut[41];
00474   sha1sum_step_text(0,0);
00475   SHA1Result(&incrCtx, zResult);
00476   incrInit = 0;
00477   DigestToBase16(zResult, zOut);
00478   if (hashLen!=0) { 
00479     //printf("Length %d\n", hashLen);
00480   }
00481   hashLen = 0;
00482   return zOut;
00483 }
00484 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines