2006-07-15 Jonathan Chambers <joncham@gmail.com>
[mono.git] / mcs / class / corlib / System.Security.Cryptography / MD5CryptoServiceProvider.cs
index 12db5d60aadead20770272d0aa3df656bfdcc986..a2403407d2ddc131d142227b65b57ed16fe2256d 100644 (file)
@@ -3,37 +3,56 @@
 //
 // Authors:
 //     Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
-//     Sebastien Pouliot (spouliot@motus.com)
+//     Sebastien Pouliot (sebastien@ximian.com)
 //
 // Copyright 2001 by Matthew S. Ford.
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
 //
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Runtime.InteropServices;
 
 namespace System.Security.Cryptography {
 
-       /// <summary>
-       /// C# implementation of the MD5 cryptographic hash function.
-       /// </summary>
 #if NET_1_0
        public class MD5CryptoServiceProvider : MD5 {
 #else
+       #if NET_2_0
+       [ComVisible (true)]
+       #endif
        public sealed class MD5CryptoServiceProvider : MD5 {
 #endif
                private const int BLOCK_SIZE_BYTES =  64;
                private const int HASH_SIZE_BYTES  =  16;
-               private const int HASH_SIZE_BITS   = 128;
-               [CLSCompliant(false)] private uint[] _H;
-               [CLSCompliant(false)] private uint count;
+               private uint[] _H;
+               private uint[] buff;
+               private ulong count;
                private byte[] _ProcessingBuffer;   // Used to start data when passed less than a block worth.
                private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
        
-               /// <summary>
-               /// Creates a new MD5CryptoServiceProvider.
-               /// </summary>
                public MD5CryptoServiceProvider () 
                {
                        _H = new uint[4];
-                       HashSizeValue = HASH_SIZE_BITS;
-                       _ProcessingBuffer = new byte[BLOCK_SIZE_BYTES];
+                       buff = new uint[16];
+                       _ProcessingBuffer = new byte [BLOCK_SIZE_BYTES];
 
                        Initialize();
                }
@@ -45,15 +64,20 @@ namespace System.Security.Cryptography {
 
                protected override void Dispose (bool disposing) 
                {
-                       // nothing to do (managed implementation)
+                       if (_ProcessingBuffer != null) {
+                               Array.Clear (_ProcessingBuffer, 0, _ProcessingBuffer.Length);
+                               _ProcessingBuffer = null;
+                       }
+                       if (_H != null) {
+                               Array.Clear (_H, 0, _H.Length);
+                               _H = null;
+                       }
+                       if (buff != null) {
+                               Array.Clear (buff, 0, buff.Length);
+                               buff = null;
+                       }
                }
 
-               /// <summary>
-               /// Drives the hashing function.
-               /// </summary>
-               /// <param name="rgb">Byte array containing the data to hash.</param>
-               /// <param name="start">Where in the input buffer to start.</param>
-               /// <param name="size">Size in bytes of the data in the buffer to hash.</param>
                protected override void HashCore (byte[] rgb, int start, int size) 
                {
                        int i;
@@ -85,15 +109,12 @@ namespace System.Security.Cryptography {
                        }
                }
        
-               /// <summary>
-               /// This finalizes the hash.  Takes the data from the chaining variables and returns it.
-               /// </summary>
                protected override byte[] HashFinal () 
                {
                        byte[] hash = new byte[16];
                        int i, j;
 
-                       ProcessFinalBlock(_ProcessingBuffer, 0, _ProcessingBufferCount);
+                       ProcessFinalBlock (_ProcessingBuffer, 0, _ProcessingBufferCount);
 
                        for (i=0; i<4; i++) {
                                for (j=0; j<4; j++) {
@@ -104,9 +125,6 @@ namespace System.Security.Cryptography {
                        return hash;
                }
 
-               /// <summary>
-               /// Resets the class after use.  Called automatically after hashing is done.
-               /// </summary>
                public override void Initialize () 
                {
                        count = 0;
@@ -118,14 +136,8 @@ namespace System.Security.Cryptography {
                        _H[3] = 0x10325476;
                }
 
-               /// <summary>
-               /// This is the meat of the hash function.  It is what processes each block one at a time.
-               /// </summary>
-               /// <param name="inputBuffer">Byte array to process data from.</param>
-               /// <param name="inputOffset">Where in the byte array to start processing.</param>
                private void ProcessBlock (byte[] inputBuffer, int inputOffset) 
                {
-                       uint[] buff = new uint[16];
                        uint a, b, c, d;
                        int i;
                
@@ -146,355 +158,338 @@ namespace System.Security.Cryptography {
                        // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
                        // Possibly roll up if this changes.
 
-
                        // ---- Round 1 --------
 
-                       a += (((c ^ d) & b) ^ d) + (uint) Constants.C0 + buff [0];
+                       a += (((c ^ d) & b) ^ d) + (uint) K [0] + buff [0];
                        a = (a << 7) | (a >> 25);
                        a += b;
 
-                       d += (((b ^ c) & a) ^ c) + (uint) Constants.C1 + buff [1];
+                       d += (((b ^ c) & a) ^ c) + (uint) K [1] + buff [1];
                        d = (d << 12) | (d >> 20);
                        d += a;
 
-                       c += (((a ^ b) & d) ^ b) + (uint) Constants.C2 + buff [2];
+                       c += (((a ^ b) & d) ^ b) + (uint) K [2] + buff [2];
                        c = (c << 17) | (c >> 15);
                        c += d;
 
-                       b += (((d ^ a) & c) ^ a) + (uint) Constants.C3 + buff [3];
+                       b += (((d ^ a) & c) ^ a) + (uint) K [3] + buff [3];
                        b = (b << 22) | (b >> 10);
                        b += c;
 
-                       a += (((c ^ d) & b) ^ d) + (uint) Constants.C4 + buff [4];
+                       a += (((c ^ d) & b) ^ d) + (uint) K [4] + buff [4];
                        a = (a << 7) | (a >> 25);
                        a += b;
 
-                       d += (((b ^ c) & a) ^ c) + (uint) Constants.C5 + buff [5];
+                       d += (((b ^ c) & a) ^ c) + (uint) K [5] + buff [5];
                        d = (d << 12) | (d >> 20);
                        d += a;
 
-                       c += (((a ^ b) & d) ^ b) + (uint) Constants.C6 + buff [6];
+                       c += (((a ^ b) & d) ^ b) + (uint) K [6] + buff [6];
                        c = (c << 17) | (c >> 15);
                        c += d;
 
-                       b += (((d ^ a) & c) ^ a) + (uint) Constants.C7 + buff [7];
+                       b += (((d ^ a) & c) ^ a) + (uint) K [7] + buff [7];
                        b = (b << 22) | (b >> 10);
                        b += c;
 
-                       a += (((c ^ d) & b) ^ d) + (uint) Constants.C8 + buff [8];
+                       a += (((c ^ d) & b) ^ d) + (uint) K [8] + buff [8];
                        a = (a << 7) | (a >> 25);
                        a += b;
 
-                       d += (((b ^ c) & a) ^ c) + (uint) Constants.C9 + buff [9];
+                       d += (((b ^ c) & a) ^ c) + (uint) K [9] + buff [9];
                        d = (d << 12) | (d >> 20);
                        d += a;
 
-                       c += (((a ^ b) & d) ^ b) + (uint) Constants.C10 + buff [10];
+                       c += (((a ^ b) & d) ^ b) + (uint) K [10] + buff [10];
                        c = (c << 17) | (c >> 15);
                        c += d;
 
-                       b += (((d ^ a) & c) ^ a) + (uint) Constants.C11 + buff [11];
+                       b += (((d ^ a) & c) ^ a) + (uint) K [11] + buff [11];
                        b = (b << 22) | (b >> 10);
                        b += c;
 
-                       a += (((c ^ d) & b) ^ d) + (uint) Constants.C12 + buff [12];
+                       a += (((c ^ d) & b) ^ d) + (uint) K [12] + buff [12];
                        a = (a << 7) | (a >> 25);
                        a += b;
 
-                       d += (((b ^ c) & a) ^ c) + (uint) Constants.C13 + buff [13];
+                       d += (((b ^ c) & a) ^ c) + (uint) K [13] + buff [13];
                        d = (d << 12) | (d >> 20);
                        d += a;
 
-                       c += (((a ^ b) & d) ^ b) + (uint) Constants.C14 + buff [14];
+                       c += (((a ^ b) & d) ^ b) + (uint) K [14] + buff [14];
                        c = (c << 17) | (c >> 15);
                        c += d;
 
-                       b += (((d ^ a) & c) ^ a) + (uint) Constants.C15 + buff [15];
+                       b += (((d ^ a) & c) ^ a) + (uint) K [15] + buff [15];
                        b = (b << 22) | (b >> 10);
                        b += c;
 
 
                        // ---- Round 2 --------
   
-                       a += (((b ^ c) & d) ^ c) + (uint) Constants.C16 + buff [1];
+                       a += (((b ^ c) & d) ^ c) + (uint) K [16] + buff [1];
                        a = (a << 5) | (a >> 27);
                        a += b;
 
-                       d += (((a ^ b) & c) ^ b) + (uint) Constants.C17 + buff [6];
+                       d += (((a ^ b) & c) ^ b) + (uint) K [17] + buff [6];
                        d = (d << 9) | (d >> 23);
                        d += a;
 
-                       c += (((d ^ a) & b) ^ a) + (uint) Constants.C18 + buff [11];
+                       c += (((d ^ a) & b) ^ a) + (uint) K [18] + buff [11];
                        c = (c << 14) | (c >> 18);
                        c += d;
 
-                       b += (((c ^ d) & a) ^ d) + (uint) Constants.C19 + buff [0];
+                       b += (((c ^ d) & a) ^ d) + (uint) K [19] + buff [0];
                        b = (b << 20) | (b >> 12);
                        b += c;
 
-                       a += (((b ^ c) & d) ^ c) + (uint) Constants.C20 + buff [5];
+                       a += (((b ^ c) & d) ^ c) + (uint) K [20] + buff [5];
                        a = (a << 5) | (a >> 27);
                        a += b;
 
-                       d += (((a ^ b) & c) ^ b) + (uint) Constants.C21 + buff [10];
+                       d += (((a ^ b) & c) ^ b) + (uint) K [21] + buff [10];
                        d = (d << 9) | (d >> 23);
                        d += a;
 
-                       c += (((d ^ a) & b) ^ a) + (uint) Constants.C22 + buff [15];
+                       c += (((d ^ a) & b) ^ a) + (uint) K [22] + buff [15];
                        c = (c << 14) | (c >> 18);
                        c += d;
 
-                       b += (((c ^ d) & a) ^ d) + (uint) Constants.C23 + buff [4];
+                       b += (((c ^ d) & a) ^ d) + (uint) K [23] + buff [4];
                        b = (b << 20) | (b >> 12);
                        b += c;
 
-                       a += (((b ^ c) & d) ^ c) + (uint) Constants.C24 + buff [9];
+                       a += (((b ^ c) & d) ^ c) + (uint) K [24] + buff [9];
                        a = (a << 5) | (a >> 27);
                        a += b;
 
-                       d += (((a ^ b) & c) ^ b) + (uint) Constants.C25 + buff [14];
+                       d += (((a ^ b) & c) ^ b) + (uint) K [25] + buff [14];
                        d = (d << 9) | (d >> 23);
                        d += a;
 
-                       c += (((d ^ a) & b) ^ a) + (uint) Constants.C26 + buff [3];
+                       c += (((d ^ a) & b) ^ a) + (uint) K [26] + buff [3];
                        c = (c << 14) | (c >> 18);
                        c += d;
 
-                       b += (((c ^ d) & a) ^ d) + (uint) Constants.C27 + buff [8];
+                       b += (((c ^ d) & a) ^ d) + (uint) K [27] + buff [8];
                        b = (b << 20) | (b >> 12);
                        b += c;
 
-                       a += (((b ^ c) & d) ^ c) + (uint) Constants.C28 + buff [13];
+                       a += (((b ^ c) & d) ^ c) + (uint) K [28] + buff [13];
                        a = (a << 5) | (a >> 27);
                        a += b;
 
-                       d += (((a ^ b) & c) ^ b) + (uint) Constants.C29 + buff [2];
+                       d += (((a ^ b) & c) ^ b) + (uint) K [29] + buff [2];
                        d = (d << 9) | (d >> 23);
                        d += a;
 
-                       c += (((d ^ a) & b) ^ a) + (uint) Constants.C30 + buff [7];
+                       c += (((d ^ a) & b) ^ a) + (uint) K [30] + buff [7];
                        c = (c << 14) | (c >> 18);
                        c += d;
 
-                       b += (((c ^ d) & a) ^ d) + (uint) Constants.C31 + buff [12];
+                       b += (((c ^ d) & a) ^ d) + (uint) K [31] + buff [12];
                        b = (b << 20) | (b >> 12);
                        b += c;
 
 
                        // ---- Round 3 --------
   
-                       a += (b ^ c ^ d) + (uint) Constants.C32 + buff [5];
+                       a += (b ^ c ^ d) + (uint) K [32] + buff [5];
                        a = (a << 4) | (a >> 28);
                        a += b;
 
-                       d += (a ^ b ^ c) + (uint) Constants.C33 + buff [8];
+                       d += (a ^ b ^ c) + (uint) K [33] + buff [8];
                        d = (d << 11) | (d >> 21);
                        d += a;
 
-                       c += (d ^ a ^ b) + (uint) Constants.C34 + buff [11];
+                       c += (d ^ a ^ b) + (uint) K [34] + buff [11];
                        c = (c << 16) | (c >> 16);
                        c += d;
 
-                       b += (c ^ d ^ a) + (uint) Constants.C35 + buff [14];
+                       b += (c ^ d ^ a) + (uint) K [35] + buff [14];
                        b = (b << 23) | (b >> 9);
                        b += c;
 
-                       a += (b ^ c ^ d) + (uint) Constants.C36 + buff [1];
+                       a += (b ^ c ^ d) + (uint) K [36] + buff [1];
                        a = (a << 4) | (a >> 28);
                        a += b;
 
-                       d += (a ^ b ^ c) + (uint) Constants.C37 + buff [4];
+                       d += (a ^ b ^ c) + (uint) K [37] + buff [4];
                        d = (d << 11) | (d >> 21);
                        d += a;
 
-                       c += (d ^ a ^ b) + (uint) Constants.C38 + buff [7];
+                       c += (d ^ a ^ b) + (uint) K [38] + buff [7];
                        c = (c << 16) | (c >> 16);
                        c += d;
 
-                       b += (c ^ d ^ a) + (uint) Constants.C39 + buff [10];
+                       b += (c ^ d ^ a) + (uint) K [39] + buff [10];
                        b = (b << 23) | (b >> 9);
                        b += c;
 
-                       a += (b ^ c ^ d) + (uint) Constants.C40 + buff [13];
+                       a += (b ^ c ^ d) + (uint) K [40] + buff [13];
                        a = (a << 4) | (a >> 28);
                        a += b;
 
-                       d += (a ^ b ^ c) + (uint) Constants.C41 + buff [0];
+                       d += (a ^ b ^ c) + (uint) K [41] + buff [0];
                        d = (d << 11) | (d >> 21);
                        d += a;
 
-                       c += (d ^ a ^ b) + (uint) Constants.C42 + buff [3];
+                       c += (d ^ a ^ b) + (uint) K [42] + buff [3];
                        c = (c << 16) | (c >> 16);
                        c += d;
 
-                       b += (c ^ d ^ a) + (uint) Constants.C43 + buff [6];
+                       b += (c ^ d ^ a) + (uint) K [43] + buff [6];
                        b = (b << 23) | (b >> 9);
                        b += c;
 
-                       a += (b ^ c ^ d) + (uint) Constants.C44 + buff [9];
+                       a += (b ^ c ^ d) + (uint) K [44] + buff [9];
                        a = (a << 4) | (a >> 28);
                        a += b;
 
-                       d += (a ^ b ^ c) + (uint) Constants.C45 + buff [12];
+                       d += (a ^ b ^ c) + (uint) K [45] + buff [12];
                        d = (d << 11) | (d >> 21);
                        d += a;
 
-                       c += (d ^ a ^ b) + (uint) Constants.C46 + buff [15];
+                       c += (d ^ a ^ b) + (uint) K [46] + buff [15];
                        c = (c << 16) | (c >> 16);
                        c += d;
 
-                       b += (c ^ d ^ a) + (uint) Constants.C47 + buff [2];
+                       b += (c ^ d ^ a) + (uint) K [47] + buff [2];
                        b = (b << 23) | (b >> 9);
                        b += c;
 
 
                        // ---- Round 4 --------
   
-                       a += (((~d) | b) ^ c) + (uint) Constants.C48 + buff [0];
+                       a += (((~d) | b) ^ c) + (uint) K [48] + buff [0];
                        a = (a << 6) | (a >> 26);
                        a += b;
 
-                       d += (((~c) | a) ^ b) + (uint) Constants.C49 + buff [7];
+                       d += (((~c) | a) ^ b) + (uint) K [49] + buff [7];
                        d = (d << 10) | (d >> 22);
                        d += a;
 
-                       c += (((~b) | d) ^ a) + (uint) Constants.C50 + buff [14];
+                       c += (((~b) | d) ^ a) + (uint) K [50] + buff [14];
                        c = (c << 15) | (c >> 17);
                        c += d;
 
-                       b += (((~a) | c) ^ d) + (uint) Constants.C51 + buff [5];
+                       b += (((~a) | c) ^ d) + (uint) K [51] + buff [5];
                        b = (b << 21) | (b >> 11);
                        b += c;
 
-                       a += (((~d) | b) ^ c) + (uint) Constants.C52 + buff [12];
+                       a += (((~d) | b) ^ c) + (uint) K [52] + buff [12];
                        a = (a << 6) | (a >> 26);
                        a += b;
 
-                       d += (((~c) | a) ^ b) + (uint) Constants.C53 + buff [3];
+                       d += (((~c) | a) ^ b) + (uint) K [53] + buff [3];
                        d = (d << 10) | (d >> 22);
                        d += a;
 
-                       c += (((~b) | d) ^ a) + (uint) Constants.C54 + buff [10];
+                       c += (((~b) | d) ^ a) + (uint) K [54] + buff [10];
                        c = (c << 15) | (c >> 17);
                        c += d;
 
-                       b += (((~a) | c) ^ d) + (uint) Constants.C55 + buff [1];
+                       b += (((~a) | c) ^ d) + (uint) K [55] + buff [1];
                        b = (b << 21) | (b >> 11);
                        b += c;
 
-                       a += (((~d) | b) ^ c) + (uint) Constants.C56 + buff [8];
+                       a += (((~d) | b) ^ c) + (uint) K [56] + buff [8];
                        a = (a << 6) | (a >> 26);
                        a += b;
 
-                       d += (((~c) | a) ^ b) + (uint) Constants.C57 + buff [15];
+                       d += (((~c) | a) ^ b) + (uint) K [57] + buff [15];
                        d = (d << 10) | (d >> 22);
                        d += a;
 
-                       c += (((~b) | d) ^ a) + (uint) Constants.C58 + buff [6];
+                       c += (((~b) | d) ^ a) + (uint) K [58] + buff [6];
                        c = (c << 15) | (c >> 17);
                        c += d;
 
-                       b += (((~a) | c) ^ d) + (uint) Constants.C59 + buff [13];
+                       b += (((~a) | c) ^ d) + (uint) K [59] + buff [13];
                        b = (b << 21) | (b >> 11);
                        b += c;
 
-                       a += (((~d) | b) ^ c) + (uint) Constants.C60 + buff [4];
+                       a += (((~d) | b) ^ c) + (uint) K [60] + buff [4];
                        a = (a << 6) | (a >> 26);
                        a += b;
 
-                       d += (((~c) | a) ^ b) + (uint) Constants.C61 + buff [11];
+                       d += (((~c) | a) ^ b) + (uint) K [61] + buff [11];
                        d = (d << 10) | (d >> 22);
                        d += a;
 
-                       c += (((~b) | d) ^ a) + (uint) Constants.C62 + buff [2];
+                       c += (((~b) | d) ^ a) + (uint) K [62] + buff [2];
                        c = (c << 15) | (c >> 17);
                        c += d;
 
-                       b += (((~a) | c) ^ d) + (uint) Constants.C63 + buff [9];
+                       b += (((~a) | c) ^ d) + (uint) K [63] + buff [9];
                        b = (b << 21) | (b >> 11);
                        b += c;
 
-
-                       _H[0] += a;
-                       _H[1] += b;
-                       _H[2] += c;
-                       _H[3] += d;
+                       _H [0] += a;
+                       _H [1] += b;
+                       _H [2] += c;
+                       _H [3] += d;
                }
                
-               /// <summary>
-               /// Pads and then processes the final block.
-               /// </summary>
-               /// <param name="inputBuffer">Buffer to grab data from.</param>
-               /// <param name="inputOffset">Position in buffer in bytes to get data from.</param>
-               /// <param name="inputCount">How much data in bytes in the buffer to use.</param>
                private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount) 
                {
-                       byte[] fooBuffer;
-                       int paddingSize;
-                       int i;
-                       uint size;
-
-                       paddingSize = (int)(56 - (inputCount + count) % BLOCK_SIZE_BYTES);
+                       ulong total = count + (ulong)inputCount;
+                       int paddingSize = (int)(56 - total % BLOCK_SIZE_BYTES);
 
                        if (paddingSize < 1)
                                paddingSize += BLOCK_SIZE_BYTES;
 
+                       byte[] fooBuffer = new byte [inputCount+paddingSize+8];
 
-                       fooBuffer = new byte[inputCount+paddingSize+8];
-
-                       for (i=0; i<inputCount; i++) {
+                       for (int i=0; i<inputCount; i++) {
                                fooBuffer[i] = inputBuffer[i+inputOffset];
                        }
 
                        fooBuffer[inputCount] = 0x80;
-                       for (i=inputCount+1; i<inputCount+paddingSize; i++) {
+                       for (int i=inputCount+1; i<inputCount+paddingSize; i++) {
                                fooBuffer[i] = 0x00;
                        }
 
-                       size = (uint)(count+inputCount);
-                       size *= 8;
-                       fooBuffer[inputCount+paddingSize] = (byte)((size) >>  0);
-                       fooBuffer[inputCount+paddingSize+1] = (byte)((size) >>  8);
-                       fooBuffer[inputCount+paddingSize+2] = (byte)((size) >> 16);
-                       fooBuffer[inputCount+paddingSize+3] = (byte)((size) >> 24);
-
-                       fooBuffer[inputCount+paddingSize+4]   = 0x00;
-                       fooBuffer[inputCount+paddingSize+5] = 0x00;
-                       fooBuffer[inputCount+paddingSize+6] = 0x00;
-                       fooBuffer[inputCount+paddingSize+7] = 0x00;
-
-                       ProcessBlock(fooBuffer, 0);
+                       // I deal in bytes. The algorithm deals in bits.
+                       ulong size = total << 3;
+                       AddLength (size, fooBuffer, inputCount+paddingSize);
+                       ProcessBlock (fooBuffer, 0);
 
                        if (inputCount+paddingSize+8 == 128) {
                                ProcessBlock(fooBuffer, 64);
                        }
                }
-               
-               private enum Constants : uint {
-                        C0 = 0xd76aa478, C1 = 0xe8c7b756, C2 = 0x242070db,
-                        C3 = 0xc1bdceee, C4 = 0xf57c0faf, C5 = 0x4787c62a,
-                        C6 = 0xa8304613, C7 = 0xfd469501, C8 = 0x698098d8,
-                        C9 = 0x8b44f7af,C10 = 0xffff5bb1,C11 = 0x895cd7be,
-                       C12 = 0x6b901122,C13 = 0xfd987193,C14 = 0xa679438e,
-                       C15 = 0x49b40821,C16 = 0xf61e2562,C17 = 0xc040b340,
-                       C18 = 0x265e5a51,C19 = 0xe9b6c7aa,C20 = 0xd62f105d,
-                       C21 = 0x02441453,C22 = 0xd8a1e681,C23 = 0xe7d3fbc8,
-                       C24 = 0x21e1cde6,C25 = 0xc33707d6,C26 = 0xf4d50d87,
-                       C27 = 0x455a14ed,C28 = 0xa9e3e905,C29 = 0xfcefa3f8,
-                       C30 = 0x676f02d9,C31 = 0x8d2a4c8a,C32 = 0xfffa3942,
-                       C33 = 0x8771f681,C34 = 0x6d9d6122,C35 = 0xfde5380c,
-                       C36 = 0xa4beea44,C37 = 0x4bdecfa9,C38 = 0xf6bb4b60,
-                       C39 = 0xbebfbc70,C40 = 0x289b7ec6,C41 = 0xeaa127fa,
-                       C42 = 0xd4ef3085,C43 = 0x04881d05,C44 = 0xd9d4d039,
-                       C45 = 0xe6db99e5,C46 = 0x1fa27cf8,C47 = 0xc4ac5665,
-                       C48 = 0xf4292244,C49 = 0x432aff97,C50 = 0xab9423a7,
-                       C51 = 0xfc93a039,C52 = 0x655b59c3,C53 = 0x8f0ccc92,
-                       C54 = 0xffeff47d,C55 = 0x85845dd1,C56 = 0x6fa87e4f,
-                       C57 = 0xfe2ce6e0,C58 = 0xa3014314,C59 = 0x4e0811a1,
-                       C60 = 0xf7537e82,C61 = 0xbd3af235,C62 = 0x2ad7d2bb,
-                       C63 = 0xeb86d391
+
+               internal void AddLength (ulong length, byte[] buffer, int position)
+               {
+                       buffer [position++] = (byte)(length);
+                       buffer [position++] = (byte)(length >>  8);
+                       buffer [position++] = (byte)(length >> 16);
+                       buffer [position++] = (byte)(length >> 24);
+                       buffer [position++] = (byte)(length >> 32);
+                       buffer [position++] = (byte)(length >> 40);
+                       buffer [position++] = (byte)(length >> 48);
+                       buffer [position]   = (byte)(length >> 56);
                }
 
+               private readonly static uint[] K = {
+                       0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+                       0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 
+                       0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+                       0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+                       0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+                       0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+                       0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+                       0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+                       0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+                       0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+                       0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+                       0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+                       0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+                       0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+                       0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+                       0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+               };
        }
 }