sha2.h

Go to the documentation of this file.
00001 /*************************************************************
00002 
00003     This program is a C++ implementation of the Secure Hash Algorithm (SHA)
00004     that handles the variations from the original 160 bit to 224, 256, 384
00005     and 512 bit.  The program is intended to be platform independant and
00006     has been tested on little-endian (Intel) and big-endian (Sun) machines.
00007 
00008     This program is based on a C version written by Aaron D. Gifford
00009     (as of 11/22/2004 his code could be found at http://www.adg.us/computers/sha.html).
00010     Attempts to contact him were unsuccessful.  I greatly condensed his version
00011     and shared as much code and data as I could think of.  I also inlined
00012     a lot of code that were macros in his version.  My version detects
00013     endian-ness automatically and adjusts itself accordingly.  This program
00014     has been tested with Visual C++ versions 6/7 and Dev-C++ on Windows, 
00015     g++ on Linux and CC on Solaris (g++ on Solaris gave a bus error).
00016 
00017     While I did make half-hearted attempts to optimize as I went along
00018     (testing on Wintel), any serious attempt at fast implementation is
00019     probably going to need to make use of in-lined assembly which is not
00020     very portable.
00021 
00022     The goal of this implementation is ease of use.  As much as possible
00023     I tried to hide implementation details while making it trivial to change
00024     the size of the hash and get the results.  The string and charactar
00025     array value of the hash is supplied as human-readable hex; the raw value
00026     can also be obtained.
00027 
00028     If you use this implementation somewhere I would like to be credited
00029     with my work (a link to my page below is fine).  I add no license
00030     restriction beyond any that is made by the original author.  This
00031     code comes with no warrenty expressed or implied, use at your own
00032     risk!
00033 
00034     Keith Oxenrider
00035     koxenrider[at]sol[dash]biotech[dot]com
00036     The latest version of this code should be available via the page
00037     sol-biotech.com/code.
00038 
00039 *************************************************************/
00040 
00041 
00042 
00043 
00044 #ifndef __SHA2C_H__
00045 #define __SHA2C_H__
00046 
00047 #include <string>
00048 #include <stdexcept>
00049 
00050 // NOTE: You may need to define things by hand for your system: 
00051 typedef unsigned char  sha_byte;           // Exactly 1 byte 
00052 typedef unsigned int sha_word32;           // Exactly 4 bytes 
00053 #ifdef WIN32
00054     #include <windows.h>
00055     typedef ULONG64 sha_word64;            // 8-bytes (64-bits) 
00056 #else
00057     typedef unsigned long long sha_word64; // 8-bytes (64-bits) 
00058 #endif
00059 
00060 // Digest lengths for SHA-1/224/256/384/512 
00061 const sha_word32 SHA1_DIGESTC_LENGTH = 20;
00062 const sha_word32 SHA1_DIGESTC_STRING_LENGTH   = (SHA1_DIGESTC_LENGTH   * 2 + 1);
00063 const sha_word32 SHA224_DIGESTC_LENGTH = 28;
00064 const sha_word32 SHA224_DIGESTC_STRING_LENGTH = (SHA224_DIGESTC_LENGTH * 2 + 1);
00065 const sha_word32 SHA256_DIGESTC_LENGTH = 32;
00066 const sha_word32 SHA256_DIGESTC_STRING_LENGTH = (SHA256_DIGESTC_LENGTH * 2 + 1);
00067 const sha_word32 SHA384_DIGESTC_LENGTH = 48;
00068 const sha_word32 SHA384_DIGESTC_STRING_LENGTH = (SHA384_DIGESTC_LENGTH * 2 + 1);
00069 const sha_word32 SHA512_DIGESTC_LENGTH = 64;
00070 const sha_word32 SHA512_DIGESTC_STRING_LENGTH = (SHA512_DIGESTC_LENGTH * 2 + 1);
00071 
00072 class sha2{
00073 public:
00074     enum SHA_TYPE{
00075         enuSHA_NONE,
00076         enuSHA1,
00077         enuSHA160 = enuSHA1,
00078         enuSHA224,
00079         enuSHA256,
00080         enuSHA384,
00081         enuSHA512,
00082         enuSHA_LAST //for easier looping during testing
00083     };
00084 
00085     sha2(){
00086         m_Type = enuSHA_NONE;
00087         m_boolIsBigEndian = true;
00088         m_boolEnded = false;
00089 
00090         //run-time check for endian-ness
00091         unsigned int test = 1;
00092         unsigned char *ptr = (unsigned char *)&test;
00093         if (ptr[0]) m_boolIsBigEndian = false;
00094 
00095         //these checks here because I wasn't able to figure out how to 
00096         //check at compile time
00097         if (sizeof(sha_byte) != 1) throw std::runtime_error("sha_byte != 1!");
00098         if (sizeof(sha_word32) != 4) throw std::runtime_error("sha_word32 != 4!");
00099         if (sizeof(sha_word64) != 8) throw std::runtime_error("sha_word64 != 8!");
00100 
00101         memset(m_chrRawHash, 0, SHA512_DIGESTC_LENGTH);
00102         memset(m_chrHexHash, 0, SHA512_DIGESTC_STRING_LENGTH);
00103         memset(m_digest, 0, SHA512_DIGESTC_LENGTH);
00104     };
00105 
00106     SHA_TYPE GetEnumType(){return m_Type;};
00107     bool IsBigEndian(){return m_boolIsBigEndian;};
00108     const char * GetTypeString(){
00109         switch (m_Type){
00110             case sha2::enuSHA1   : return "SHA160";
00111             case sha2::enuSHA224 : return "SHA224";
00112             case sha2::enuSHA256 : return "SHA256";
00113             case sha2::enuSHA384 : return "SHA384";
00114             case sha2::enuSHA512 : return "SHA512";
00115             default : return "Unknown!";
00116         }
00117     };
00118 
00119 //call these three in order if you want to load chunk-by-chunk...
00120     void Init(SHA_TYPE type);
00121     //these two throw a std::runtime_error if the type is not defined
00122     void Update(const sha_byte *data, size_t len);//call as many times as needed
00123     void End();
00124 
00125 //or call this one if you only have one chunk of data
00126     const std::string &GetHash(SHA_TYPE type, const sha_byte* data, size_t len);
00127 
00128 //call one of these routines to access the hash
00129     //these throw a std::runtime_error if End has not been called
00130     const char *HexHash();//NULL terminated
00131     const std::string &StringHash();
00132     const char *RawHash(int &length);//NO NULL termination! size stored in 'length'
00133 
00134 
00135 private:
00136     SHA_TYPE m_Type;
00137     std::string m_strHash;
00138     bool m_boolEnded, m_boolIsBigEndian;
00139     char m_chrRawHash[SHA512_DIGESTC_LENGTH], m_chrHexHash[SHA512_DIGESTC_STRING_LENGTH];
00140     sha_byte m_digest[SHA512_DIGESTC_LENGTH];
00141 
00142 //these are common buffers for maintaining the hash
00143     struct SHA_CTX{
00144         sha_byte   state[sizeof(sha_word64) * 8];//maximum size
00145         sha_word64 bitcount[2];//sha1, 224 and 256 only use the first entry
00146         sha_byte   buffer[128];
00147     }ctx;
00148 
00149     
00150 //** INTERNAL FUNCTION PROTOTYPES ************************************
00151     void SHA256_Internal_Last(bool isSha1 = false);
00152     void SHA512_Internal_Last();
00153 
00154     void SHA1_Internal_Transform(const sha_word32 *data);
00155     void SHA256_Internal_Transform(const sha_word32* data);
00156     void SHA512_Internal_Transform(const sha_word64*);
00157 
00158     void SHA32bit_Update(const sha_byte *data, size_t len, bool isSha1=false);
00159     void SHA64bit_Update(const sha_byte *data, size_t len);
00160 
00161 //macro replacements
00162     inline void MEMSET_BZERO(void *p, size_t l){memset(p, 0, l);};
00163     inline void MEMCPY_BCOPY(void *d,const void *s, size_t l) {memcpy(d, s, l);};
00164 
00165     //For incrementally adding the unsigned 64-bit integer n to the
00166     //unsigned 128-bit integer (represented using a two-element array of
00167     //64-bit words):
00168     inline void ADDINC128(sha_word64 *w, sha_word32 n)  {
00169         w[0] += (sha_word64)(n);
00170         if (w[0] < (n)) w[1]++;
00171     }
00172 
00173     // Shift-right (used in SHA-256, SHA-384, and SHA-512): 
00174     inline sha_word32 SHR(sha_word32 b,sha_word32 x){return (x >> b);};
00175     inline sha_word64 SHR(sha_word64 b,sha_word64 x){return (x >> b);};
00176     // 32-bit Rotate-right (used in SHA-256): 
00177     inline sha_word32 ROTR32(sha_word32 b,sha_word32 x){return ((x >> b) | (x << (32 - b)));};
00178     // 64-bit Rotate-right (used in SHA-384 and SHA-512): 
00179     inline sha_word64 ROTR64(sha_word64 b,sha_word64 x){return ((x >> b) | (x << (64 - b)));};
00180     // 32-bit Rotate-left (used in SHA-1): 
00181     inline sha_word32 ROTL32(sha_word32 b,sha_word32 x){return ((x << b) | (x >> (32 - b)));};
00182 
00183     // Two logical functions used in SHA-1, SHA-254, SHA-256, SHA-384, and SHA-512: 
00184     inline sha_word32 Ch(sha_word32 x,sha_word32 y,sha_word32 z){return ((x & y) ^ ((~x) & z));};
00185     inline sha_word64 Ch(sha_word64 x,sha_word64 y,sha_word64 z){return ((x & y) ^ ((~x) & z));};
00186     inline sha_word32 Maj(sha_word32 x,sha_word32 y,sha_word32 z){return ((x & y) ^ (x & z) ^ (y & z));};
00187     inline sha_word64 Maj(sha_word64 x,sha_word64 y,sha_word64 z){return ((x & y) ^ (x & z) ^ (y & z));};
00188 
00189     // Function used in SHA-1: 
00190     inline sha_word32 Parity(sha_word32 x,sha_word32 y,sha_word32 z){return (x ^ y ^ z);};
00191 
00192 // Four logical functions used in SHA-256: 
00193     inline sha_word32 Sigma0_256(sha_word32 x){return (ROTR32(2, x) ^ ROTR32(13, x) ^ ROTR32(22, x));};
00194     inline sha_word32 Sigma1_256(sha_word32 x){return (ROTR32(6, x) ^ ROTR32(11, x) ^ ROTR32(25, x));};
00195     inline sha_word32 sigma0_256(sha_word32 x){return (ROTR32(7, x) ^ ROTR32(18, x) ^ SHR(   3 , x));};
00196     inline sha_word32 sigma1_256(sha_word32 x){return (ROTR32(17,x) ^ ROTR32(19, x) ^ SHR(   10, x));};
00197 
00198 // Four of six logical functions used in SHA-384 and SHA-512: 
00199     inline sha_word64 Sigma0_512(sha_word64 x){return (ROTR64(28, x) ^ ROTR64(34, x) ^ ROTR64(39, x));};
00200     inline sha_word64 Sigma1_512(sha_word64 x){return (ROTR64(14, x) ^ ROTR64(18, x) ^ ROTR64(41, x));};
00201     inline sha_word64 sigma0_512(sha_word64 x){return (ROTR64( 1, x) ^ ROTR64( 8, x) ^ SHR(    7, x));};
00202     inline sha_word64 sigma1_512(sha_word64 x){return (ROTR64(19, x) ^ ROTR64(61, x) ^ SHR(    6, x));};
00203 
00204     inline void REVERSE32(sha_word32 w, sha_word32 &x)  {
00205         w = (w >> 16) | (w << 16);
00206         x = ((w & 0xff00ff00UL) >> 8) | ((w & 0x00ff00ffUL) << 8);
00207     }
00208     #ifdef _VC6
00209         inline void REVERSE64(sha_word64 w, sha_word64 &x)  {
00210             w = (w >> 32) | (w << 32);
00211             w =   ((w & 0xff00ff00ff00ff00ui64) >> 8) |
00212                   ((w & 0x00ff00ff00ff00ffui64) << 8);
00213             (x) = ((w & 0xffff0000ffff0000ui64) >> 16) |
00214                   ((w & 0x0000ffff0000ffffui64) << 16);
00215         }
00216     #else
00217         inline void REVERSE64(sha_word64 w, sha_word64 &x)  {
00218             w = (w >> 32) | (w << 32);
00219             w =   ((w & 0xff00ff00ff00ff00ULL) >> 8) |
00220                   ((w & 0x00ff00ff00ff00ffULL) << 8);
00221             (x) = ((w & 0xffff0000ffff0000ULL) >> 16) |
00222                   ((w & 0x0000ffff0000ffffULL) << 16);
00223         }
00224     #endif
00225 
00226 };//end class sha2
00227 #endif // __SHA2C_H__ 

Generated on Mon Feb 16 15:14:49 2009 for Scorched3D by  doxygen 1.5.3