网站建议:179001057@qq.com

The MD4 Class.(C#)

技术2022-05-11  0

<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script> <script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script> /* Copyright 2002 Blood (eaststarbuy@sina.com) This code is ported from Norbert Hranitzky's (norbert.hranitzky@mchp.siemens.de) Java version. */ //reference Namespace using System; using System.Text; namespace Blood.COM.Security {     /// <summary>     /// Implements The MD4 message digest algorithm in C#     /// </summary>     public Class MD4     {                  // MD4 specific object variables         //-----------------------------------------------------------------------              /// <summary>         /// The size in bytes of The input block to The transformation algorithm         /// </summary>         private const int BLOCK_LENGTH = 64;        // = 512 / 8         /// <summary>         /// 4 32-bit words (interim result)         /// </summary>         private uint[] context = new uint[4];         /// <summary>         /// Number of bytes procesed so far mod. 2 power of 64.         /// </summary>         private long count;         /// <summary>         /// 512-bit input buffer = 16 x 32-bit words holds until it reaches 512 bits         /// </summary>         private byte[] buffer = new byte[BLOCK_LENGTH];         /// <summary>         /// 512-bit work buffer = 16 x 32-bit words         /// </summary>         private uint[] X = new uint[16];              // Constructors         //------------------------------------------------------------------------         public MD4()         {            engineReset();         }         /// <summary>         /// This constructor is here to implement The clonability of this Class         /// </summary>         /// <param name=" MD"> </param>         private MD4( MD4 MD): this()         {             //this();             context = (uint[]) MD.context.Clone();             buffer = (byte[]) MD.buffer.Clone();             count = MD.count;         }         // Clonable method implementation         //-------------------------------------------------------------------------         public object Clone()         {             return new MD4(this);         }         // JCE methods         //-------------------------------------------------------------------------         /// <summary>         /// Resets this object disregarding any temporary data present at The         /// time of The invocation of this call.         /// </summary>         private void engineReset()         {             // initial values of MD4 i.e. A, B, C, D             // as per rfc-1320; They are low-order byte first             context[0] = 0x67452301;             context[1] = 0xEFCDAB89;             context[2] = 0x98BADCFE;             context[3] = 0x10325476;             count = 0L;             for(int i = 0; i < BLOCK_LENGTH; i++)             {                 buffer[i] = 0;             }         }                  /// <summary>         /// Continues an MD4 message digest using The input byte         /// </summary>         /// <param name="b">byte to input</param>         private void engineUpdate(byte b)         {             // compute number of bytes still unhashed; ie. present in buffer             int i = (int)(count % BLOCK_LENGTH);             count++;            // update number of bytes             buffer[i] = b;             if(i == BLOCK_LENGTH - 1)                 transform(ref buffer, 0);         }         /// <summary>         /// MD4 block update operation         /// </summary>         /// <remarks>         /// Continues an MD4 message digest operation by filling The buffer,         /// transform(ing) data in 512-bit message block(s), updating The variables         /// context and count, and leaving (buffering) The remaining bytes in buffer         /// for The next update or finish.         /// </remarks>         /// <param name="input">input block</param>         /// <param name="offset">start of meaningful bytes in input</param>         /// <param name="len">count of bytes in input blcok to consider</param>         private void engineUpdate(byte[] input, int offset, int len)         {             // make sure we don't exceed input's allocated size/length             if(offset < 0 || len < 0 || (long)offset + len > input.Length)             {                 throw new ArgumentOutOfRangeException();             }             // compute number of bytes still unhashed; ie. present in buffer             int bufferNdx = (int)(count % BLOCK_LENGTH);             count += len;        // update number of bytes             int partLen = BLOCK_LENGTH - bufferNdx;             int i = 0;             if(len >= partLen)             {                 Array.Copy(input, offset + i, buffer, bufferNdx, partLen);                 transform(ref buffer, 0);                 for(i = partLen; i + BLOCK_LENGTH - 1 < len; i+= BLOCK_LENGTH)                 {                     transform(ref input, offset + i);                 }                 bufferNdx = 0;             }             // buffer remaining input             if(i < len)             {                 Array.Copy(input, offset + i, buffer, bufferNdx, len - i);             }         }                  /// <summary>         /// Completes The hash computation by performing final operations such         /// as padding.  At The return of this engineDigest, The MD engine is         /// reset.         /// </summary>         /// <returns> The array of bytes for The resulting hash value.</returns>         private byte[] engineDigest()         {             // pad output to 56 mod 64; as RFC1320 puts it: congruent to 448 mod 512             int bufferNdx = (int)(count % BLOCK_LENGTH);             int padLen = (bufferNdx < 56) ? (56 - bufferNdx) : (120 - bufferNdx);             // padding is always binary 1 followed by binary 0's             byte[] tail = new byte[padLen + 8];             tail[0] = (byte)0x80;             // append length before final transform             // save number of bits, casting The long to an array of 8 bytes             // save low-order byte first.             for(int i = 0; i < 8 ; i++)             {                 tail[padLen + i] = (byte)((count * 8) >> (8 * i));             }             engineUpdate(tail, 0, tail.Length);             byte[] result = new byte[16];             // cast this MD4's context (array of 4 uints) into an array of 16 bytes.             for(int i = 0;i < 4; i++)             {                 for(int j = 0; j < 4; j++)                 {                     result[i * 4 + j] = (byte)(context[i] >> (8 * j));                 }             }             // reset The engine             engineReset();             return result;         }         /// <summary>         /// Returns a byte hash from a string         /// </summary>         /// <param name="s">string to hash</param>         /// <returns>byte-array that contains The hash</returns>         public byte[] GetByteHashFromString(string s)         {             byte[] b = Encoding.UTF8.GetBytes(s);              MD4 MD4 = new MD4();              MD4.engineUpdate(b, 0, b.Length);             return MD4.engineDigest();         }         /// <summary>         /// Returns a binary hash from an input byte array         /// </summary>         /// <param name="b">byte-array to hash</param>         /// <returns>binary hash of input</returns>         public byte[] GetByteHashFromBytes(byte[] b)         {              MD4 MD4 = new MD4();                   MD4.engineUpdate(b, 0, b.Length);             return MD4.engineDigest();         }         /// <summary>         /// Returns a string that contains The hexadecimal hash         /// </summary>         /// <param name="b">byte-array to input</param>         /// <returns>String that contains The hex of The hash</returns>         public string Ge ThexHashFromBytes(byte[] b)         {             byte[] e = GetByteHashFromBytes(b);             return bytesToHex(e, e.Length);         }         /// <summary>         /// Returns a byte hash from The input byte         /// </summary>         /// <param name="b">byte to hash</param>         /// <returns>binary hash of The input byte</returns>         public byte[] GetByteHashFromByte(byte b)         {              MD4 MD4 = new MD4();              MD4.engineUpdate(b);             return MD4.engineDigest();         }         /// <summary>         /// Returns a string that contains The hexadecimal hash         /// </summary>         /// <param name="b">byte to hash</param>         /// <returns>String that contains The hex of The hash</returns>         public string Ge ThexHashFromByte(byte b)         {             byte[] e = GetByteHashFromByte(b);             return bytesToHex(e, e.Length);         }         /// <summary>         /// Returns a string that contains The hexadecimal hash         /// </summary>         /// <param name="s">string to hash</param>         /// <returns>String that contains The hex of The hash</returns>         public string Ge ThexHashFromString(string s)         {             byte[] b = GetByteHashFromString(s);             return bytesToHex(b, b.Length);         }         private static string bytesToHex(byte[] a, int len)         {             string temp = BitConverter.ToString(a);                  // We need to remove The dashes that come from The BitConverter             StringBuilder sb = new StringBuilder((len - 2) / 2);    // This should be The final size             for(int i = 0; i < temp.Length ; i++)             {                 if(temp[i] != '-')                 {                     sb.Append(temp[i]);                 }             }             return sb.ToString();         }         // own methods         //-----------------------------------------------------------------------------------         /// <summary>         /// MD4 basic transformation         /// </summary>         /// <remarks>         /// Transforms context based on 512 bits from input block starting         /// from The offset'th byte.         /// </remarks>         /// <param name="block">input sub-array</param>         /// <param name="offset">starting position of sub-array</param>         private void transform(ref byte[] block, int offset)         {             // decodes 64 bytes from input block into an array of 16 32-bit             // entities. Use A as a temp var.             for (int i = 0; i < 16; i++)             {                 X[i] = ((uint)block[offset++] & 0xFF)     |                     (((uint)block[offset++] & 0xFF) <<  8)   |                     (((uint)block[offset++] & 0xFF) <<  16)  |                     (((uint)block[offset++] & 0xFF) <<  24);             }             uint A = context[0];             uint B = context[1];             uint C = context[2];             uint D = context[3];             A = FF(A, B, C, D, X[ 0],  3);             D = FF(D, A, B, C, X[ 1],  7);             C = FF(C, D, A, B, X[ 2], 11);             B = FF(B, C, D, A, X[ 3], 19);             A = FF(A, B, C, D, X[ 4],  3);             D = FF(D, A, B, C, X[ 5],  7);             C = FF(C, D, A, B, X[ 6], 11);             B = FF(B, C, D, A, X[ 7], 19);             A = FF(A, B, C, D, X[ 8],  3);             D = FF(D, A, B, C, X[ 9],  7);             C = FF(C, D, A, B, X[10], 11);             B = FF(B, C, D, A, X[11], 19);             A = FF(A, B, C, D, X[12],  3);             D = FF(D, A, B, C, X[13],  7);             C = FF(C, D, A, B, X[14], 11);             B = FF(B, C, D, A, X[15], 19);             A = GG(A, B, C, D, X[ 0],  3);             D = GG(D, A, B, C, X[ 4],  5);             C = GG(C, D, A, B, X[ 8],  9);             B = GG(B, C, D, A, X[12], 13);             A = GG(A, B, C, D, X[ 1],  3);             D = GG(D, A, B, C, X[ 5],  5);             C = GG(C, D, A, B, X[ 9],  9);             B = GG(B, C, D, A, X[13], 13);             A = GG(A, B, C, D, X[ 2],  3);             D = GG(D, A, B, C, X[ 6],  5);             C = GG(C, D, A, B, X[10],  9);             B = GG(B, C, D, A, X[14], 13);             A = GG(A, B, C, D, X[ 3],  3);             D = GG(D, A, B, C, X[ 7],  5);             C = GG(C, D, A, B, X[11],  9);             B = GG(B, C, D, A, X[15], 13);             A = HH(A, B, C, D, X[ 0],  3);             D = HH(D, A, B, C, X[ 8],  9);             C = HH(C, D, A, B, X[ 4], 11);             B = HH(B, C, D, A, X[12], 15);             A = HH(A, B, C, D, X[ 2],  3);             D = HH(D, A, B, C, X[10],  9);             C = HH(C, D, A, B, X[ 6], 11);             B = HH(B, C, D, A, X[14], 15);             A = HH(A, B, C, D, X[ 1],  3);             D = HH(D, A, B, C, X[ 9],  9);             C = HH(C, D, A, B, X[ 5], 11);             B = HH(B, C, D, A, X[13], 15);             A = HH(A, B, C, D, X[ 3],  3);             D = HH(D, A, B, C, X[11],  9);             C = HH(C, D, A, B, X[ 7], 11);             B = HH(B, C, D, A, X[15], 15);             context[0] += A;             context[1] += B;             context[2] += C;             context[3] += D;         }         // The basic MD4 atomic functions.         private uint FF(uint a, uint b, uint c, uint d, uint x, int s)         {             uint t = a + ((b & c) | (~b & d)) + x;             return t << s | t >> (32 - s);         }         private uint GG(uint a, uint b, uint c, uint d, uint x, int s)         {             uint t = a + ((b & (c | d)) | (c & d)) + x + 0x5A827999;             return t << s | t >> (32 - s);         }         private uint HH(uint a, uint b, uint c, uint d, uint x, int s)         {             uint t = a + (b ^ c ^ d) + x + 0x6ED9EBA1;             return t << s | t >> (32 - s);         }     } // Class MD4 } // namespace Blood.COM.Security <script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script> <script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

最新回复(0)