New test.
[mono.git] / mcs / class / corlib / System.Security.Cryptography / SHA1CryptoServiceProvider.cs
index ea7f6a75f30fce4e96ac429fb2874b5f84451e91..9f5c9db6260a2cf289acf9e13780da1d9e6039dc 100644 (file)
@@ -6,11 +6,7 @@
 //     Sebastien Pouliot (sebastien@ximian.com)
 //
 // Copyright 2001 by Matthew S. Ford.
-// (C) 2004 Novell (http://www.novell.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (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
@@ -39,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 {
@@ -46,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();
                }
@@ -117,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;
 
@@ -402,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;