New test.
[mono.git] / mcs / class / corlib / System.Security.Cryptography / SHA1CryptoServiceProvider.cs
index 55c70519cf9c88548e13933a6a21f849f1c46cfa..9f5c9db6260a2cf289acf9e13780da1d9e6039dc 100644 (file)
@@ -35,6 +35,8 @@
 // Mono must provide those two class for binary compatibility.
 // In our case both class are wrappers around a managed internal class SHA1Internal.
 
+using System.Runtime.InteropServices;
+
 namespace System.Security.Cryptography {
 
        internal class SHA1Internal {
@@ -42,7 +44,7 @@ namespace System.Security.Cryptography {
                private const int BLOCK_SIZE_BYTES =  64;
                private const int HASH_SIZE_BYTES  =  20;
                private uint[] _H;  // these are my chaining variables
-               private uint count;
+               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.
                private uint[] buff;
@@ -399,44 +401,49 @@ namespace System.Security.Cryptography {
        
                private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount) 
                {
-                       int i;
-                       int paddingSize = (int)(56 - (inputCount + count) % BLOCK_SIZE_BYTES);
+                       ulong total = count + (ulong)inputCount;
+                       int paddingSize = (56 - (int)(total % BLOCK_SIZE_BYTES));
 
                        if (paddingSize < 1)
                                paddingSize += BLOCK_SIZE_BYTES;
 
                        byte[] 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;
                        }
 
                        // I deal in bytes. The algorithm deals in bits.
-                       uint size = (uint)((count+inputCount) << 3);
-
-                       fooBuffer[inputCount+paddingSize]   = 0x00;
-                       fooBuffer[inputCount+paddingSize+1] = 0x00;
-                       fooBuffer[inputCount+paddingSize+2] = 0x00;
-                       fooBuffer[inputCount+paddingSize+3] = 0x00;
-
-                       fooBuffer[inputCount+paddingSize+4] = (byte)((size) >> 24);
-                       fooBuffer[inputCount+paddingSize+5] = (byte)((size) >> 16);
-                       fooBuffer[inputCount+paddingSize+6] = (byte)((size) >>  8);
-                       fooBuffer[inputCount+paddingSize+7] = (byte)((size) >>  0);
-
-                       ProcessBlock(fooBuffer, 0);
+                       ulong size = total << 3;
+                       AddLength (size, fooBuffer, inputCount+paddingSize);
+                       ProcessBlock (fooBuffer, 0);
 
                        if (inputCount+paddingSize+8 == 128) {
                                ProcessBlock(fooBuffer, 64);
                        }
                }
+
+               internal void AddLength (ulong length, byte[] buffer, int position)
+               {
+                       buffer [position++] = (byte)(length >> 56);
+                       buffer [position++] = (byte)(length >> 48);
+                       buffer [position++] = (byte)(length >> 40);
+                       buffer [position++] = (byte)(length >> 32);
+                       buffer [position++] = (byte)(length >> 24);
+                       buffer [position++] = (byte)(length >> 16);
+                       buffer [position++] = (byte)(length >>  8);
+                       buffer [position]   = (byte)(length);
+               }
        }
 
+#if NET_2_0
+       [ComVisible (true)]
+#endif
        public sealed class SHA1CryptoServiceProvider : SHA1 {
 
                private SHA1Internal sha;