sha1.cpp File Reference


Detailed Description

This file implements the Secure Hashing Algorithm 1 as defined in FIPS PUB 180-1 published April 17, 1995.

The SHA-1, produces a 160-bit message digest for a given data stream. It should take about 2**n steps to find a message with the same digest as a given message and 2**(n/2) to find any two messages with the same digest, when n is the digest size in bits. Therefore, this algorithm can serve as a means of providing a "fingerprint" for a message.

Portability Issues: SHA-1 is defined in terms of 32-bit "words". This code uses <stdint.h> (included via "sha1.h" to define 32 and 8 bit unsigned integer types. If your C compiler does not support 32 bit unsigned integers, this code is not appropriate.

Caveats: SHA-1 is designed to work with messages less than 2^64 bits long. Although SHA-1 allows a message digest to be generated for messages of any number of bits less than 2^64, this implementation only works with messages with a length that is a multiple of the size of an 8-bit character.

Id
sha1.cpp,v 1.4 2003/10/20 16:10:17 lecroart Exp

Definition in file sha1.cpp.

#include "stdmisc.h"
#include <stdio.h>
#include <string.h>
#include <string>
#include <map>
#include <vector>
#include "nel/misc/sha1.h"
#include "nel/misc/file.h"
#include "nel/misc/path.h"

Go to the source code of this file.

Data Structures

struct  SHA1Context

Defines

#define SHA1CircularShift(bits, word)   (((word) << (bits)) | ((word) >> (32-(bits))))
#define SHA1HashSize   20

Typedefs

typedef short int_least16_t
typedef SHA1Context SHA1Context
typedef unsigned int uint32_t
typedef unsigned char uint8_t

Enumerations

enum  { shaSuccess = 0, shaNull, shaInputTooLong, shaStateError }

Functions

CHashKey getSHA1 (const string &filename)
CHashKey getSHA1 (const uint8 *buffer, uint32 size)
int SHA1Input (SHA1Context *, const uint8_t *, unsigned int)
void SHA1PadMessage (SHA1Context *)
void SHA1ProcessMessageBlock (SHA1Context *)
int SHA1Reset (SHA1Context *)
int SHA1Result (SHA1Context *, uint8_t Message_Digest[20])

Variables

uint8_t buffer [bufferSize]
const int bufferSize = 100000


Define Documentation

#define SHA1CircularShift bits,
word   )     (((word) << (bits)) | ((word) >> (32-(bits))))
 

Definition at line 235 of file sha1.cpp.

Referenced by SHA1ProcessMessageBlock().

#define SHA1HashSize   20
 

Definition at line 106 of file sha1.cpp.

Referenced by SHA1Result().


Typedef Documentation

typedef short int_least16_t
 

Definition at line 89 of file sha1.cpp.

typedef struct SHA1Context SHA1Context
 

typedef unsigned int uint32_t
 

Definition at line 87 of file sha1.cpp.

Referenced by SHA1ProcessMessageBlock().

typedef unsigned char uint8_t
 

Definition at line 88 of file sha1.cpp.

Referenced by getSHA1().


Enumeration Type Documentation

anonymous enum
 

Enumeration values:
shaSuccess 
shaNull 
shaInputTooLong 
shaStateError 

Definition at line 98 of file sha1.cpp.

00099 {
00100     shaSuccess = 0,
00101     shaNull,            /* Null pointer parameter */
00102     shaInputTooLong,    /* input data too long */
00103     shaStateError       /* called Input after Result */
00104 };


Function Documentation

CHashKey getSHA1 const string &  filename  ) 
 

Definition at line 170 of file sha1.cpp.

References buffer, bufferSize, NLMISC::CIFile::close(), NLMISC::CIFile::eof(), NLMISC::CIFile::getFileSize(), min, nlwarning, NLMISC::CIFile::open(), NLMISC::CIFile::serialBuffer(), NLMISC::CIFile::setCacheFileOnOpen(), SHA1Input(), SHA1Reset(), SHA1Result(), sint, uint8, and uint8_t.

00171 {
00172     SHA1Context sha;
00173     int err;
00174     uint8_t Message_Digest[20];
00175 
00176         //printf("reading '%s'\n", findData.cFileName);
00177         CIFile ifile;
00178         ifile.setCacheFileOnOpen(true);
00179         if (!ifile.open(CPath::lookup(filename)))
00180         {
00181                 nlwarning ("SHA: Can't open the file '%s'", filename.c_str());
00182                 return CHashKey();
00183         }
00184 
00185         //FILE *fp = fopen (filename.c_str(), "rb");
00186         //if (fp == NULL) return CHashKey();
00187 
00188         err = SHA1Reset(&sha);
00189         if (err)
00190         {
00191                 nlwarning("SHA: SHA1Reset Error %d.\n", err );
00192                 ifile.close ();
00193                 return CHashKey();
00194         }
00195 
00196         sint fs = ifile.getFileSize();
00197         sint n, read = 0;
00198         do
00199         {
00200                 //bs = (int)fread (buffer, 1, bufferSize, fp);
00201                 n = std::min (bufferSize, fs-read);
00202                 //nlinfo ("read %d bytes", n);
00203                 ifile.serialBuffer((uint8 *)buffer, n);
00204 
00205                 err = SHA1Input(&sha, buffer, n);
00206                 if (err)
00207                 {
00208                         nlwarning ("SHA: SHA1Input Error %d.\n", err);
00209                         ifile.close();
00210                         return CHashKey();
00211                 }
00212                 read += n;
00213         }
00214         while (!ifile.eof());
00215 
00216         ifile.close     ();
00217 
00218         err = SHA1Result(&sha, Message_Digest);
00219         if (err)
00220         {
00221                 nlwarning("SHA: SHA1Result Error %d, could not compute message digest.\n", err );
00222                 return CHashKey();
00223         }
00224 
00225         CHashKey hk (Message_Digest);
00226         return hk;
00227 }

CHashKey getSHA1 const uint8 buffer,
uint32  size
 

Definition at line 139 of file sha1.cpp.

00140 {
00141     SHA1Context sha;
00142     int err;
00143     uint8_t Message_Digest[20];
00144         
00145         err = SHA1Reset(&sha);
00146         if (err)
00147         {
00148                 nlwarning("SHA: SHA1Reset Error %d.\n", err );
00149                 return CHashKey();
00150         }
00151         
00152         err = SHA1Input(&sha, (const uint8_t*)buffer, size);
00153         if (err)
00154         {
00155                 nlwarning ("SHA: SHA1Input Error %d.\n", err);
00156                 return CHashKey();
00157         }
00158         
00159         err = SHA1Result(&sha, Message_Digest);
00160         if (err)
00161         {
00162                 nlwarning("SHA: SHA1Result Error %d, could not compute message digest.\n", err );
00163                 return CHashKey();
00164         }
00165         
00166         CHashKey hk (Message_Digest);
00167         return hk;
00168 }       

int SHA1Input SHA1Context ,
const uint8_t ,
unsigned  int
 

Definition at line 357 of file sha1.cpp.

References SHA1Context::Computed, SHA1Context::Corrupted, SHA1Context::Length_High, SHA1Context::Length_Low, SHA1Context::Message_Block, SHA1Context::Message_Block_Index, SHA1ProcessMessageBlock(), shaNull, shaStateError, and shaSuccess.

Referenced by getSHA1().

00360 {
00361     if (!length)
00362     {
00363         return shaSuccess;
00364     }
00365 
00366     if (!context || !message_array)
00367     {
00368         return shaNull;
00369     }
00370 
00371     if (context->Computed)
00372     {
00373         context->Corrupted = shaStateError;
00374 
00375         return shaStateError;
00376     }
00377 
00378     if (context->Corrupted)
00379     {
00380          return context->Corrupted;
00381     }
00382     while(length-- && !context->Corrupted)
00383     {
00384     context->Message_Block[context->Message_Block_Index++] =
00385                     (*message_array & 0xFF);
00386 
00387     context->Length_Low += 8;
00388     if (context->Length_Low == 0)
00389     {
00390         context->Length_High++;
00391         if (context->Length_High == 0)
00392         {
00393             /* Message is too long */
00394             context->Corrupted = 1;
00395         }
00396     }
00397 
00398     if (context->Message_Block_Index == 64)
00399     {
00400         SHA1ProcessMessageBlock(context);
00401     }
00402 
00403     message_array++;
00404     }
00405 
00406     return shaSuccess;
00407 }

void SHA1PadMessage SHA1Context  ) 
 

Definition at line 541 of file sha1.cpp.

References SHA1Context::Length_High, SHA1Context::Length_Low, SHA1Context::Message_Block, SHA1Context::Message_Block_Index, and SHA1ProcessMessageBlock().

Referenced by SHA1Result().

00542 {
00543     /*
00544      *  Check to see if the current message block is too small to hold
00545      *  the initial padding bits and length.  If so, we will pad the
00546      *  block, process it, and then continue padding into a second
00547      *  block.
00548      */
00549     if (context->Message_Block_Index > 55)
00550     {
00551         context->Message_Block[context->Message_Block_Index++] = 0x80;
00552         while(context->Message_Block_Index < 64)
00553         {
00554             context->Message_Block[context->Message_Block_Index++] = 0;
00555         }
00556 
00557         SHA1ProcessMessageBlock(context);
00558 
00559         while(context->Message_Block_Index < 56)
00560         {
00561             context->Message_Block[context->Message_Block_Index++] = 0;
00562         }
00563     }
00564     else
00565     {
00566         context->Message_Block[context->Message_Block_Index++] = 0x80;
00567         while(context->Message_Block_Index < 56)
00568         {
00569 
00570             context->Message_Block[context->Message_Block_Index++] = 0;
00571         }
00572     }
00573 
00574     /*
00575      *  Store the message length as the last 8 octets
00576      */
00577     context->Message_Block[56] = context->Length_High >> 24;
00578     context->Message_Block[57] = context->Length_High >> 16;
00579     context->Message_Block[58] = context->Length_High >> 8;
00580     context->Message_Block[59] = context->Length_High;
00581     context->Message_Block[60] = context->Length_Low >> 24;
00582     context->Message_Block[61] = context->Length_Low >> 16;
00583     context->Message_Block[62] = context->Length_Low >> 8;
00584     context->Message_Block[63] = context->Length_Low;
00585 
00586     SHA1ProcessMessageBlock(context);
00587 }

void SHA1ProcessMessageBlock SHA1Context  ) 
 

Definition at line 430 of file sha1.cpp.

References SHA1Context::Intermediate_Hash, SHA1Context::Message_Block, SHA1Context::Message_Block_Index, SHA1CircularShift, t, and uint32_t.

Referenced by SHA1Input(), and SHA1PadMessage().

00431 {
00432     const uint32_t K[] =    {       /* Constants defined in SHA-1   */
00433                             0x5A827999,
00434                             0x6ED9EBA1,
00435                             0x8F1BBCDC,
00436                             0xCA62C1D6
00437                             };
00438     int           t;                 /* Loop counter                */
00439     uint32_t      temp;              /* Temporary word value        */
00440     uint32_t      W[80];             /* Word sequence               */
00441     uint32_t      A, B, C, D, E;     /* Word buffers                */
00442 
00443     /*
00444      *  Initialize the first 16 words in the array W
00445      */
00446     for(t = 0; t < 16; t++)
00447     {
00448         W[t] = context->Message_Block[t * 4] << 24;
00449         W[t] |= context->Message_Block[t * 4 + 1] << 16;
00450         W[t] |= context->Message_Block[t * 4 + 2] << 8;
00451         W[t] |= context->Message_Block[t * 4 + 3];
00452     }
00453 
00454     for(t = 16; t < 80; t++)
00455     {
00456        W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
00457     }
00458 
00459     A = context->Intermediate_Hash[0];
00460     B = context->Intermediate_Hash[1];
00461     C = context->Intermediate_Hash[2];
00462     D = context->Intermediate_Hash[3];
00463     E = context->Intermediate_Hash[4];
00464 
00465     for(t = 0; t < 20; t++)
00466     {
00467         temp =  SHA1CircularShift(5,A) +
00468                 ((B & C) | ((~B) & D)) + E + W[t] + K[0];
00469         E = D;
00470         D = C;
00471         C = SHA1CircularShift(30,B);
00472 
00473         B = A;
00474         A = temp;
00475     }
00476 
00477     for(t = 20; t < 40; t++)
00478     {
00479         temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
00480         E = D;
00481         D = C;
00482         C = SHA1CircularShift(30,B);
00483         B = A;
00484         A = temp;
00485     }
00486 
00487     for(t = 40; t < 60; t++)
00488     {
00489         temp = SHA1CircularShift(5,A) +
00490                ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
00491         E = D;
00492         D = C;
00493         C = SHA1CircularShift(30,B);
00494         B = A;
00495         A = temp;
00496     }
00497 
00498     for(t = 60; t < 80; t++)
00499     {
00500         temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
00501         E = D;
00502         D = C;
00503         C = SHA1CircularShift(30,B);
00504         B = A;
00505         A = temp;
00506     }
00507 
00508     context->Intermediate_Hash[0] += A;
00509     context->Intermediate_Hash[1] += B;
00510     context->Intermediate_Hash[2] += C;
00511     context->Intermediate_Hash[3] += D;
00512     context->Intermediate_Hash[4] += E;
00513 
00514     context->Message_Block_Index = 0;
00515 }

int SHA1Reset SHA1Context  ) 
 

Definition at line 257 of file sha1.cpp.

References SHA1Context::Computed, SHA1Context::Corrupted, SHA1Context::Intermediate_Hash, SHA1Context::Length_High, SHA1Context::Length_Low, SHA1Context::Message_Block_Index, shaNull, and shaSuccess.

Referenced by getSHA1().

00258 {
00259     if (!context)
00260     {
00261         return shaNull;
00262     }
00263 
00264     context->Length_Low             = 0;
00265     context->Length_High            = 0;
00266     context->Message_Block_Index    = 0;
00267 
00268     context->Intermediate_Hash[0]   = 0x67452301;
00269     context->Intermediate_Hash[1]   = 0xEFCDAB89;
00270     context->Intermediate_Hash[2]   = 0x98BADCFE;
00271     context->Intermediate_Hash[3]   = 0x10325476;
00272     context->Intermediate_Hash[4]   = 0xC3D2E1F0;
00273 
00274     context->Computed   = 0;
00275     context->Corrupted  = 0;
00276 
00277     return shaSuccess;
00278 }

int SHA1Result SHA1Context ,
uint8_t  Message_Digest[20]
 

Definition at line 299 of file sha1.cpp.

References SHA1Context::Computed, SHA1Context::Corrupted, SHA1Context::Intermediate_Hash, SHA1Context::Length_High, SHA1Context::Length_Low, SHA1Context::Message_Block, SHA1HashSize, SHA1PadMessage(), shaNull, and shaSuccess.

Referenced by getSHA1().

00301 {
00302     int i;
00303 
00304     if (!context || !Message_Digest)
00305     {
00306         return shaNull;
00307     }
00308 
00309     if (context->Corrupted)
00310     {
00311         return context->Corrupted;
00312     }
00313 
00314     if (!context->Computed)
00315     {
00316         SHA1PadMessage(context);
00317         for(i=0; i<64; ++i)
00318         {
00319             /* message may be sensitive, clear it out */
00320             context->Message_Block[i] = 0;
00321         }
00322         context->Length_Low = 0;    /* and clear length */
00323         context->Length_High = 0;
00324         context->Computed = 1;
00325 
00326     }
00327 
00328     for(i = 0; i < SHA1HashSize; ++i)
00329     {
00330         Message_Digest[i] = context->Intermediate_Hash[i>>2]
00331                             >> 8 * ( 3 - ( i & 0x03 ) );
00332     }
00333 
00334     return shaSuccess;
00335 }


Variable Documentation

uint8_t buffer[bufferSize] [static]
 

Definition at line 96 of file sha1.cpp.

const int bufferSize = 100000 [static]
 

Definition at line 95 of file sha1.cpp.

Referenced by getSHA1().


Generated on Tue Mar 16 06:43:17 2004 for NeL by doxygen 1.3.6