2 // System.Security.Cryptography SHA1CryptoServiceProvider Class implementation
5 // Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
6 // Sebastien Pouliot (sebastien@ximian.com)
8 // Copyright 2001 by Matthew S. Ford.
9 // (C) 2004 Novell (http://www.novell.com)
13 // The MS Framework includes two (almost) identical class for SHA1.
14 // SHA1Managed is a 100% managed implementation.
15 // SHA1CryptoServiceProvider (this file) is a wrapper on CryptoAPI.
16 // Mono must provide those two class for binary compatibility.
17 // In our case both class are wrappers around a managed internal class SHA1Internal.
19 namespace System.Security.Cryptography {
21 internal class SHA1Internal {
23 private const int BLOCK_SIZE_BYTES = 64;
24 private const int HASH_SIZE_BYTES = 20;
25 private uint[] _H; // these are my chaining variables
27 private byte[] _ProcessingBuffer; // Used to start data when passed less than a block worth.
28 private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
30 public SHA1Internal ()
33 _ProcessingBuffer = new byte[BLOCK_SIZE_BYTES];
38 public void HashCore (byte[] rgb, int start, int size)
42 if (_ProcessingBufferCount != 0) {
43 if (size < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
44 System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, size);
45 _ProcessingBufferCount += size;
49 i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
50 System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, i);
51 ProcessBlock (_ProcessingBuffer, 0);
52 _ProcessingBufferCount = 0;
58 for (i=0; i<size-size%BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
59 ProcessBlock (rgb, start+i);
62 if (size%BLOCK_SIZE_BYTES != 0) {
63 System.Buffer.BlockCopy (rgb, size-size%BLOCK_SIZE_BYTES+start, _ProcessingBuffer, 0, size%BLOCK_SIZE_BYTES);
64 _ProcessingBufferCount = size%BLOCK_SIZE_BYTES;
68 public byte[] HashFinal ()
70 byte[] hash = new byte[20];
72 ProcessFinalBlock (_ProcessingBuffer, 0, _ProcessingBufferCount);
74 for (int i=0; i<5; i++) {
75 for (int j=0; j<4; j++) {
76 hash [i*4+j] = (byte)(_H[i] >> (8*(3-j)));
83 public void Initialize ()
86 _ProcessingBufferCount = 0;
95 private void ProcessBlock(byte[] inputBuffer, int inputOffset)
97 uint[] buff = new uint[80];
101 count += BLOCK_SIZE_BYTES;
103 for (i=0; i<16; i++) {
104 buff[i] = ((uint)(inputBuffer[inputOffset+4*i]) << 24)
105 | ((uint)(inputBuffer[inputOffset+4*i+1]) << 16)
106 | ((uint)(inputBuffer[inputOffset+4*i+2]) << 8)
107 | ((uint)(inputBuffer[inputOffset+4*i+3]));
110 for (i=16; i<80; i++) {
111 buff[i] = ((buff[i-3] ^ buff[i-8] ^ buff[i-14] ^ buff[i-16]) << 1)
112 | ((buff[i-3] ^ buff[i-8] ^ buff[i-14] ^ buff[i-16]) >> 31);
121 // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
122 // Possibly roll up if this changes.
124 // ---- Round 1 --------
126 e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[0];
127 b = (b << 30) | (b >> 2);
129 d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[1];
130 a = (a << 30) | (a >> 2);
132 c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[2];
133 e = (e << 30) | (e >> 2);
135 b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[3];
136 d = (d << 30) | (d >> 2);
138 a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[4];
139 c = (c << 30) | (c >> 2);
141 e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[5];
142 b = (b << 30) | (b >> 2);
144 d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[6];
145 a = (a << 30) | (a >> 2);
147 c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[7];
148 e = (e << 30) | (e >> 2);
150 b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[8];
151 d = (d << 30) | (d >> 2);
153 a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[9];
154 c = (c << 30) | (c >> 2);
156 e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[10];
157 b = (b << 30) | (b >> 2);
159 d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[11];
160 a = (a << 30) | (a >> 2);
162 c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[12];
163 e = (e << 30) | (e >> 2);
165 b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[13];
166 d = (d << 30) | (d >> 2);
168 a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[14];
169 c = (c << 30) | (c >> 2);
171 e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[15];
172 b = (b << 30) | (b >> 2);
174 d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[16];
175 a = (a << 30) | (a >> 2);
177 c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[17];
178 e = (e << 30) | (e >> 2);
180 b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[18];
181 d = (d << 30) | (d >> 2);
183 a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[19];
184 c = (c << 30) | (c >> 2);
186 // ---- Round 2 --------
188 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[20];
189 b = (b << 30) | (b >> 2);
191 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[21];
192 a = (a << 30) | (a >> 2);
194 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[22];
195 e = (e << 30) | (e >> 2);
197 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[23];
198 d = (d << 30) | (d >> 2);
200 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[24];
201 c = (c << 30) | (c >> 2);
203 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[25];
204 b = (b << 30) | (b >> 2);
206 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[26];
207 a = (a << 30) | (a >> 2);
209 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[27];
210 e = (e << 30) | (e >> 2);
212 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[28];
213 d = (d << 30) | (d >> 2);
215 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[29];
216 c = (c << 30) | (c >> 2);
218 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[30];
219 b = (b << 30) | (b >> 2);
221 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[31];
222 a = (a << 30) | (a >> 2);
224 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[32];
225 e = (e << 30) | (e >> 2);
227 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[33];
228 d = (d << 30) | (d >> 2);
230 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[34];
231 c = (c << 30) | (c >> 2);
233 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[35];
234 b = (b << 30) | (b >> 2);
236 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[36];
237 a = (a << 30) | (a >> 2);
239 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[37];
240 e = (e << 30) | (e >> 2);
242 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[38];
243 d = (d << 30) | (d >> 2);
245 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[39];
246 c = (c << 30) | (c >> 2);
248 // ---- Round 3 --------
250 e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[40];
251 b = (b << 30) | (b >> 2);
253 d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[41];
254 a = (a << 30) | (a >> 2);
256 c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[42];
257 e = (e << 30) | (e >> 2);
259 b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[43];
260 d = (d << 30) | (d >> 2);
262 a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[44];
263 c = (c << 30) | (c >> 2);
265 e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[45];
266 b = (b << 30) | (b >> 2);
268 d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[46];
269 a = (a << 30) | (a >> 2);
271 c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[47];
272 e = (e << 30) | (e >> 2);
274 b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[48];
275 d = (d << 30) | (d >> 2);
277 a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[49];
278 c = (c << 30) | (c >> 2);
280 e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[50];
281 b = (b << 30) | (b >> 2);
283 d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[51];
284 a = (a << 30) | (a >> 2);
286 c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[52];
287 e = (e << 30) | (e >> 2);
289 b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[53];
290 d = (d << 30) | (d >> 2);
292 a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[54];
293 c = (c << 30) | (c >> 2);
295 e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[55];
296 b = (b << 30) | (b >> 2);
298 d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[56];
299 a = (a << 30) | (a >> 2);
301 c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[57];
302 e = (e << 30) | (e >> 2);
304 b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[58];
305 d = (d << 30) | (d >> 2);
307 a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[59];
308 c = (c << 30) | (c >> 2);
310 // ---- Round 4 --------
312 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[60];
313 b = (b << 30) | (b >> 2);
315 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[61];
316 a = (a << 30) | (a >> 2);
318 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[62];
319 e = (e << 30) | (e >> 2);
321 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[63];
322 d = (d << 30) | (d >> 2);
324 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[64];
325 c = (c << 30) | (c >> 2);
327 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[65];
328 b = (b << 30) | (b >> 2);
330 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[66];
331 a = (a << 30) | (a >> 2);
333 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[67];
334 e = (e << 30) | (e >> 2);
336 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[68];
337 d = (d << 30) | (d >> 2);
339 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[69];
340 c = (c << 30) | (c >> 2);
342 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[70];
343 b = (b << 30) | (b >> 2);
345 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[71];
346 a = (a << 30) | (a >> 2);
348 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[72];
349 e = (e << 30) | (e >> 2);
351 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[73];
352 d = (d << 30) | (d >> 2);
354 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[74];
355 c = (c << 30) | (c >> 2);
357 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[75];
358 b = (b << 30) | (b >> 2);
360 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[76];
361 a = (a << 30) | (a >> 2);
363 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[77];
364 e = (e << 30) | (e >> 2);
366 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[78];
367 d = (d << 30) | (d >> 2);
369 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[79];
370 c = (c << 30) | (c >> 2);
380 private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
383 int paddingSize = (int)(56 - (inputCount + count) % BLOCK_SIZE_BYTES);
386 paddingSize += BLOCK_SIZE_BYTES;
388 byte[] fooBuffer = new byte[inputCount+paddingSize+8];
390 for (i=0; i<inputCount; i++) {
391 fooBuffer[i] = inputBuffer[i+inputOffset];
394 fooBuffer[inputCount] = 0x80;
395 for (i=inputCount+1; i<inputCount+paddingSize; i++) {
399 // I deal in bytes. The algorithm deals in bits.
400 uint size = (uint)((count+inputCount) << 3);
402 fooBuffer[inputCount+paddingSize] = 0x00;
403 fooBuffer[inputCount+paddingSize+1] = 0x00;
404 fooBuffer[inputCount+paddingSize+2] = 0x00;
405 fooBuffer[inputCount+paddingSize+3] = 0x00;
407 fooBuffer[inputCount+paddingSize+4] = (byte)((size) >> 24);
408 fooBuffer[inputCount+paddingSize+5] = (byte)((size) >> 16);
409 fooBuffer[inputCount+paddingSize+6] = (byte)((size) >> 8);
410 fooBuffer[inputCount+paddingSize+7] = (byte)((size) >> 0);
412 ProcessBlock(fooBuffer, 0);
414 if (inputCount+paddingSize+8 == 128) {
415 ProcessBlock(fooBuffer, 64);
420 public sealed class SHA1CryptoServiceProvider : SHA1 {
422 private SHA1Internal sha;
424 public SHA1CryptoServiceProvider ()
426 sha = new SHA1Internal ();
429 ~SHA1CryptoServiceProvider ()
434 protected override void Dispose (bool disposing)
436 // nothing new to do (managed implementation)
437 base.Dispose (disposing);
440 protected override void HashCore (byte[] rgb, int start, int size)
443 sha.HashCore (rgb, start, size);
446 protected override byte[] HashFinal ()
449 return sha.HashFinal ();
452 public override void Initialize ()