home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1998 February / PCOnline_02_1998.iso / filesbbs / win95 / cryptext.exe / Sha.c < prev    next >
C/C++ Source or Header  |  1996-09-02  |  9KB  |  349 lines

  1. /* Implementation of NIST's Secure Hash Algorithm (FIPS 180)
  2.  * Lightly bummed for execution efficiency.
  3.  *
  4.  * Jim Gillogly 3 May 1993
  5.  *
  6.  * 27 Aug 93: imported LITTLE_ENDIAN mods from Peter Gutmann's implementation
  7.  * 5 Jul 94: Modified for NSA fix
  8.  *
  9.  * Compile: cc -O -o sha sha.c
  10.  *
  11.  * To remove the test wrapper and use just the nist_hash () routine,
  12.  *      compile with -DDONT_WRAP
  13.  *
  14.  * To reverse byte order for little-endian machines, use -DLITTLE_ENDIAN
  15.  *
  16.  * To get the original SHA definition before the 1994 fix, use -DVERSION_0
  17.  *
  18.  * Usage: sha [-vt] [filename ...]
  19.  *
  20.  *      -v switch: output the filename as well
  21.  *      -t switch: suppress spaces between 32-bit blocks
  22.  *
  23.  *      If no input files are specified, process standard input.
  24.  *
  25.  * Output: 40-hex-digit digest of each file specified (160 bits)
  26.  *
  27.  * Synopsis of the function calls:
  28.  *
  29.  *   sha_file (char *filename, unsigned long *buffer)
  30.  *      Filename is a file to be opened and processed.
  31.  *      buffer is a user-supplied array of 5 or more longs.
  32.  *      The 5-word buffer is filled with 160 bits of non-terminated hash.
  33.  *      Returns 0 if successful, non-zero if bad file.
  34.  *
  35.  *   void sha_stream (FILE *stream, unsigned long *buffer)
  36.  *      Input is from already-opened stream, not file.
  37.  *
  38.  *   void sha_memory (char *mem, long length, unsigned long *buffer)
  39.  *      Input is a memory block "length" bytes long.
  40.  *
  41.  * Caveat:
  42.  *      Not tested for case that requires the high word of the length,
  43.  *      which would be files larger than 1/2 gig or so.
  44.  *
  45.  * Limitation:
  46.  *      sha_memory (the memory block function) will deal with blocks no longer
  47.  *      than 4 gigabytes; for longer samples, the stream version will
  48.  *      probably be most convenient (e.g. perl moby_data.pl | sha).
  49.  *
  50.  * Bugs:
  51.  *      The standard is defined for bit strings; I assume bytes.
  52.  *
  53.  * Copyright 1993, Dr. James J. Gillogly
  54.  * This code may be freely used in any application.
  55.  */
  56.  
  57. #define LITTLE_ENDIAN
  58.  
  59. // #define VERSION_0  Define this to get the original SHA definition
  60.  
  61. #include <windows.h>
  62. #include <stdio.h>
  63. #include <memory.h>
  64. #include "sha.h"
  65.  
  66. #define VERBOSE
  67.  
  68. #define SUCCESS 0
  69. #define FAILURE -1
  70.  
  71. // Using just the hash routine itself
  72. #ifndef DONT_WRAP
  73.  
  74. // Produces 160-bit digest of the message
  75. #define HASH_SIZE 5
  76.  
  77. int main (int argc, char **argv)
  78. {
  79.     DWORD    hbuf[HASH_SIZE];
  80.     LPSTR    s;
  81.     int     file_args = FALSE;    // If no files, take it from stdin
  82.     int     verbose = FALSE;
  83.     int     terse = FALSE;
  84.  
  85. #ifdef MEMTEST
  86.     sha_memory ("abc", 3l, hbuf);        // NIST test value from appendix A
  87.     if (verbose) printf ("Memory:");
  88.     if (terse) printf ("%08lx%08lx%08lx%08lx%08lx\n",
  89.     hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
  90.     else printf ("%08lx %08lx %08lx %08lx %08lx\n",
  91.     hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
  92. #endif
  93.  
  94.     for (++argv; --argc; ++argv)    // March down the arg list
  95.     {
  96.         if (**argv == '-')                // Process one or more flags
  97.             for (s = &(*argv)[1]; *s; s++)    // Obfuscated C contest entry
  98.                 switch (*s)
  99.                 {
  100.                     case 'v': case 'V':
  101.                         verbose = TRUE;
  102.                         break;
  103.  
  104.                     case 't': case 'T':
  105.                         terse = TRUE;
  106.                         break;
  107.  
  108.                     default:
  109.                         fprintf (stderr, "Unrecognized flag: %c\n", *s);
  110.                         return FALSE;
  111.                 }
  112.         else        // Process a file
  113.         {
  114.             if (verbose) printf ("%s:", *argv);
  115.             file_args = TRUE;        // Whether or not we could read it
  116.  
  117.             if (sha_file (*argv, hbuf) == FAILURE)
  118.                 printf ("Can't open file %s.\n", *argv);
  119.             else
  120.                 if (terse) printf ("%08lx%08lx%08lx%08lx%08lx\n",
  121.                     hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
  122.                 else printf ("%08lx %08lx %08lx %08lx %08lx\n",
  123.                     hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
  124.         }
  125.     }
  126.     if (! file_args)        // No file specified
  127.     {
  128.         if (verbose) printf ("%s:", *argv);
  129.         sha_stream (stdin, hbuf);
  130.  
  131.         if (terse) printf ("%08lx%08lx%08lx%08lx%08lx\n",
  132.             hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
  133.         else printf ("%08lx %08lx %08lx %08lx %08lx\n",
  134.             hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
  135.     }
  136.     return TRUE;
  137. }
  138.  
  139. #endif // DONT_WRAP
  140.  
  141. // Imported from Peter Gutmann's implementation
  142. #ifdef LITTLE_ENDIAN
  143.  
  144. /* When run on a little-endian CPU we need to perform byte reversal on an
  145.    array of longwords.  It is possible to make the code endianness-
  146.    independant by fiddling around with data at the byte level, but this
  147.    makes for very slow code, so we rely on the user to sort out endianness
  148.    at compile time */
  149.  
  150. static void
  151. byteReverse (LPDWORD buffer, int byteCount)
  152. {
  153.     DWORD    value;
  154.     int     count;
  155.  
  156.     byteCount /= sizeof (DWORD);
  157.     for (count = 0; count < byteCount; count++)
  158.     {
  159.         value = (buffer[count] << 16 ) | (buffer[count] >> 16);
  160.         buffer[count] = ((value & 0xFF00FF00L) >> 8) | ((value & 0x00FF00FFL) << 8);
  161.     }
  162. }
  163. #endif    // LITTLE_ENDIAN
  164.  
  165.  
  166.  
  167. union longbyte
  168. {
  169.     DWORD    W[80];        // Process 16 32-bit words at a time
  170.     BYTE    B[320];        // But read them as bytes for counting
  171. };
  172.  
  173. int
  174. sha_file (LPSTR filename, DWORD *buffer)    // Hash a file
  175. {
  176.     FILE *infile;
  177.  
  178.     if ((infile = fopen (filename, "rb")) == NULL)
  179.     {
  180.         int i;
  181.  
  182.         for (i = 0; i < 5; i++)
  183.             buffer[i] = 0xdeadbeef;
  184.         return FAILURE;
  185.     }
  186.     sha_stream (infile, buffer);
  187.     fclose (infile);
  188.     return SUCCESS;
  189. }
  190.  
  191. void
  192. sha_memory (LPBYTE mem, DWORD length, LPDWORD buffer)    // Hash a memory block
  193. {
  194.     nist_guts (FALSE, (FILE *) NULL, mem, length, buffer);
  195. }
  196.  
  197. void
  198. sha_stream (FILE *stream, LPDWORD buffer)
  199. {
  200.     nist_guts (TRUE, stream, NULL, 0l, buffer);
  201. }
  202.  
  203. // magic functions
  204. #define f0(x,y,z) (z ^ (x & (y ^ z)))
  205. #define f1(x,y,z) (x ^ y ^ z)
  206. #define f2(x,y,z) ((x & y) | (z & (x | y)))
  207. #define f3(x,y,z) (x ^ y ^ z)
  208.  
  209. // magic constants
  210. #define K0 0x5a827999
  211. #define K1 0x6ed9eba1
  212. #define K2 0x8f1bbcdc
  213. #define K3 0xca62c1d6
  214.  
  215. // barrel roll
  216. #define S(n, X) ((X << n) | (X >> (32 - n)))
  217.  
  218. #define r0(f, K) \
  219.     temp = S(5, A) + f(B, C, D) + E + *p0++ + K; \
  220.     E = D;  \
  221.     D = C;  \
  222.     C = S(30, B); \
  223.     B = A;  \
  224.     A = temp
  225.  
  226. #ifdef VERSION_0
  227. #define r1(f, K) \
  228.     temp = S(5, A) + f(B, C, D) + E + \
  229.        (*p0++ = *p1++ ^ *p2++ ^ *p3++ ^ *p4++) + K; \
  230.     E = D;  \
  231.     D = C;  \
  232.     C = S(30, B); \
  233.     B = A;  \
  234.     A = temp
  235. #else
  236. // version 1: summer '94 update
  237. #define r1(f, K) \
  238.     temp = *p1++ ^ *p2++ ^ *p3++ ^ *p4++; \
  239.     temp = S(5, A) + f(B, C, D) + E + (*p0++ = S(1,temp)) + K; \
  240.     E = D;  \
  241.     D = C;  \
  242.     C = S(30, B); \
  243.     B = A;  \
  244.     A = temp
  245. #endif
  246.  
  247. static void
  248. nist_guts (BOOL file_flag, FILE *stream, LPBYTE mem, DWORD length, LPDWORD buf)
  249. {
  250.     int        i, nread, nbits;
  251.     union    longbyte d;
  252.     DWORD    hi_length, lo_length;
  253.     BOOL    padded;
  254.     LPBYTE    s;
  255.  
  256.     LPDWORD    p0, p1, p2, p3, p4;
  257.     DWORD    A, B, C, D, E, temp;
  258.  
  259.     DWORD    h0, h1, h2, h3, h4;
  260.  
  261.     h0 = 0x67452301;    // Accumulators
  262.     h1 = 0xefcdab89;
  263.     h2 = 0x98badcfe;
  264.     h3 = 0x10325476;
  265.     h4 = 0xc3d2e1f0;
  266.  
  267.     padded = FALSE;
  268.     s = mem;
  269.     for (hi_length = lo_length = 0; ;)    // Process 16 longs at a time
  270.     {
  271.         if (file_flag)
  272.             nread = fread (d.B, 1, 64, stream);    // Read as 64 bytes
  273.         else
  274.         {
  275.             if (length < 64)
  276.                 nread = length;
  277.             else
  278.                 nread = 64;
  279.             length -= nread;
  280.             memcpy (d.B, s, nread);
  281.             s += nread;
  282.         }
  283.         if (nread < 64)                        // Partial block?
  284.         {
  285.             nbits = nread << 3;                // Length: bits
  286.             if ((lo_length += nbits) < nbits)
  287.                 hi_length++;                // 64-bit integer
  288.  
  289.             if (nread < 64 && !padded)        // Append a single bit
  290.             {
  291.                 d.B[nread++] = 0x80;        // Using up next byte
  292.                 padded = TRUE;                // Single bit once
  293.             }
  294.             for (i = nread; i < 64; i++)    // Pad with nulls
  295.                 d.B[i] = 0;
  296.             if (nread <= 56)                // Room for length in this block
  297.             {
  298.                 d.W[14] = hi_length;
  299.                 d.W[15] = lo_length;
  300. #ifdef LITTLE_ENDIAN
  301.                 byteReverse (d.W, 56);
  302. #endif    // LITTLE_ENDIAN
  303.             }
  304. #ifdef LITTLE_ENDIAN
  305.             else
  306.                 byteReverse (d.W, 64);
  307. #endif    // LITTLE_ENDIAN
  308.         }
  309.         else    // Full block -- get efficient
  310.         {
  311.             if ((lo_length += 512) < 512)
  312.                 hi_length++;                // 64-bit integer
  313. #ifdef LITTLE_ENDIAN
  314.             byteReverse (d.W, 64);
  315. #endif    // LITTLE_ENDIAN
  316.         }
  317.  
  318.         p0 = d.W;
  319.         A = h0; B = h1; C = h2; D = h3; E = h4;
  320.  
  321.         r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0);
  322.         r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0);
  323.         r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0);
  324.         r0(f0,K0);
  325.  
  326.         p1 = &d.W[13]; p2 = &d.W[8]; p3 = &d.W[2]; p4 = &d.W[0];
  327.  
  328.         r1(f0,K0); r1(f0,K0); r1(f0,K0); r1(f0,K0);
  329.         r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
  330.         r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
  331.         r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
  332.         r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
  333.         r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
  334.         r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
  335.         r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
  336.         r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
  337.         r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
  338.         r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
  339.         r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
  340.         r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
  341.  
  342.         h0 += A; h1 += B; h2 += C; h3 += D; h4 += E;
  343.  
  344.         if (nread <= 56) break;        // If it's greater, length in next block
  345.     }
  346.     buf[0] = h0; buf[1] = h1; buf[2] = h2; buf[3] = h3; buf[4] = h4;
  347. }
  348.  
  349.