sha256.cpp

Ir a la documentación de este archivo.
00001 // vim: set expandtab tabstop=8 shiftwidth=8 foldmethod=marker:
00022 #include "sha256.hpp"
00023 #include <stdio.h>
00024 #include <signal.h>
00025 #include <cstring>
00026 #include <string>
00027 #include <sstream>
00028 #include <iomanip>
00029 #include <iostream>
00030 
00031 using namespace std;
00032 
00033 void crypt_argchk(char *v, char *s, int d)
00034 {
00035         fprintf(stderr, "LTC_ARGCHK '%s' failure on line %d of file %s\n",
00036                 v, d, s);
00037         exit(1);
00038 }
00039 
00040 const struct ltc_hash_descriptor sha256_desc =
00041         {
00042                 "sha256",
00043                 0,
00044                 32,
00045                 64,
00046 
00047                 /* OID */
00048                 { 2, 16, 840, 1, 101, 3, 4, 2, 1,  },
00049                 9,
00050 
00051                 &sha256_init,
00052                 &sha256_process,
00053                 &sha256_done,
00054                 NULL,
00055                 NULL
00056         };
00057 
00058 
00059 /* Arreglo K */
00060 static const ulong32 K[64] =
00061         {
00062                 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
00063                 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
00064                 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
00065                 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
00066                 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
00067                 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
00068                 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
00069                 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
00070                 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
00071                 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
00072                 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
00073                 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
00074                 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
00075         };
00076 
00077 /* funciones lógicas */
00078 #define Ch(x,y,z)       (z ^ (x & (y ^ z)))
00079 #define Maj(x,y,z)      (((x | y) & z) | (x & y))
00080 #define S(x, n)         RORc((x),(n))
00081 #define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
00082 #define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
00083 #define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
00084 #define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
00085 #define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
00086 
00087 /* Comprime 512-bits */
00088 #ifdef LTC_CLEAN_STACK
00089 static int _sha256_compress(hash_state * md, unsigned char *buf)
00090 #else
00091 static int  sha256_compress(hash_state * md, unsigned char *buf)
00092 #endif
00093 {
00094         ulong32 S[8], W[64], t0, t1;
00095 #ifdef LTC_SMALL_CODE
00096 
00097         ulong32 t;
00098 #endif
00099 
00100         int i;
00101 
00102         /* copy state into S */
00103         for (i = 0; i < 8; i++)
00104         {
00105                 S[i] = md->sha256.state[i];
00106         }
00107 
00108         /* copy the state into 512-bits into W[0..15] */
00109         for (i = 0; i < 16; i++)
00110         {
00111                 LOAD32H(W[i], buf + (4*i));
00112         }
00113 
00114         /* fill W[16..63] */
00115         for (i = 16; i < 64; i++)
00116         {
00117                 W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
00118         }
00119 
00120         /* Compress */
00121 #ifdef LTC_SMALL_CODE
00122 #define RND(a,b,c,d,e,f,g,h,i)                         \
00123      t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
00124      t1 = Sigma0(a) + Maj(a, b, c);                    \
00125      d += t0;                                          \
00126      h  = t0 + t1;
00127 
00128         for (i = 0; i < 64; ++i)
00129         {
00130                 RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i);
00131                 t = S[7];
00132                 S[7] = S[6];
00133                 S[6] = S[5];
00134                 S[5] = S[4];
00135                 S[4] = S[3];
00136                 S[3] = S[2];
00137                 S[2] = S[1];
00138                 S[1] = S[0];
00139                 S[0] = t;
00140         }
00141 #else
00142 #define RND(a,b,c,d,e,f,g,h,i,ki)                    \
00143      t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i];   \
00144      t1 = Sigma0(a) + Maj(a, b, c);                  \
00145      d += t0;                                        \
00146      h  = t0 + t1;
00147 
00148         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
00149         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
00150         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
00151         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
00152         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
00153         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
00154         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
00155         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
00156         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
00157         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
00158         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
00159         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
00160         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
00161         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
00162         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
00163         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
00164         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
00165         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
00166         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
00167         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
00168         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
00169         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
00170         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
00171         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
00172         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
00173         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
00174         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
00175         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
00176         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
00177         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
00178         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
00179         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
00180         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
00181         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
00182         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
00183         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
00184         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
00185         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
00186         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
00187         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
00188         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
00189         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
00190         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
00191         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
00192         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
00193         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
00194         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
00195         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
00196         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
00197         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
00198         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
00199         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
00200         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
00201         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
00202         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
00203         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
00204         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
00205         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
00206         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
00207         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
00208         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
00209         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
00210         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
00211         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);
00212 
00213 #undef RND
00214 
00215 #endif
00216 
00217         /* feedback */
00218         for (i = 0; i < 8; i++)
00219         {
00220                 md->sha256.state[i] = md->sha256.state[i] + S[i];
00221         }
00222         return CRYPT_OK;
00223 }
00224 
00225 #ifdef LTC_CLEAN_STACK
00226 static int sha256_compress(hash_state * md, unsigned char *buf)
00227 {
00228         int err;
00229         err = _sha256_compress(md, buf);
00230         burn_stack(sizeof(ulong32) * 74);
00231         return err;
00232 }
00233 #endif
00234 
00235 int sha256_init(hash_state * md)
00236 {
00237         LTC_ARGCHK(md != NULL);
00238 
00239         md->sha256.curlen = 0;
00240         md->sha256.length = 0;
00241         md->sha256.state[0] = 0x6A09E667UL;
00242         md->sha256.state[1] = 0xBB67AE85UL;
00243         md->sha256.state[2] = 0x3C6EF372UL;
00244         md->sha256.state[3] = 0xA54FF53AUL;
00245         md->sha256.state[4] = 0x510E527FUL;
00246         md->sha256.state[5] = 0x9B05688CUL;
00247         md->sha256.state[6] = 0x1F83D9ABUL;
00248         md->sha256.state[7] = 0x5BE0CD19UL;
00249         return CRYPT_OK;
00250 }
00251 
00252 HASH_PROCESS(sha256_process, sha256_compress, sha256, 64)
00253 
00254 int sha256_done(hash_state * md, unsigned char *out)
00255 {
00256         int i;
00257 
00258         LTC_ARGCHK(md  != NULL);
00259         LTC_ARGCHK(out != NULL);
00260 
00261         if (md->sha256.curlen >= sizeof(md->sha256.buf)) {
00262                 return CRYPT_INVALID_ARG;
00263         }
00264 
00265 
00266         /* increase the length of the message */
00267         md->sha256.length += md->sha256.curlen * 8;
00268 
00269         /* append the '1' bit */
00270         md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80;
00271 
00272         /* if the length is currently above 56 bytes we append zeros
00273          * then compress.  Then we can fall back to padding zeros and length
00274          * encoding like normal.
00275          */
00276         if (md->sha256.curlen > 56) {
00277                 while (md->sha256.curlen < 64) {
00278                         md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
00279                 }
00280                 sha256_compress(md, md->sha256.buf);
00281                 md->sha256.curlen = 0;
00282         }
00283 
00284         /* pad upto 56 bytes of zeroes */
00285         while (md->sha256.curlen < 56) {
00286                 md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
00287         }
00288 
00289         /* store length */
00290         STORE64H(md->sha256.length, md->sha256.buf+56);
00291         sha256_compress(md, md->sha256.buf);
00292 
00293         /* copy output */
00294         for (i = 0; i < 8; i++) {
00295                 STORE32H(md->sha256.state[i], out+(4*i));
00296         }
00297 #ifdef LTC_CLEAN_STACK
00298         zeromem(md, sizeof(hash_state));
00299 #endif
00300 
00301         return CRYPT_OK;
00302 }
00303 
00304 
00305 string hexaDeHash(unsigned char *hash, int l)
00306 {
00307         int i;
00308         stringstream ss;
00309         ss.str("");
00310         ss.clear();
00311         for (i=0; i< l; i++) {
00312                 ss << setfill('0') << setw(2) << setbase(16) <<
00313                 (unsigned int)hash[i];
00314         }
00315         return ss.str();
00316 }
00317 
00318 
00319 
00320 /* Calcula condensado SHA-256 de un archivo.
00321  *
00322  * Basado en md5wrapper::getHashFromFile(std::string filename)  de
00323  * código de dominio público.
00324  * Feb. 2005    Benjamin Grüdelbach    
00325  * http://www.md5hashing.com/c++/md5wrapper.h
00326  *
00327  * @param narch Nombre del archivo
00328  */
00329 std::string sha256archivo(std::string narch)
00330 {
00331         FILE *file;
00332         hash_state md;
00333         int len;
00334         unsigned char colchon[1024], hash[33];
00335 
00336         if ((file = fopen (narch.c_str(), "rb")) == NULL) {
00337                 cerr << "sha256archivo no pudo abrir archivo '" <<
00338                 narch << "'" << endl;
00339                 exit(1);
00340         }
00341 
00342         sha256_init(&md);
00343 
00344         while ( (len = fread (colchon, 1, 1024, file)) ) {
00345                 sha256_process(&md, colchon, len);
00346         }
00347 
00348         sha256_done(&md, hash);
00349         fclose (file);
00350 
00351         return hexaDeHash(hash, 32);
00352 }
00353 
00354 /*
00355  * EOF
00356  */
00357 
00358 #ifdef EJEMPLO_SHA256
00359 
00360 int main()
00361 {
00362         hash_state md;
00363         unsigned char *in = (unsigned char *)"hola mundo", out[33];
00364         sha256_init(&md);
00365         sha256_process(&md, (const unsigned char *)in, strlen((char *)in));
00366         sha256_done(&md, out);
00367         int i;
00368         for (i=0; i< 32; i++) {
00369                 printf("%02x", out[i]);
00370         }
00371         printf("\n");
00372         return 0;
00373 }
00374 
00375 #endif

Generado el Wed Jan 6 06:58:22 2010 para Mt77 por  doxygen 1.5.4