SHA1算法C#描述

前一段时间把MD5写出来了: http://blog.csdn.net/aimeast/archive/2008/11/19/3337153.aspx
今天又把SHA1写了出来。
这个类于前面那个MD5是相似的。正确性的验证也于MD5完全相同。

  1. /*********************************************/
  2. //
  3. //  
  4. //  未经允许,禁止转载
  5. //  2008-11-22 23:42:39
  6. //  Email:  lixd3389@gmail.com
  7. //  Blog:   http://blog.csdn.net/aimeast
  8. //  原文地址:http://blog.csdn.net/aimeast/archive/2008/11/22/3352612.aspx
  9. //
  10. /*********************************************/
  11. using System;
  12. using System.IO;
  13. namespace MY_SHA1
  14. {
  15.     class My_SHA1
  16.     {
  17.         private static UInt32 h0, h1, h2, h3, h4;
  18.         private const UInt32 K1 = 0x5A827999;
  19.         private const UInt32 K2 = 0x6ED9EBA1;
  20.         private const UInt32 K3 = 0x8F1BBCDC;
  21.         private const UInt32 K4 = 0xCA62C1D6;
  22.         private static UInt32 F1(UInt32 x, UInt32 y, UInt32 z) { return (z ^ (x & (y ^ z))); }
  23.         private static UInt32 F2(UInt32 x, UInt32 y, UInt32 z) { return (x ^ y ^ z); }
  24.         private static UInt32 F3(UInt32 x, UInt32 y, UInt32 z) { return ((x & y) | (z & (x | y))); }
  25.         private static UInt32 F4(UInt32 x, UInt32 y, UInt32 z) { return (x ^ y ^ z); }
  26.         private static UInt32 rol(UInt32 x, int n) { return ((x << n) | (x >> (32 - n))); }
  27.         private static UInt32 M(UInt32[] x, int i)
  28.         {
  29.             UInt32 tm = x[i & 0x0f] ^ x[(i - 14) & 0x0f] ^ x[(i - 8) & 0x0f] ^ x[(i - 3) & 0x0f];
  30.             return (x[i & 0x0f] = rol(tm, 1));
  31.         }
  32.         private static void R(UInt32 a, ref  UInt32 b, ref UInt32 e, UInt32 f, UInt32 k, UInt32 m)
  33.         {
  34.             e += rol(a, 5) + f + k + m;
  35.             b = rol(b, 30);
  36.         }
  37.         private static void sha1_init()
  38.         {
  39.             h0 = 0x67452301;
  40.             h1 = 0xefcdab89;
  41.             h2 = 0x98badcfe;
  42.             h3 = 0x10325476;
  43.             h4 = 0xc3d2e1f0;
  44.         }
  45.         private static void sha1_transform(byte[] block)
  46.         {
  47.             UInt32 a, b, c, d, e;
  48.             UInt32[] x = new UInt32[16];
  49.             a = h0;
  50.             b = h1;
  51.             c = h2;
  52.             d = h3;
  53.             e = h4;
  54.             for(int i = 0, j = 0;i < 16;i++, j += 4)
  55.                 x[i] = BitConverter.ToUInt32(new byte[] { block[j + 3], block[j + 2], block[j + 1], block[j] }, 0);
  56.             R(a, ref b, ref e, F1(b, c, d), K1, x[0]);
  57.             R(e, ref a, ref d, F1(a, b, c), K1, x[1]);
  58.             R(d, ref e, ref c, F1(e, a, b), K1, x[2]);
  59.             R(c, ref d, ref b, F1(d, e, a), K1, x[3]);
  60.             R(b, ref c, ref a, F1(c, d, e), K1, x[4]);
  61.             R(a, ref b, ref e, F1(b, c, d), K1, x[5]);
  62.             R(e, ref a, ref d, F1(a, b, c), K1, x[6]);
  63.             R(d, ref e, ref c, F1(e, a, b), K1, x[7]);
  64.             R(c, ref d, ref b, F1(d, e, a), K1, x[8]);
  65.             R(b, ref c, ref a, F1(c, d, e), K1, x[9]);
  66.             R(a, ref b, ref e, F1(b, c, d), K1, x[10]);
  67.             R(e, ref a, ref d, F1(a, b, c), K1, x[11]);
  68.             R(d, ref e, ref c, F1(e, a, b), K1, x[12]);
  69.             R(c, ref d, ref b, F1(d, e, a), K1, x[13]);
  70.             R(b, ref c, ref a, F1(c, d, e), K1, x[14]);
  71.             R(a, ref b, ref e, F1(b, c, d), K1, x[15]);
  72.             R(e, ref a, ref d, F1(a, b, c), K1, M(x, 16));
  73.             R(d, ref e, ref c, F1(e, a, b), K1, M(x, 17));
  74.             R(c, ref d, ref b, F1(d, e, a), K1, M(x, 18));
  75.             R(b, ref c, ref a, F1(c, d, e), K1, M(x, 19));
  76.             R(a, ref b, ref e, F2(b, c, d), K2, M(x, 20));
  77.             R(e, ref a, ref d, F2(a, b, c), K2, M(x, 21));
  78.             R(d, ref e, ref c, F2(e, a, b), K2, M(x, 22));
  79.             R(c, ref d, ref b, F2(d, e, a), K2, M(x, 23));
  80.             R(b, ref c, ref a, F2(c, d, e), K2, M(x, 24));
  81.             R(a, ref b, ref e, F2(b, c, d), K2, M(x, 25));
  82.             R(e, ref a, ref d, F2(a, b, c), K2, M(x, 26));
  83.             R(d, ref e, ref c, F2(e, a, b), K2, M(x, 27));
  84.             R(c, ref d, ref b, F2(d, e, a), K2, M(x, 28));
  85.             R(b, ref c, ref a, F2(c, d, e), K2, M(x, 29));
  86.             R(a, ref b, ref e, F2(b, c, d), K2, M(x, 30));
  87.             R(e, ref a, ref d, F2(a, b, c), K2, M(x, 31));
  88.             R(d, ref e, ref c, F2(e, a, b), K2, M(x, 32));
  89.             R(c, ref d, ref b, F2(d, e, a), K2, M(x, 33));
  90.             R(b, ref c, ref a, F2(c, d, e), K2, M(x, 34));
  91.             R(a, ref b, ref e, F2(b, c, d), K2, M(x, 35));
  92.             R(e, ref a, ref d, F2(a, b, c), K2, M(x, 36));
  93.             R(d, ref e, ref c, F2(e, a, b), K2, M(x, 37));
  94.             R(c, ref d, ref b, F2(d, e, a), K2, M(x, 38));
  95.             R(b, ref c, ref a, F2(c, d, e), K2, M(x, 39));
  96.             R(a, ref b, ref e, F3(b, c, d), K3, M(x, 40));
  97.             R(e, ref a, ref d, F3(a, b, c), K3, M(x, 41));
  98.             R(d, ref e, ref c, F3(e, a, b), K3, M(x, 42));
  99.             R(c, ref d, ref b, F3(d, e, a), K3, M(x, 43));
  100.             R(b, ref c, ref a, F3(c, d, e), K3, M(x, 44));
  101.             R(a, ref b, ref e, F3(b, c, d), K3, M(x, 45));
  102.             R(e, ref a, ref d, F3(a, b, c), K3, M(x, 46));
  103.             R(d, ref e, ref c, F3(e, a, b), K3, M(x, 47));
  104.             R(c, ref d, ref b, F3(d, e, a), K3, M(x, 48));
  105.             R(b, ref c, ref a, F3(c, d, e), K3, M(x, 49));
  106.             R(a, ref b, ref e, F3(b, c, d), K3, M(x, 50));
  107.             R(e, ref a, ref d, F3(a, b, c), K3, M(x, 51));
  108.             R(d, ref e, ref c, F3(e, a, b), K3, M(x, 52));
  109.             R(c, ref d, ref b, F3(d, e, a), K3, M(x, 53));
  110.             R(b, ref c, ref a, F3(c, d, e), K3, M(x, 54));
  111.             R(a, ref b, ref e, F3(b, c, d), K3, M(x, 55));
  112.             R(e, ref a, ref d, F3(a, b, c), K3, M(x, 56));
  113.             R(d, ref e, ref c, F3(e, a, b), K3, M(x, 57));
  114.             R(c, ref d, ref b, F3(d, e, a), K3, M(x, 58));
  115.             R(b, ref c, ref a, F3(c, d, e), K3, M(x, 59));
  116.             R(a, ref b, ref e, F4(b, c, d), K4, M(x, 60));
  117.             R(e, ref a, ref d, F4(a, b, c), K4, M(x, 61));
  118.             R(d, ref e, ref c, F4(e, a, b), K4, M(x, 62));
  119.             R(c, ref d, ref b, F4(d, e, a), K4, M(x, 63));
  120.             R(b, ref c, ref a, F4(c, d, e), K4, M(x, 64));
  121.             R(a, ref b, ref e, F4(b, c, d), K4, M(x, 65));
  122.             R(e, ref a, ref d, F4(a, b, c), K4, M(x, 66));
  123.             R(d, ref e, ref c, F4(e, a, b), K4, M(x, 67));
  124.             R(c, ref d, ref b, F4(d, e, a), K4, M(x, 68));
  125.             R(b, ref c, ref a, F4(c, d, e), K4, M(x, 69));
  126.             R(a, ref b, ref e, F4(b, c, d), K4, M(x, 70));
  127.             R(e, ref a, ref d, F4(a, b, c), K4, M(x, 71));
  128.             R(d, ref e, ref c, F4(e, a, b), K4, M(x, 72));
  129.             R(c, ref d, ref b, F4(d, e, a), K4, M(x, 73));
  130.             R(b, ref c, ref a, F4(c, d, e), K4, M(x, 74));
  131.             R(a, ref b, ref e, F4(b, c, d), K4, M(x, 75));
  132.             R(e, ref a, ref d, F4(a, b, c), K4, M(x, 76));
  133.             R(d, ref e, ref c, F4(e, a, b), K4, M(x, 77));
  134.             R(c, ref d, ref b, F4(d, e, a), K4, M(x, 78));
  135.             R(b, ref c, ref a, F4(c, d, e), K4, M(x, 79));
  136.             h0 += a;
  137.             h1 += b;
  138.             h2 += c;
  139.             h3 += d;
  140.             h4 += e;
  141.         }       
  142.         /// <summary>
  143.         /// 得到stream的SHA1
  144.         /// </summary>
  145.         /// <param name="stream">要处理的流</param>
  146.         /// <param name="index">开始处理的位置</param>
  147.         /// <param name="count">要处理的长度</param>
  148.         /// <returns></returns>
  149.         public static string Compute(Stream stream, long index, long count)
  150.         {
  151.             if(stream == null)
  152.                 throw new ArgumentNullException();
  153.             byte[] block = new byte[64];
  154.             UInt64 size = 0;
  155.             int b;
  156.             sha1_init();
  157.             while(index-- > 0 && stream.ReadByte() >= 0)
  158.                 ;
  159.             if(index >= 0)
  160.                 throw new ArgumentException("""index");
  161.             while((b = stream.ReadByte()) != -1 && count-- > 0)
  162.             {
  163.                 block[size++ % 64] = (byte)b;
  164.                 if(size % 64 == 0)
  165.                     sha1_transform(block);
  166.             }
  167.             if(count > 0)
  168.                 throw new ArgumentException("""count");
  169.             UInt64 bp = size % 64;//blockPoint
  170.             block[bp++] = 0x80;
  171.             if(bp > 56)
  172.             {
  173.                 while(bp < 64)
  174.                     block[bp++] = 0;
  175.                 sha1_transform(block);
  176.                 for(int i = 0;i < 56;i++)
  177.                     block[i] = 0;
  178.             }
  179.             else
  180.                 while(bp < 56)
  181.                     block[bp++] = 0;
  182.             size *= 8;
  183.             block[56] = (byte)(size >> 56);
  184.             block[57] = (byte)((size >> 48) & 0xFF);
  185.             block[58] = (byte)((size >> 40) & 0xFF);
  186.             block[59] = (byte)((size >> 32) & 0xFF);
  187.             block[60] = (byte)((size >> 24) & 0xFF);
  188.             block[61] = (byte)((size >> 16) & 0xFF);
  189.             block[62] = (byte)((size >> 8) & 0xFF);
  190.             block[63] = (byte)(size & 0xFF);
  191.             sha1_transform(block);
  192.             //注意,这里的结果要进行翻转
  193.             return Rev(string.Format("{0}-{1}-{2}-{3}-{4}",
  194.                 BitConverter.ToString(BitConverter.GetBytes(h4)),
  195.                 BitConverter.ToString(BitConverter.GetBytes(h3)),
  196.                 BitConverter.ToString(BitConverter.GetBytes(h2)),
  197.                 BitConverter.ToString(BitConverter.GetBytes(h1)),
  198.                 BitConverter.ToString(BitConverter.GetBytes(h0))).Replace("-"""));
  199.         }
  200.         private static string Rev(string str)
  201.         {
  202.             string s = string.Empty;
  203.             for(int i = 0;i < 40;i += 2)
  204.                 s = str.Substring(i, 2) + s;
  205.             return s;
  206.         }
  207.     }
  208. }

检测算法正确性的代码
用这段代码检测,只要出现了 OK!........说明我的算法是正确的。
  1. using System;
  2. using System.IO;
  3. using System.Security.Cryptography;
  4. using MY_SHA1;
  5. namespace _SHA1
  6. {
  7.     class Program
  8.     {
  9.         static void Main(string[] args)
  10.         {
  11.             Random rnd = new Random();
  12.             SHA1 sha = SHA1.Create();
  13.             bool f = true;
  14.             for(int i = 0;i < 10000;i++)
  15.             {
  16.                 byte[] buf = new byte[i];
  17.                 for(int j = 0;j < i;j++)
  18.                     buf[j] = (byte)rnd.Next(200);
  19.                 MemoryStream ms = new MemoryStream(buf);
  20.                 string s1 = My_SHA1.Compute(ms, 0, i);
  21.                 ms.Seek(0, SeekOrigin.Begin);
  22.                 string s2 = BitConverter.ToString(sha.ComputeHash(ms)).Replace("-""");
  23.                 if(s1 != s2)
  24.                 {
  25.                     Console.WriteLine("{0}/n {1}/n {2}", i, s1, s2);
  26.                     f = false;
  27.                 }
  28.             }
  29.             if(f)
  30.                 Console.WriteLine("OK!........");
  31.         }
  32.     }
  33. }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值