// 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:
// 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 {
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();
}
private void ProcessBlock(byte[] inputBuffer, int inputOffset)
{
- uint[] buff = new uint[80];
uint a, b, c, d, e;
int i;
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;