New test.
[mono.git] / mcs / class / corlib / System.Security.Cryptography / SHA1CryptoServiceProvider.cs
index 0657e85dfeb4884c6cf1ab67e7ea4e5b72d98a72..9f5c9db6260a2cf289acf9e13780da1d9e6039dc 100644 (file)
@@ -6,7 +6,26 @@
 //     Sebastien Pouliot (sebastien@ximian.com)
 //
 // Copyright 2001 by Matthew S. Ford.
-// (C) 2004 Novell (http://www.novell.com)
+// 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.
 //
 
 // Note:
@@ -16,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 {
@@ -23,14 +44,16 @@ 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;
 
                public SHA1Internal () 
                {
                        _H = new uint[5];
                        _ProcessingBuffer = new byte[BLOCK_SIZE_BYTES];
+                       buff = new uint[80];
                        
                        Initialize();
                }
@@ -94,7 +117,6 @@ namespace System.Security.Cryptography {
 
                private void ProcessBlock(byte[] inputBuffer, int inputOffset) 
                {
-                       uint[] buff = new uint[80];
                        uint a, b, c, d, e;
                        int i;
 
@@ -379,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;