sha2.cpp

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 #include "sha2.h"
00042 
00043 #include <iostream>
00044 
00045 using namespace std;
00046 
00047 // Hash constant words K for SHA-1:
00048 const sha_word32 K1_0_TO_19  = 0x5a827999UL;
00049 const sha_word32 K1_20_TO_39 = 0x6ed9eba1UL;
00050 const sha_word32 K1_40_TO_59 = 0x8f1bbcdcUL;
00051 const sha_word32 K1_60_TO_79 = 0xca62c1d6UL;
00052 
00053 
00054 
00055 //** SHA2 INITIAL HASH VALUES AND CONSTANTS **************************
00056 
00057 // Initial hash value H for SHA-1: 
00058 const static sha_word32 sha1_initial_hash_value[5] = {
00059     0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL,
00060     0xc3d2e1f0UL
00061 };
00062 
00063 // Hash constant words K for SHA-224 and SHA-256: 
00064 const static sha_word32 K256[64] = {
00065     0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
00066     0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
00067     0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
00068     0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
00069     0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
00070     0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
00071     0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
00072     0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
00073     0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
00074     0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
00075     0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
00076     0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
00077     0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
00078     0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
00079     0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
00080     0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
00081 };
00082 
00083 // Initial hash value H for SHA-224: 
00084 const static sha_word32 sha224_initial_hash_value[8] = {
00085     0xc1059ed8UL, 0x367cd507UL, 0x3070dd17UL, 0xf70e5939UL,
00086     0xffc00b31UL, 0x68581511UL, 0x64f98fa7UL, 0xbefa4fa4UL
00087 };
00088 
00089 // Initial hash value H for SHA-256: 
00090 const static sha_word32 sha256_initial_hash_value[8] = {
00091     0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL,
00092     0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL
00093 };
00094 
00095 // ui64 Hash constant words K for SHA-384 and SHA-512: 
00096 #ifdef _VC6
00097     const static sha_word64 K512[80] = {
00098         0x428a2f98d728ae22ui64, 0x7137449123ef65cdui64,
00099         0xb5c0fbcfec4d3b2fui64, 0xe9b5dba58189dbbcui64,
00100         0x3956c25bf348b538ui64, 0x59f111f1b605d019ui64,
00101         0x923f82a4af194f9bui64, 0xab1c5ed5da6d8118ui64,
00102         0xd807aa98a3030242ui64, 0x12835b0145706fbeui64,
00103         0x243185be4ee4b28cui64, 0x550c7dc3d5ffb4e2ui64,
00104         0x72be5d74f27b896fui64, 0x80deb1fe3b1696b1ui64,
00105         0x9bdc06a725c71235ui64, 0xc19bf174cf692694ui64,
00106         0xe49b69c19ef14ad2ui64, 0xefbe4786384f25e3ui64,
00107         0x0fc19dc68b8cd5b5ui64, 0x240ca1cc77ac9c65ui64,
00108         0x2de92c6f592b0275ui64, 0x4a7484aa6ea6e483ui64,
00109         0x5cb0a9dcbd41fbd4ui64, 0x76f988da831153b5ui64,
00110         0x983e5152ee66dfabui64, 0xa831c66d2db43210ui64,
00111         0xb00327c898fb213fui64, 0xbf597fc7beef0ee4ui64,
00112         0xc6e00bf33da88fc2ui64, 0xd5a79147930aa725ui64,
00113         0x06ca6351e003826fui64, 0x142929670a0e6e70ui64,
00114         0x27b70a8546d22ffcui64, 0x2e1b21385c26c926ui64,
00115         0x4d2c6dfc5ac42aedui64, 0x53380d139d95b3dfui64,
00116         0x650a73548baf63deui64, 0x766a0abb3c77b2a8ui64,
00117         0x81c2c92e47edaee6ui64, 0x92722c851482353bui64,
00118         0xa2bfe8a14cf10364ui64, 0xa81a664bbc423001ui64,
00119         0xc24b8b70d0f89791ui64, 0xc76c51a30654be30ui64,
00120         0xd192e819d6ef5218ui64, 0xd69906245565a910ui64,
00121         0xf40e35855771202aui64, 0x106aa07032bbd1b8ui64,
00122         0x19a4c116b8d2d0c8ui64, 0x1e376c085141ab53ui64,
00123         0x2748774cdf8eeb99ui64, 0x34b0bcb5e19b48a8ui64,
00124         0x391c0cb3c5c95a63ui64, 0x4ed8aa4ae3418acbui64,
00125         0x5b9cca4f7763e373ui64, 0x682e6ff3d6b2b8a3ui64,
00126         0x748f82ee5defb2fcui64, 0x78a5636f43172f60ui64,
00127         0x84c87814a1f0ab72ui64, 0x8cc702081a6439ecui64,
00128         0x90befffa23631e28ui64, 0xa4506cebde82bde9ui64,
00129         0xbef9a3f7b2c67915ui64, 0xc67178f2e372532bui64,
00130         0xca273eceea26619cui64, 0xd186b8c721c0c207ui64,
00131         0xeada7dd6cde0eb1eui64, 0xf57d4f7fee6ed178ui64,
00132         0x06f067aa72176fbaui64, 0x0a637dc5a2c898a6ui64,
00133         0x113f9804bef90daeui64, 0x1b710b35131c471bui64,
00134         0x28db77f523047d84ui64, 0x32caab7b40c72493ui64,
00135         0x3c9ebe0a15c9bebcui64, 0x431d67c49c100d4cui64,
00136         0x4cc5d4becb3e42b6ui64, 0x597f299cfc657e2aui64,
00137         0x5fcb6fab3ad6faecui64, 0x6c44198c4a475817ui64
00138     };
00139     // Initial hash value H for SHA-384 
00140     const static sha_word64 sha384_initial_hash_value[8] = {
00141         0xcbbb9d5dc1059ed8ui64, 0x629a292a367cd507ui64,
00142         0x9159015a3070dd17ui64, 0x152fecd8f70e5939ui64,
00143         0x67332667ffc00b31ui64, 0x8eb44a8768581511ui64,
00144         0xdb0c2e0d64f98fa7ui64, 0x47b5481dbefa4fa4ui64
00145     };
00146 
00147     // Initial hash value H for SHA-512 
00148     const static sha_word64 sha512_initial_hash_value[8] = {
00149         0x6a09e667f3bcc908ui64, 0xbb67ae8584caa73bui64,
00150         0x3c6ef372fe94f82bui64, 0xa54ff53a5f1d36f1ui64,
00151         0x510e527fade682d1ui64, 0x9b05688c2b3e6c1fui64,
00152         0x1f83d9abfb41bd6bui64, 0x5be0cd19137e2179ui64
00153     };
00154 #else
00155     const static sha_word64 K512[80] = {
00156         0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
00157         0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
00158         0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
00159         0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
00160         0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
00161         0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
00162         0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
00163         0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
00164         0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
00165         0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
00166         0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
00167         0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
00168         0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
00169         0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
00170         0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
00171         0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
00172         0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
00173         0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
00174         0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
00175         0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
00176         0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
00177         0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
00178         0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
00179         0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
00180         0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
00181         0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
00182         0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
00183         0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
00184         0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
00185         0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
00186         0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
00187         0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
00188         0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
00189         0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
00190         0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
00191         0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
00192         0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
00193         0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
00194         0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
00195         0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
00196     };
00197     // Initial hash value H for SHA-384 
00198     const static sha_word64 sha384_initial_hash_value[8] = {
00199         0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL,
00200         0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL,
00201         0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
00202         0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL
00203     };
00204 
00205     // Initial hash value H for SHA-512 
00206     const static sha_word64 sha512_initial_hash_value[8] = {
00207         0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
00208         0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
00209         0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
00210         0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
00211     };
00212 #endif
00213 
00214 /*
00215  * Constant used by SHA224/256/384/512_End() functions for converting the
00216  * digest to a readable hexadecimal character string:
00217  */
00218 static const char *sha_hex_digits = "0123456789abcdef";
00219 
00220 
00221 void sha2::SHA1_Internal_Transform(const sha_word32 *data) {
00222     sha_word32  a, b, c, d, e;
00223     sha_word32 *state = (sha_word32*)ctx.state;
00224     sha_word32  T1, T2, *W1=(sha_word32*)ctx.buffer;
00225     int j;
00226 
00227 // Initialize registers with the prev. intermediate value 
00228     a = state[0];
00229     b = state[1];
00230     c = state[2];
00231     d = state[3];
00232     e = state[4];
00233     j = 0;
00234     do {
00235         if (m_boolIsBigEndian) W1[j] = *data++;
00236         else REVERSE32(*data++, W1[j]);// Copy data while converting to host byte order
00237         T1 = ROTL32(5, a) + Ch(b, c, d) + e + K1_0_TO_19 + W1[j];
00238         e = d;
00239         d = c;
00240         c = ROTL32(30, b);
00241         b = a;
00242         a = T1;
00243         j++;
00244     } while (j < 16);
00245 
00246     do {
00247         T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f];
00248         if (j < 20)      T2 = Ch(b,c,d)     + K1_0_TO_19;
00249         else if (j < 40) T2 = Parity(b,c,d) + K1_20_TO_39;
00250         else if (j < 60) T2 = Maj(b,c,d)    + K1_40_TO_59;
00251         else             T2 = Parity(b,c,d) + K1_60_TO_79;
00252         T1 = ROTL32(5, a) + T2 + e + (W1[j&0x0f] = ROTL32(1, T1));
00253         e = d;
00254         d = c;
00255         c = ROTL32(30, b);
00256         b = a;
00257         a = T1;
00258         j++;
00259     } while (j < 80);
00260 
00261     state[0] += a;
00262     state[1] += b;
00263     state[2] += c;
00264     state[3] += d;
00265     state[4] += e;
00266 }
00267 
00268 
00269 
00270 ///* SHA-256: ********************************************************
00271 
00272 void sha2::SHA256_Internal_Transform(const sha_word32* data) {
00273     sha_word32  a, b, c, d, e, f, g, h, s0, s1;
00274     sha_word32 *state = (sha_word32*)ctx.state;
00275     sha_word32  T1, T2, *W256=(sha_word32*)ctx.buffer;;
00276     int j;
00277 
00278 // Initialize registers with the prev. intermediate value 
00279     a = state[0];
00280     b = state[1];
00281     c = state[2];
00282     d = state[3];
00283     e = state[4];
00284     f = state[5];
00285     g = state[6];
00286     h = state[7];
00287 
00288     j = 0;
00289     do {
00290         if (m_boolIsBigEndian) W256[j] = *data++;
00291         else REVERSE32(*data++,W256[j]);// Copy data while converting to host byte order
00292 
00293         T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
00294         T2 = Sigma0_256(a) + Maj(a, b, c);
00295         h = g;
00296         g = f;
00297         f = e;
00298         e = d + T1;
00299         d = c;
00300         c = b;
00301         b = a;
00302         a = T1 + T2;
00303 
00304         j++;
00305     } while (j < 16);
00306 
00307     do {
00308 // Part of the message block expansion: 
00309         s0 = W256[(j+1)&0x0f];
00310         s0 = sigma0_256(s0);
00311         s1 = W256[(j+14)&0x0f];
00312         s1 = sigma1_256(s1);
00313 
00314 // Apply the SHA-256 compression function to update a..h 
00315         T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
00316         (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
00317         T2 = Sigma0_256(a) + Maj(a, b, c);
00318         h = g;
00319         g = f;
00320         f = e;
00321         e = d + T1;
00322         d = c;
00323         c = b;
00324         b = a;
00325         a = T1 + T2;
00326 
00327         j++;
00328     } while (j < 64);
00329 
00330 // Compute the current intermediate hash value 
00331     state[0] += a;
00332     state[1] += b;
00333     state[2] += c;
00334     state[3] += d;
00335     state[4] += e;
00336     state[5] += f;
00337     state[6] += g;
00338     state[7] += h;
00339 }
00340 
00341 //** SHA-512: ********************************************************
00342 
00343 void sha2::SHA512_Internal_Transform(const sha_word64* data) {
00344     sha_word64  a, b, c, d, e, f, g, h, s0, s1;
00345     sha_word64 *state = (sha_word64 *)ctx.state;
00346     sha_word64  T1, T2, *W512 = (sha_word64*)ctx.buffer;
00347     int j;
00348 
00349 // Initialize registers with the prev. intermediate value 
00350     a = state[0];
00351     b = state[1];
00352     c = state[2];
00353     d = state[3];
00354     e = state[4];
00355     f = state[5];
00356     g = state[6];
00357     h = state[7];
00358 
00359     j = 0;
00360 
00361     do {
00362 
00363         if (m_boolIsBigEndian){
00364             W512[j] = *data;
00365             data++;
00366         }else{
00367             REVERSE64(*data++, W512[j]);// copy and convert TO host byte order
00368         }
00369 
00370         T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
00371         T2 = Sigma0_512(a) + Maj(a, b, c);
00372         h = g;
00373         g = f;
00374         f = e;
00375         e = d + T1;
00376         d = c;
00377         c = b;
00378         b = a;
00379         a = T1 + T2;
00380 
00381         j++;
00382     } while (j < 16);
00383 
00384     do {
00385 // Part of the message block expansion: 
00386         s0 = W512[(j+1)&0x0f];
00387         s0 = sigma0_512(s0);
00388         s1 = W512[(j+14)&0x0f];
00389         s1 =  sigma1_512(s1);
00390 
00391 // Apply the SHA-512 compression function to update a..h 
00392         T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
00393         (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
00394         T2 = Sigma0_512(a) + Maj(a, b, c);
00395         h = g;
00396         g = f;
00397         f = e;
00398         e = d + T1;
00399         d = c;
00400         c = b;
00401         b = a;
00402         a = T1 + T2;
00403 
00404         j++;
00405     } while (j < 80);
00406 
00407 // Compute the current intermediate hash value 
00408     state[0] += a;
00409     state[1] += b;
00410     state[2] += c;
00411     state[3] += d;
00412     state[4] += e;
00413     state[5] += f;
00414     state[6] += g;
00415     state[7] += h;
00416 }
00417 
00418 
00419 void sha2::SHA256_Internal_Last(bool isSha1) {
00420     sha_word32    usedspace;
00421 
00422     usedspace = (sha_word32)(ctx.bitcount[0] >> 3) % 64;
00423     if (usedspace == 0) {
00424         MEMSET_BZERO(ctx.buffer, 56);
00425         ctx.buffer[0] = 0x80;
00426     }else {
00427         ctx.buffer[usedspace++] = 0x80;
00428         if (usedspace <= 56) {
00429             MEMSET_BZERO(&ctx.buffer[usedspace], 56 - usedspace);
00430         }else {
00431             if (usedspace < 64) {
00432                 MEMSET_BZERO(&ctx.buffer[usedspace], 64 - usedspace);
00433             }
00434             if (isSha1) SHA1_Internal_Transform((sha_word32*)ctx.buffer);
00435             else SHA256_Internal_Transform((sha_word32*)ctx.buffer);
00436             MEMSET_BZERO(ctx.buffer, 56);
00437         }
00438     }
00439 
00440     if (!m_boolIsBigEndian) REVERSE64(ctx.bitcount[0],ctx.bitcount[0]);
00441     *(sha_word64*)&ctx.buffer[56] = ctx.bitcount[0];
00442     if (isSha1) SHA1_Internal_Transform((sha_word32*)ctx.buffer);
00443     else SHA256_Internal_Transform((sha_word32*)ctx.buffer);
00444 }
00445 
00446 
00447 void sha2::SHA512_Internal_Last() {
00448     sha_word32    usedspace;
00449 
00450     usedspace = (sha_word32)(ctx.bitcount[0] >> 3) % 128;
00451     if (usedspace == 0) {
00452         MEMSET_BZERO(ctx.buffer, 112);
00453         ctx.buffer[0] = 0x80;
00454     }else{
00455         ctx.buffer[usedspace++] = 0x80;
00456         if (usedspace <= 112) {
00457             MEMSET_BZERO(&ctx.buffer[usedspace], 112 - usedspace);
00458         }else {
00459             if (usedspace < 128) {
00460                 MEMSET_BZERO(&ctx.buffer[usedspace], 128 - usedspace);
00461             }
00462             SHA512_Internal_Transform((sha_word64*)ctx.buffer);
00463             MEMSET_BZERO(ctx.buffer, 112);
00464         }
00465         usedspace = 0;
00466     }
00467 
00468     if (!m_boolIsBigEndian){
00469         REVERSE64(ctx.bitcount[0],ctx.bitcount[0]);
00470         REVERSE64(ctx.bitcount[1],ctx.bitcount[1]);
00471     }
00472 
00473     *(sha_word64*)&ctx.buffer[112] = ctx.bitcount[1];
00474     *(sha_word64*)&ctx.buffer[120] = ctx.bitcount[0];
00475     SHA512_Internal_Transform((sha_word64*)ctx.buffer);
00476 }
00477 
00478 
00479 
00480 void sha2::SHA32bit_Update(const sha_byte *data, size_t len, bool isSha1) {
00481     sha_word32 freespace, usedspace;
00482     
00483     if (len<1){return;}// Calling with no data is valid - we do nothing 
00484 
00485     usedspace = (sha_word32)(ctx.bitcount[0] >> 3) % 64;
00486     if (usedspace > 0) {// Calculate how much free space is available in the buffer 
00487         freespace = 64 - usedspace;
00488         if (len >= freespace) {// Fill the buffer completely and process it 
00489             MEMCPY_BCOPY(&ctx.buffer[usedspace], data, freespace);
00490             ctx.bitcount[0] += freespace << 3;
00491             len -= freespace;
00492             data += freespace;
00493             if (isSha1) SHA1_Internal_Transform((sha_word32 *)ctx.buffer);
00494             else SHA256_Internal_Transform((sha_word32 *)ctx.buffer);
00495         }else {// The buffer is not yet full
00496             MEMCPY_BCOPY(&ctx.buffer[usedspace], data, len);
00497             ctx.bitcount[0] += len << 3;
00498             return;
00499         }
00500     }
00501     while (len >= 64) {// Process as many complete blocks as we can
00502         if (isSha1) SHA1_Internal_Transform((sha_word32*)data);
00503         else SHA256_Internal_Transform((sha_word32*)data);
00504         ctx.bitcount[0] += 512;
00505         len -= 64;
00506         data += 64;
00507     }
00508     if (len > 0) {// There's left-overs, so save 'em
00509         MEMCPY_BCOPY(&ctx.buffer, data, len);
00510         ctx.bitcount[0] += len << 3;
00511     }
00512 }
00513 
00514 
00515 
00516 void sha2::SHA64bit_Update(const sha_byte *data, size_t len) {
00517     sha_word32 freespace, usedspace;
00518 
00519     if (len < 1){return;}// Calling with no data is valid - we do nothing 
00520 
00521     usedspace = (sha_word32)(ctx.bitcount[0] >> 3) % 128;
00522     if (usedspace > 0) {// Calculate how much free space is available in the buffer 
00523         freespace = 128 - usedspace;
00524         if (len >= freespace) {// Fill the buffer completely and process it 
00525             MEMCPY_BCOPY(&ctx.buffer[usedspace], data, freespace);
00526             ADDINC128(ctx.bitcount, freespace << 3);
00527             len -= freespace;
00528             data += freespace;
00529             SHA512_Internal_Transform((sha_word64*)ctx.buffer);
00530         }else {// The buffer is not yet full 
00531             MEMCPY_BCOPY(&ctx.buffer[usedspace], data, len);
00532             ADDINC128(ctx.bitcount, len << 3);
00533             return;
00534         }
00535     }
00536     while (len >= 128) {// Process as many complete blocks as we can 
00537         SHA512_Internal_Transform((sha_word64*)data);
00538         ADDINC128(ctx.bitcount, 1024);
00539         len -= 128;
00540         data += 128;
00541     }
00542     if (len > 0) {// There's left-overs, so save 'em 
00543         MEMCPY_BCOPY(ctx.buffer, data, len);
00544         ADDINC128(ctx.bitcount, len << 3);
00545     }
00546 }
00547 
00548 
00549 /*
00550  *
00551  *
00552  *
00553  *  Public interfaces...
00554  *
00555  *
00556  *
00557  */
00558 
00559 void sha2::Init(SHA_TYPE type){
00560     m_Type = type;
00561     m_boolEnded = false;
00562     MEMSET_BZERO(&ctx, sizeof(SHA_CTX));
00563     switch (m_Type){
00564         case enuSHA1   : MEMCPY_BCOPY(ctx.state, sha1_initial_hash_value, sizeof(sha_word32) * 5); break;
00565         case enuSHA224 : MEMCPY_BCOPY(ctx.state, sha224_initial_hash_value, sizeof(sha_word32) * 8); break;
00566         case enuSHA256 : MEMCPY_BCOPY(ctx.state, sha256_initial_hash_value, sizeof(sha_word32) * 8); break;
00567         case enuSHA384 : MEMCPY_BCOPY(ctx.state, sha384_initial_hash_value, sizeof(sha_word64) * 8); break;
00568         case enuSHA512 : MEMCPY_BCOPY(ctx.state, sha512_initial_hash_value, sizeof(sha_word64) * 8); break;
00569         default : throw std::runtime_error("Invalid SHA_TYPE type!");
00570     }
00571 }
00572 
00573 
00574 void sha2::Update(const sha_byte* data, size_t len){
00575     switch (m_Type){
00576         case enuSHA1   : SHA32bit_Update(data, len, true); break;
00577         case enuSHA224 : SHA32bit_Update(data, len); break;
00578         case enuSHA256 : SHA32bit_Update(data, len); break;
00579         case enuSHA384 : SHA64bit_Update(data, len); break;
00580         case enuSHA512 : SHA64bit_Update(data, len); break;
00581         default : throw std::runtime_error("Invalid SHA_TYPE type!");
00582     }
00583 }
00584 
00585 
00586 void sha2::End(){
00587     sha_byte *d = m_digest;
00588     char *buf = m_chrHexHash;
00589     int i, j, diglen, statecnt=8;
00590     bool is64bit=false;
00591     sha_word32 *state32=(sha_word32 *)ctx.state;
00592     sha_word64 *state64=(sha_word64 *)ctx.state;
00593 
00594     switch (m_Type){
00595         case enuSHA1   : {
00596             SHA256_Internal_Last(true);
00597             statecnt = 5;
00598             diglen = SHA1_DIGESTC_LENGTH;
00599             break;
00600         }
00601         case enuSHA224 : {
00602             SHA256_Internal_Last();
00603             diglen = SHA224_DIGESTC_LENGTH;
00604             break;
00605         }
00606         case enuSHA256 : {
00607             SHA256_Internal_Last();
00608             diglen = SHA256_DIGESTC_LENGTH;
00609             break;
00610         }
00611         case enuSHA384 : {
00612             SHA512_Internal_Last();
00613             is64bit = true;
00614             diglen = SHA384_DIGESTC_LENGTH;
00615             break;
00616         }
00617         case enuSHA512 : {
00618             SHA512_Internal_Last();
00619             is64bit = true;
00620             diglen = SHA512_DIGESTC_LENGTH;
00621             break;
00622         }
00623         default : throw std::runtime_error("Invalid SHA_TYPE type!");
00624     }
00625     if (m_boolIsBigEndian){
00626         MEMCPY_BCOPY(&m_digest, &ctx.state, diglen);
00627     }else{
00628         sha_byte *dp = m_digest, *ptr;
00629         for (i=0; i<statecnt; i++){
00630             if (is64bit) ptr = (sha_byte *)&state64[i];
00631             else ptr = (sha_byte *)&state32[i];
00632             for (j = is64bit ? 7 : 3; j>-1; --j) *dp++ = ptr[j];
00633         }
00634     }
00635 
00636     for (i=0; i<diglen; i++) {
00637         *buf++ = sha_hex_digits[(*d & 0xf0) >> 4];
00638         *buf++ = sha_hex_digits[*d & 0x0f];
00639         d++;
00640     }
00641     *buf = (char)0;
00642     m_strHash = m_chrHexHash;
00643     m_boolEnded = true;
00644 }
00645 
00646 const string &sha2::GetHash(SHA_TYPE type, const sha_byte* data, size_t len){
00647     Init(type);
00648     Update(data, len);
00649     End();
00650     return m_strHash;
00651 }
00652 
00653 
00654 
00655 const char *sha2::HexHash(){
00656     if (!m_boolEnded) throw std::runtime_error("Unfinished execution!");
00657     return m_strHash.c_str();
00658 }
00659 const string &sha2::StringHash(){
00660     if (!m_boolEnded) throw std::runtime_error("Unfinished execution!");
00661     return m_strHash;
00662 }
00663 const char *sha2::RawHash(int &length){
00664     if (!m_boolEnded) throw std::runtime_error("Unfinished execution!");
00665     switch (m_Type){
00666         case enuSHA1   : length = SHA1_DIGESTC_LENGTH;   break;
00667         case enuSHA224 : length = SHA224_DIGESTC_LENGTH; break;
00668         case enuSHA256 : length = SHA256_DIGESTC_LENGTH; break;
00669         case enuSHA384 : length = SHA384_DIGESTC_LENGTH; break;
00670         case enuSHA512 : length = SHA512_DIGESTC_LENGTH; break;
00671         default : length = 0;
00672     }
00673     return (const char *)m_digest;
00674 }
00675 

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