LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 6804|回复: 4

SHA-1算法C语言实现

[复制链接]
发表于 2006-3-30 19:35:42 | 显示全部楼层 |阅读模式
从网上下载的 SHA-1算法C语言实现代码。

  1. /* sha1sum.c - print SHA-1 Message-Digest Algorithm
  2. * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
  3. * Copyright (C) 2004 g10 Code GmbH
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2, or (at your option) any
  8. * later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software Foundation,
  17. * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */

  19. /* SHA-1 coden take from gnupg 1.3.92.

  20.    Note, that this is a simple tool to be used for MS Windows.
  21. */

  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <assert.h>
  26. #include <errno.h>

  27. #undef BIG_ENDIAN_HOST
  28. typedef unsigned int u32;

  29. /****************
  30. * Rotate a 32 bit integer by n bytes
  31. ****************/
  32. #if defined(__GNUC__) && defined(__i386__)
  33. static inline u32 rol( u32 x, int n)
  34. {
  35.         __asm__("roll %%cl,%0"
  36.             :"=r" (x)
  37.             :"0" (x),"c" (n));
  38.         return x;
  39. }
  40. #else
  41. #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
  42. #endif


  43. typedef struct {
  44.     u32  h0,h1,h2,h3,h4;
  45.     u32  nblocks;
  46.     unsigned char buf[64];
  47.     int  count;
  48. } SHA1_CONTEXT;



  49. void sha1_init( SHA1_CONTEXT *hd )
  50. {
  51.     hd->h0 = 0x67452301;
  52.     hd->h1 = 0xefcdab89;
  53.     hd->h2 = 0x98badcfe;
  54.     hd->h3 = 0x10325476;
  55.     hd->h4 = 0xc3d2e1f0;
  56.     hd->nblocks = 0;
  57.     hd->count = 0;
  58. }


  59. /*
  60. * Transform the message X which consists of 16 32-bit-words
  61. */
  62. static void
  63. transform( SHA1_CONTEXT *hd, unsigned char *data )
  64. {
  65.     u32 a,b,c,d,e,tm;
  66.     u32 x[16];

  67.     /* get values from the chaining vars */
  68.     a = hd->h0;
  69.     b = hd->h1;
  70.     c = hd->h2;
  71.     d = hd->h3;
  72.     e = hd->h4;

  73. #ifdef BIG_ENDIAN_HOST
  74.     memcpy( x, data, 64 );
  75. #else
  76.     { int i;
  77.         unsigned char *p2;
  78.         for(i=0, p2=(unsigned char*)x; i < 16; i++, p2 += 4 ) {
  79.             p2[3] = *data++;
  80.             p2[2] = *data++;
  81.             p2[1] = *data++;
  82.             p2[0] = *data++;
  83.         }
  84.     }
  85. #endif


  86. #define K1  0x5A827999L
  87. #define K2  0x6ED9EBA1L
  88. #define K3  0x8F1BBCDCL
  89. #define K4  0xCA62C1D6L
  90. #define F1(x,y,z)   ( z ^ ( x & ( y ^ z ) ) )
  91. #define F2(x,y,z)   ( x ^ y ^ z )
  92. #define F3(x,y,z)   ( ( x & y ) | ( z & ( x | y ) ) )
  93. #define F4(x,y,z)   ( x ^ y ^ z )


  94. #define M(i) ( tm =   x[i&0x0f] ^ x[(i-14)&0x0f]    \
  95.                ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f]      \
  96.                , (x[i&0x0f] = rol(tm,1)) )

  97. #define R(a,b,c,d,e,f,k,m)  do { e += rol( a, 5 )   \
  98.             + f( b, c, d )                          \
  99.             + k                                     \
  100.             + m;                                    \
  101.         b = rol( b, 30 );                           \
  102.     } while(0)
  103.     R( a, b, c, d, e, F1, K1, x[ 0] );
  104.     R( e, a, b, c, d, F1, K1, x[ 1] );
  105.     R( d, e, a, b, c, F1, K1, x[ 2] );
  106.     R( c, d, e, a, b, F1, K1, x[ 3] );
  107.     R( b, c, d, e, a, F1, K1, x[ 4] );
  108.     R( a, b, c, d, e, F1, K1, x[ 5] );
  109.     R( e, a, b, c, d, F1, K1, x[ 6] );
  110.     R( d, e, a, b, c, F1, K1, x[ 7] );
  111.     R( c, d, e, a, b, F1, K1, x[ 8] );
  112.     R( b, c, d, e, a, F1, K1, x[ 9] );
  113.     R( a, b, c, d, e, F1, K1, x[10] );
  114.     R( e, a, b, c, d, F1, K1, x[11] );
  115.     R( d, e, a, b, c, F1, K1, x[12] );
  116.     R( c, d, e, a, b, F1, K1, x[13] );
  117.     R( b, c, d, e, a, F1, K1, x[14] );
  118.     R( a, b, c, d, e, F1, K1, x[15] );
  119.     R( e, a, b, c, d, F1, K1, M(16) );
  120.     R( d, e, a, b, c, F1, K1, M(17) );
  121.     R( c, d, e, a, b, F1, K1, M(18) );
  122.     R( b, c, d, e, a, F1, K1, M(19) );
  123.     R( a, b, c, d, e, F2, K2, M(20) );
  124.     R( e, a, b, c, d, F2, K2, M(21) );
  125.     R( d, e, a, b, c, F2, K2, M(22) );
  126.     R( c, d, e, a, b, F2, K2, M(23) );
  127.     R( b, c, d, e, a, F2, K2, M(24) );
  128.     R( a, b, c, d, e, F2, K2, M(25) );
  129.     R( e, a, b, c, d, F2, K2, M(26) );
  130.     R( d, e, a, b, c, F2, K2, M(27) );
  131.     R( c, d, e, a, b, F2, K2, M(28) );
  132.     R( b, c, d, e, a, F2, K2, M(29) );
  133.     R( a, b, c, d, e, F2, K2, M(30) );
  134.     R( e, a, b, c, d, F2, K2, M(31) );
  135.     R( d, e, a, b, c, F2, K2, M(32) );
  136.     R( c, d, e, a, b, F2, K2, M(33) );
  137.     R( b, c, d, e, a, F2, K2, M(34) );
  138.     R( a, b, c, d, e, F2, K2, M(35) );
  139.     R( e, a, b, c, d, F2, K2, M(36) );
  140.     R( d, e, a, b, c, F2, K2, M(37) );
  141.     R( c, d, e, a, b, F2, K2, M(38) );
  142.     R( b, c, d, e, a, F2, K2, M(39) );
  143.     R( a, b, c, d, e, F3, K3, M(40) );
  144.     R( e, a, b, c, d, F3, K3, M(41) );
  145.     R( d, e, a, b, c, F3, K3, M(42) );
  146.     R( c, d, e, a, b, F3, K3, M(43) );
  147.     R( b, c, d, e, a, F3, K3, M(44) );
  148.     R( a, b, c, d, e, F3, K3, M(45) );
  149.     R( e, a, b, c, d, F3, K3, M(46) );
  150.     R( d, e, a, b, c, F3, K3, M(47) );
  151.     R( c, d, e, a, b, F3, K3, M(48) );
  152.     R( b, c, d, e, a, F3, K3, M(49) );
  153.     R( a, b, c, d, e, F3, K3, M(50) );
  154.     R( e, a, b, c, d, F3, K3, M(51) );
  155.     R( d, e, a, b, c, F3, K3, M(52) );
  156.     R( c, d, e, a, b, F3, K3, M(53) );
  157.     R( b, c, d, e, a, F3, K3, M(54) );
  158.     R( a, b, c, d, e, F3, K3, M(55) );
  159.     R( e, a, b, c, d, F3, K3, M(56) );
  160.     R( d, e, a, b, c, F3, K3, M(57) );
  161.     R( c, d, e, a, b, F3, K3, M(58) );
  162.     R( b, c, d, e, a, F3, K3, M(59) );
  163.     R( a, b, c, d, e, F4, K4, M(60) );
  164.     R( e, a, b, c, d, F4, K4, M(61) );
  165.     R( d, e, a, b, c, F4, K4, M(62) );
  166.     R( c, d, e, a, b, F4, K4, M(63) );
  167.     R( b, c, d, e, a, F4, K4, M(64) );
  168.     R( a, b, c, d, e, F4, K4, M(65) );
  169.     R( e, a, b, c, d, F4, K4, M(66) );
  170.     R( d, e, a, b, c, F4, K4, M(67) );
  171.     R( c, d, e, a, b, F4, K4, M(68) );
  172.     R( b, c, d, e, a, F4, K4, M(69) );
  173.     R( a, b, c, d, e, F4, K4, M(70) );
  174.     R( e, a, b, c, d, F4, K4, M(71) );
  175.     R( d, e, a, b, c, F4, K4, M(72) );
  176.     R( c, d, e, a, b, F4, K4, M(73) );
  177.     R( b, c, d, e, a, F4, K4, M(74) );
  178.     R( a, b, c, d, e, F4, K4, M(75) );
  179.     R( e, a, b, c, d, F4, K4, M(76) );
  180.     R( d, e, a, b, c, F4, K4, M(77) );
  181.     R( c, d, e, a, b, F4, K4, M(78) );
  182.     R( b, c, d, e, a, F4, K4, M(79) );

  183.     /* Update chaining vars */
  184.     hd->h0 += a;
  185.     hd->h1 += b;
  186.     hd->h2 += c;
  187.     hd->h3 += d;
  188.     hd->h4 += e;
  189. }


  190. /* Update the message digest with the contents
  191. * of INBUF with length INLEN.
  192. */
  193. static void sha1_write( SHA1_CONTEXT *hd, unsigned char *inbuf, size_t inlen)
  194. {
  195.     if( hd->count == 64 ) { /* flush the buffer */
  196.         transform( hd, hd->buf );
  197.         hd->count = 0;
  198.         hd->nblocks++;
  199.     }
  200.     if( !inbuf )
  201.         return;
  202.     if( hd->count ) {
  203.         for( ; inlen && hd->count < 64; inlen-- )
  204.             hd->buf[hd->count++] = *inbuf++;
  205.         sha1_write( hd, NULL, 0 );
  206.         if( !inlen )
  207.             return;
  208.     }

  209.     while( inlen >= 64 ) {
  210.         transform( hd, inbuf );
  211.         hd->count = 0;
  212.         hd->nblocks++;
  213.         inlen -= 64;
  214.         inbuf += 64;
  215.     }
  216.     for( ; inlen && hd->count < 64; inlen-- )
  217.         hd->buf[hd->count++] = *inbuf++;
  218. }


  219. /* The routine final terminates the computation and
  220. * returns the digest.
  221. * The handle is prepared for a new cycle, but adding bytes to the
  222. * handle will the destroy the returned buffer.
  223. * Returns: 20 bytes representing the digest.
  224. */

  225. static void sha1_final(SHA1_CONTEXT *hd)
  226. {
  227.     u32 t, msb, lsb;
  228.     unsigned char *p;

  229.     sha1_write(hd, NULL, 0); /* flush */;

  230.     t = hd->nblocks;
  231.     /* multiply by 64 to make a byte count */
  232.     lsb = t << 6;
  233.     msb = t >> 26;
  234.     /* add the count */
  235.     t = lsb;
  236.     if( (lsb += hd->count) < t )
  237.         msb++;
  238.     /* multiply by 8 to make a bit count */
  239.     t = lsb;
  240.     lsb <<= 3;
  241.     msb <<= 3;
  242.     msb |= t >> 29;

  243.     if( hd->count < 56 ) { /* enough room */
  244.         hd->buf[hd->count++] = 0x80; /* pad */
  245.         while( hd->count < 56 )
  246.             hd->buf[hd->count++] = 0;  /* pad */
  247.     }
  248.     else { /* need one extra block */
  249.         hd->buf[hd->count++] = 0x80; /* pad character */
  250.         while( hd->count < 64 )
  251.             hd->buf[hd->count++] = 0;
  252.         sha1_write(hd, NULL, 0);  /* flush */;
  253.         memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
  254.     }
  255.     /* append the 64 bit count */
  256.     hd->buf[56] = msb >> 24;
  257.     hd->buf[57] = msb >> 16;
  258.     hd->buf[58] = msb >>  8;
  259.     hd->buf[59] = msb           ;
  260.     hd->buf[60] = lsb >> 24;
  261.     hd->buf[61] = lsb >> 16;
  262.     hd->buf[62] = lsb >>  8;
  263.     hd->buf[63] = lsb           ;
  264.     transform( hd, hd->buf );

  265.     p = hd->buf;
  266. #ifdef BIG_ENDIAN_HOST
  267. #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
  268. #else /* little endian */
  269. #define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \
  270.         *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0)
  271. #endif
  272.     X(0);
  273.     X(1);
  274.     X(2);
  275.     X(3);
  276.     X(4);
  277. #undef X
  278. }




  279. int main (int argc, char **argv)
  280. {
  281.     assert (sizeof (u32) == 4);

  282.     if (argc < 2)
  283.     {
  284.         fprintf (stderr, "usage: sha1sum filenames\n");
  285.         exit (1);
  286.     }
  287.     for (argc--, argv++; argc; argv++, argc--)
  288.     {
  289.         FILE *fp;
  290.         char buffer[4096];
  291.         size_t n;
  292.         SHA1_CONTEXT ctx;
  293.         int i;
  294.       
  295.         fp = fopen (*argv, "rb");
  296.         if (!fp)
  297.         {
  298.             fprintf (stderr, "can't open `%s': %s\n", *argv, strerror (errno));
  299.             exit (1);
  300.         }
  301.         sha1_init (&ctx);
  302.         while ( (n = fread (buffer, 1, sizeof buffer, fp)))
  303.             sha1_write (&ctx, buffer, n);
  304.         if (ferror (fp))
  305.         {
  306.             fprintf (stderr, "error reading `%s': %s\n", *argv,strerror (errno));
  307.             exit (1);
  308.         }
  309.         sha1_final (&ctx);
  310.         fclose (fp);
  311.       
  312.         for (i=0; i < 20; i++)
  313.             printf ("%02x", ctx.buf[i]);
  314.         printf ("  %s\n", *argv);
  315.     }
  316.     return 0;
  317. }

  318. /*
  319. Local Variables:
  320. compile-command: "cc -Wall -g -o sha1sum sha1sum.c"
  321. End:
  322. */

复制代码
发表于 2006-3-30 20:24:13 | 显示全部楼层
好像不长啊,可惜看不懂...
回复 支持 反对

使用道具 举报

发表于 2006-3-31 00:29:34 | 显示全部楼层
帖算法而不是代码应该更好一点
回复 支持 反对

使用道具 举报

发表于 2006-5-6 22:43:58 | 显示全部楼层
Post by rickxbx
帖算法而不是代码应该更好一点


最好再带一个实例的 (Vector).
回复 支持 反对

使用道具 举报

发表于 2006-5-7 12:47:02 | 显示全部楼层
要是能讲下算法的思想和具体的实现就好了。贴了代码也是看不懂的,一头雾水呢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表