MD5算法C#实现

  1 using System;
  2 using System.IO;
  3 // MD5 Alogrithm
  4 // by liwei 2013.3.12 http://www.cnblogs.com/Okalun/
  5 // 伪代码
  6 
  7 ////Note: All variables are unsigned 32 bits and wrap modulo 2^32 when calculating
  8 //var int[64] r, k
  9 
 10 ////r specifies the per-round shift amounts
 11 //r[ 0..15]:= {7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22} 
 12 //r[16..31]:= {5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20}
 13 //r[32..47]:= {4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23}
 14 //r[48..63]:= {6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21}
 15 
 16 ////Use binary integer part of the sines of integers as constants:
 17 //for i from 0 to 63
 18 //    k[i] := floor(abs(sin(i + 1)) × 2^32)
 19 
 20 ////Initialize variables:
 21 //var int h0 := 0x67452301
 22 //var int h1 := 0xEFCDAB89
 23 //var int h2 := 0x98BADCFE
 24 //var int h3 := 0x10325476
 25 
 26 ////Pre-processing:
 27 //append "1" bit to message
 28 //append "0" bits until message length in bits ≡ 448 (mod 512)
 29 //append bit length of message as 64-bit little-endian integer to message
 30 
 31 ////Process the message in successive 512-bit chunks:
 32 //for each 512-bit chunk of message
 33 //    break chunk into sixteen 32-bit little-endian words w[i], 0 ≤ i ≤ 15
 34 
 35 //    //Initialize hash value for this chunk:
 36 //    var int a := h0
 37 //    var int b := h1
 38 //    var int c := h2
 39 //    var int d := h3
 40 
 41 //    //Main loop:
 42 //    for i from 0 to 63
 43 //        if 0 ≤ i ≤ 15 then
 44 //            f := (b and c) or ((not b) and d)
 45 //            g := i
 46 //        else if 16 ≤ i ≤ 31
 47 //            f := (d and b) or ((not d) and c)
 48 //            g := (5×i + 1) mod 16
 49 //        else if 32 ≤ i ≤ 47
 50 //            f := b xor c xor d
 51 //            g := (3×i + 5) mod 16
 52 //        else if 48 ≤ i ≤ 63
 53 //            f := c xor (b or (not d))
 54 //            g := (7×i) mod 16
 55 
 56 //        temp := d
 57 //        d := c
 58 //        c := b
 59 //        b := leftrotate((a + f + k[i] + w[g]),r[i]) + b
 60 //        a := temp
 61 //    Next i
 62 //    //Add this chunk's hash to result so far:
 63 //    h0 := h0 + a
 64 //    h1 := h1 + b 
 65 //    h2 := h2 + c
 66 //    h3 := h3 + d
 67 //End ForEach
 68 //var int digest := h0 append h1 append h2 append h3 //(expressed as little-endian)
 69 namespace HashEncrypted
 70 {
 71     class MD5
 72     {
 73         private static int[] leftrotates = { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
 74                             5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,
 75                             4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,
 76                             6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21
 77                           };
 78         private static uint[] table = new uint[64];
 79         private static uint[] tempresults = new uint[4];
 80         private static byte[] MD5ByteArray = new byte[16];
 81         private static byte[] PaddingData = {128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 82                              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 83                              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 84                              0, 0, 0, 0 };
 85 
 86         private string hexOutput = "";
 87         public string MD5HexOutput
 88         {
 89             get
 90             {
 91                 for (int i = 0; i < 16; i++)
 92                 {
 93                     hexOutput += String.Format("{0:x2}", MD5ByteArray[i]);
 94                 }
 95                 return hexOutput;
 96             }
 97         }
 98 
 99         static MD5()
100         {
101             for (int i = 0; i < table.Length; i++)
102             {
103                 table[i] = (uint)Math.Floor(Math.Abs(Math.Sin(i + 1)) * (2L << 31));
104             };
105         }
106 
107         private static void MD5Init()
108         {
109             tempresults[0] = 0x67452301;  //in memory, this is 0x01234567
110             tempresults[1] = 0xefcdab89;  //in memory, this is 0x89abcdef
111             tempresults[2] = 0x98badcfe;  //in memory, this is 0xfedcba98
112             tempresults[3] = 0x10325476;  //in memory, this is 0x76543210 
113         }
114 
115         private static byte[] UlongToBytes(ulong inputUlong)
116         {
117             byte[] outputBytes = new byte[8];
118             for (int i = 0; i < 8; i++)
119             {
120                 outputBytes[7 - i] = (byte)((inputUlong >> 8 * (7 - i)) & 0xFF);
121             }
122             return outputBytes;
123         }
124 
125         private static uint LeftRotate(uint num, int bit)
126         {
127             return (num << bit) | (num >> (32 - bit));
128         }
129 
130         private static uint[] MD5Append(byte[] Source, long SourceLength)
131         {
132             int paddedLength;
133             int needPaddingSize;
134             int paddingSourceLength = Source.Length;
135             byte[] paddedSource;
136             byte[] lengthBytes = UlongToBytes((ulong)SourceLength * 8);
137 
138             paddedLength = (64 * (paddingSourceLength / 64 + 1));
139             paddedSource = new byte[paddedLength];
140             needPaddingSize = (paddedLength - paddingSourceLength - 8);
141 
142             for (int i = 0; i < paddedLength; i++)
143             {
144                 if (i < paddingSourceLength)
145                 {
146                     paddedSource[i] = Source[i];
147                 }
148                 else if (i < needPaddingSize + paddingSourceLength)
149                 {
150                     paddedSource[i] = PaddingData[i - paddingSourceLength];
151                 }
152                 else
153                 {
154                     paddedSource[i] = lengthBytes[i - paddingSourceLength - needPaddingSize];
155                 }
156             }
157 
158             uint[] target = new uint[paddedLength / 4];
159             for (int i = 0, j = 0; i < paddedLength; j++, i += 4)
160             {
161                 target[j] = (uint)(paddedSource[i] | paddedSource[i + 1] << 8 | paddedSource[i + 2] << 16 | paddedSource[i + 3] << 24);
162             }
163             return target;
164         }
165 
166         private static void MD5Trasform(uint[] input)
167         {
168             uint a = tempresults[0];
169             uint b = tempresults[1];
170             uint c = tempresults[2];
171             uint d = tempresults[3];
172             uint calValue;
173             uint index;
174 
175             for (uint i = 0; i < 64; i++)
176             {
177                 if (i <= 15)
178                 {
179                     calValue = (b & c) | ((~b) & d);
180                     index = i;
181                 }
182                 else if (i <= 31)
183                 {
184                     calValue = (d & b) | ((~d) & c);
185                     index = (5 * i + 1) % 16;
186                 }
187                 else if (i <= 47)
188                 {
189                     calValue = b ^ c ^ d;
190                     index = (3 * i + 5) % 16;
191                 }
192                 else
193                 {
194                     calValue = c ^ (b | (~d));
195                     index = (7 * i) % 16;
196                 }
197 
198                 uint temp = a + calValue + table[i] + input[index];
199                 temp = LeftRotate(temp, leftrotates[i]);
200                 a = b + temp;
201 
202                 temp = d;
203                 d = c;
204                 c = b;
205                 b = a;
206                 a = temp;
207             }
208 
209             tempresults[0] += a;
210             tempresults[1] += b;
211             tempresults[2] += c;
212             tempresults[3] += d;
213         }
214 
215         private static void GetMD5ByteArray(uint[] MD5UnintArray)
216         {
217             MD5ByteArray = new byte[16];
218             for (int i = 0, j = 0; i < 4; i++, j += 4)
219             {
220                 MD5ByteArray[j] = (byte)(MD5UnintArray[i] & 0xff);
221                 MD5ByteArray[j + 1] = (byte)((MD5UnintArray[i] >> 8) & 0xff);
222                 MD5ByteArray[j + 2] = (byte)((MD5UnintArray[i] >> 16) & 0xff);
223                 MD5ByteArray[j + 3] = (byte)((MD5UnintArray[i] >> 24) & 0xff);
224             }
225         }
226 
227         private static void MD5BytesDigest(byte[] Date)
228         {
229             uint[] PaddedData;
230             uint[] block = new uint[16];
231             MD5Init();
232             PaddedData = MD5Append(Date, (long)Date.Length);
233 
234             for (int i = 0; i < PaddedData.Length / 16; i++)
235             {
236                 for (int j = 0; j < 16; j++)
237                 {
238                     block[j] = PaddedData[i * 16 + j];
239                 }
240                 MD5Trasform(block);
241             }
242             GetMD5ByteArray(tempresults);
243         }
244 
245         public MD5(byte[] Date)
246         {
247             MD5BytesDigest(Date);
248         }
249 
250         public MD5(string StringDate)
251         {
252             MD5BytesDigest(System.Text.Encoding.Default.GetBytes(StringDate));
253         }
254 
255         public MD5(FileInfo fileInfo)
256         {
257             byte[] buffer = new byte[64];
258             byte[] lastDateBuffer;
259             uint[] paddedLastData;
260             uint[] block = new uint[16];
261             MD5Init();
262 
263             try
264             {
265                 using (FileStream fs = fileInfo.OpenRead())
266                 {
267                     int numBytesToRead = 0;
268                  269 
270                     while (true)
271                     {
272                         int readLength;
273                         readLength = fs.Read(buffer, 0, buffer.Length);
274                         if (readLength == 64)
275                         {
276                             for (int i = 0, j = 0; j < 16; j++, i += 4)
277                             {
278                                 block[j] = (uint)(buffer[i] | buffer[i + 1] << 8 | buffer[i + 2] << 16 | buffer[i + 3] << 24);
279                             }
280                             MD5Trasform(block);
281                         }
282                         else
283                         {
284                             lastDateBuffer = new byte[fs.Length - numBytesToRead];
285                             for (int i = 0; i < readLength; i++)
286                             {
287                                 lastDateBuffer[i] = buffer[i];
288                             }
289                             paddedLastData = MD5Append(lastDateBuffer, fs.Length);
290 
291                             for (int j = 0; j < 16; j++)
292                             {
293                                 block[j] = paddedLastData[j];
294                             }
295                             MD5Trasform(block);
296                             break;
297                         }
298                         numBytesToRead += readLength;
299                     }
300                 }
301             }
302             catch (FileNotFoundException ioEx)
303             {
304                 Console.WriteLine(ioEx.Message);
305             }
306             GetMD5ByteArray(tempresults);
307         }
308     }
309 
310     class Program
311     {
312         private static void StringTest(string input)
313         {
314             MD5 m = new MD5(input);
315             Console.WriteLine("MD5(\"" + input + "\")=" + m.MD5HexOutput);
316         }
317 
318         private static void FileTest(string filename)
319         {
320             FileInfo fi = new FileInfo(filename);
321             MD5 f = new MD5(fi);
322             Console.WriteLine("file :" + filename + " MD5 is " + f.MD5HexOutput);
323         }
324 
325         private static void Test()
326         {
327             StringTest("");
328             StringTest("a");
329             StringTest("abc");
330             StringTest("message digest");
331             FileTest(@"C#本质论源代码.zip");
332             Console.ReadKey();
333         }
334 
335         static void Main(string[] args)
336         {
337             Test();
338         }
339     }
340 }

 

转载于:https://www.cnblogs.com/Okalun/archive/2013/03/12/2955518.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值