You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

259 lines
8.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace POSV.Common.Util
{
/// <summary>
/// MD5算法的3rdParty实现
/// 参考https://github.com/Dozer74/MD5
/// </summary>
public class LabMD5
{
#region Helper
private sealed class Digest
{
public uint A;
public uint B;
public uint C;
public uint D;
public Digest()
{
A = 0x67452301;
B = 0xEFCDAB89;
C = 0x98BADCFE;
D = 0X10325476;
}
public override string ToString()
{
string st;
st = BitHelper.ReverseByte(A).ToString("x8") +
BitHelper.ReverseByte(B).ToString("x8") +
BitHelper.ReverseByte(C).ToString("x8") +
BitHelper.ReverseByte(D).ToString("x8");
return st;
}
}
private static class BitHelper
{
/// <summary>
/// rotate
/// </summary>
/// <param name="num">num</param>
/// <param name="shift">shift</param>
/// <returns></returns>
public static uint RotateLeft(uint num , ushort shift)
{
return (num >> (32 - shift)) | (num << shift);
}
/// <summary>
/// reverse
/// </summary>
public static uint ReverseByte(uint num)
{
return ((num & 0x000000ff) << 24) |
(num >> 24) |
((num & 0x00ff0000) >> 8) |
((num & 0x0000ff00) << 8);
}
}
#endregion Helper
#region Table
/// <summary>
/// table 4294967296*sin(i)
/// </summary>
private static readonly uint[] T =
{
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
};
#endregion Table
private uint[] X = new uint[16];
/// <summary>
/// ComputeHash
/// </summary>
public string ComputeHash(byte[] bytes)
{
var dg = new Digest();
var bMsg = CreatePaddedBuffer(bytes);
var mesLength = (uint)(bMsg.Length * 8) / 32;
for (uint i = 0; i < mesLength / 16; i++)
{
CopyBlock(bMsg , i);
Transform(ref dg.A , ref dg.B , ref dg.C , ref dg.D);
}
return dg.ToString();
}
private void Transform(ref uint A , ref uint B , ref uint C , ref uint D)
{
var AA = A;
var BB = B;
var CC = C;
var DD = D;
/* Round 1 */
F(ref A , B , C , D , 0 , 7 , 1);
F(ref D , A , B , C , 1 , 12 , 2);
F(ref C , D , A , B , 2 , 17 , 3);
F(ref B , C , D , A , 3 , 22 , 4);
F(ref A , B , C , D , 4 , 7 , 5);
F(ref D , A , B , C , 5 , 12 , 6);
F(ref C , D , A , B , 6 , 17 , 7);
F(ref B , C , D , A , 7 , 22 , 8);
F(ref A , B , C , D , 8 , 7 , 9);
F(ref D , A , B , C , 9 , 12 , 10);
F(ref C , D , A , B , 10 , 17 , 11);
F(ref B , C , D , A , 11 , 22 , 12);
F(ref A , B , C , D , 12 , 7 , 13);
F(ref D , A , B , C , 13 , 12 , 14);
F(ref C , D , A , B , 14 , 17 , 15);
F(ref B , C , D , A , 15 , 22 , 16);
/* Round 2 */
G(ref A , B , C , D , 1 , 5 , 17);
G(ref D , A , B , C , 6 , 9 , 18);
G(ref C , D , A , B , 11 , 14 , 19);
G(ref B , C , D , A , 0 , 20 , 20);
G(ref A , B , C , D , 5 , 5 , 21);
G(ref D , A , B , C , 10 , 9 , 22);
G(ref C , D , A , B , 15 , 14 , 23);
G(ref B , C , D , A , 4 , 20 , 24);
G(ref A , B , C , D , 9 , 5 , 25);
G(ref D , A , B , C , 14 , 9 , 26);
G(ref C , D , A , B , 3 , 14 , 27);
G(ref B , C , D , A , 8 , 20 , 28);
G(ref A , B , C , D , 13 , 5 , 29);
G(ref D , A , B , C , 2 , 9 , 30);
G(ref C , D , A , B , 7 , 14 , 31);
G(ref B , C , D , A , 12 , 20 , 32);
/* Round 3 */
H(ref A , B , C , D , 5 , 4 , 33);
H(ref D , A , B , C , 8 , 11 , 34);
H(ref C , D , A , B , 11 , 16 , 35);
H(ref B , C , D , A , 14 , 23 , 36);
H(ref A , B , C , D , 1 , 4 , 37);
H(ref D , A , B , C , 4 , 11 , 38);
H(ref C , D , A , B , 7 , 16 , 39);
H(ref B , C , D , A , 10 , 23 , 40);
H(ref A , B , C , D , 13 , 4 , 41);
H(ref D , A , B , C , 0 , 11 , 42);
H(ref C , D , A , B , 3 , 16 , 43);
H(ref B , C , D , A , 6 , 23 , 44);
H(ref A , B , C , D , 9 , 4 , 45);
H(ref D , A , B , C , 12 , 11 , 46);
H(ref C , D , A , B , 15 , 16 , 47);
H(ref B , C , D , A , 2 , 23 , 48);
/* Round 4 */
I(ref A , B , C , D , 0 , 6 , 49);
I(ref D , A , B , C , 7 , 10 , 50);
I(ref C , D , A , B , 14 , 15 , 51);
I(ref B , C , D , A , 5 , 21 , 52);
I(ref A , B , C , D , 12 , 6 , 53);
I(ref D , A , B , C , 3 , 10 , 54);
I(ref C , D , A , B , 10 , 15 , 55);
I(ref B , C , D , A , 1 , 21 , 56);
I(ref A , B , C , D , 8 , 6 , 57);
I(ref D , A , B , C , 15 , 10 , 58);
I(ref C , D , A , B , 6 , 15 , 59);
I(ref B , C , D , A , 13 , 21 , 60);
I(ref A , B , C , D , 4 , 6 , 61);
I(ref D , A , B , C , 11 , 10 , 62);
I(ref C , D , A , B , 2 , 15 , 63);
I(ref B , C , D , A , 9 , 21 , 64);
A = A + AA;
B = B + BB;
C = C + CC;
D = D + DD;
}
private byte[] CreatePaddedBuffer(byte[] mes)
{
var padSize = 448 - mes.Length * 8 % 512;
var pad = (uint)((padSize + 512) % 512);
if (pad == 0) pad = 512;
var sizeMsgBuff = (uint)(mes.Length + pad / 8 + 8);
var sizeMsg = (ulong)mes.Length * 8;
var bMsg = new byte[sizeMsgBuff];
for (var i = 0; i < mes.Length; i++)
bMsg[i] = mes[i];
bMsg[mes.Length] |= 0x80;
for (var i = 8; i > 0; i--)
bMsg[sizeMsgBuff - i] = (byte)((sizeMsg >> ((8 - i) * 8)) & 0x00000000000000ff);
return bMsg;
}
private void CopyBlock(byte[] bMsg , uint block)
{
block = block << 6;
for (uint j = 0; j < 61; j += 4)
X[j >> 2] = ((uint)bMsg[block + j + 3] << 24) |
((uint)bMsg[block + j + 2] << 16) |
((uint)bMsg[block + j + 1] << 8) |
bMsg[block + j];
}
#region Transform
private void F(ref uint a , uint b , uint c , uint d , uint k , ushort s , uint i)
{
a = b + BitHelper.RotateLeft(a + ((b & c) | (~b & d)) + X[k] + T[i - 1] , s);
}
private void G(ref uint a , uint b , uint c , uint d , uint k , ushort s , uint i)
{
a = b + BitHelper.RotateLeft(a + ((b & d) | (c & ~d)) + X[k] + T[i - 1] , s);
}
private void H(ref uint a , uint b , uint c , uint d , uint k , ushort s , uint i)
{
a = b + BitHelper.RotateLeft(a + (b ^ c ^ d) + X[k] + T[i - 1] , s);
}
private void I(ref uint a , uint b , uint c , uint d , uint k , ushort s , uint i)
{
a = b + BitHelper.RotateLeft(a + (c ^ (b | ~d)) + X[k] + T[i - 1] , s);
}
#endregion Transform
}
}