2 // System.Security.Cryptography SHA1CryptoServiceProvider Class implementation
\r
5 // Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
\r
7 // Copyright 2001 by Matthew S. Ford.
\r
11 using System.Security.Cryptography;
\r
13 namespace System.Security.Cryptography {
\r
16 /// C# implementation of the SHA1 cryptographic hash function.
\r
17 /// LAMESPEC?: Basically the same thing as SHA1Managed except for how its implemented.
\r
19 public sealed class SHA1CryptoServiceProvider : SHA1 {
\r
20 private const int BLOCK_SIZE_BYTES = 64;
\r
21 private const int HASH_SIZE_BYTES = 20;
\r
22 private const int HASH_SIZE_BITS = 160;
\r
23 [CLSCompliant(false)] private uint[] _H; // these are my chaining variables
\r
24 [CLSCompliant(false)] private uint count;
\r
25 private byte[] _ProcessingBuffer; // Used to start data when passed less than a block worth.
\r
26 private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
\r
29 /// Creates a new SHA1CryptoServiceProvider.
\r
31 public SHA1CryptoServiceProvider () {
\r
33 HashSizeValue = HASH_SIZE_BITS;
\r
34 _ProcessingBuffer = new byte[BLOCK_SIZE_BYTES];
\r
40 /// Drives the hashing function.
\r
42 /// <param name="rgb">Byte array containing the data to hash.</param>
\r
43 /// <param name="start">Where in the input buffer to start.</param>
\r
44 /// <param name="size">Size in bytes of the data in the buffer to hash.</param>
\r
45 protected override void HashCore (byte[] rgb, int start, int size) {
\r
49 if (_ProcessingBufferCount != 0) {
\r
50 if (size < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
\r
51 System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, size);
\r
52 _ProcessingBufferCount += size;
\r
56 i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
\r
57 System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, i);
\r
58 ProcessBlock (_ProcessingBuffer, 0);
\r
59 _ProcessingBufferCount = 0;
\r
65 for (i=0; i<size-size%BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
\r
66 ProcessBlock (rgb, start+i);
\r
69 if (size%BLOCK_SIZE_BYTES != 0) {
\r
70 System.Buffer.BlockCopy (rgb, size-size%BLOCK_SIZE_BYTES+start, _ProcessingBuffer, 0, size%BLOCK_SIZE_BYTES);
\r
71 _ProcessingBufferCount = size%BLOCK_SIZE_BYTES;
\r
76 /// This finalizes the hash. Takes the data from the chaining variables and returns it.
\r
78 protected override byte[] HashFinal () {
\r
79 byte[] hash = new byte[20];
\r
82 ProcessFinalBlock(_ProcessingBuffer, 0, _ProcessingBufferCount);
\r
84 for (i=0; i<5; i++) {
\r
85 for (j=0; j<4; j++) {
\r
86 hash[i*4+j] = (byte)(_H[i] >> (8*(3-j)));
\r
96 /// Resets the class after use. Called automatically after hashing is done.
\r
98 public override void Initialize () {
\r
100 _ProcessingBufferCount = 0;
\r
102 _H[0] = 0x67452301;
\r
103 _H[1] = 0xefcdab89;
\r
104 _H[2] = 0x98badcfe;
\r
105 _H[3] = 0x10325476;
\r
106 _H[4] = 0xC3D2E1F0;
\r
110 /// This is the meat of the hash function. It is what processes each block one at a time.
\r
112 /// <param name="inputBuffer">Byte array to process data from.</param>
\r
113 /// <param name="inputOffset">Where in the byte array to start processing.</param>
\r
114 private void ProcessBlock(byte[] inputBuffer, int inputOffset) {
\r
115 uint[] buff = new uint[80];
\r
116 uint a, b, c, d, e;
\r
119 count += BLOCK_SIZE_BYTES;
\r
121 for (i=0; i<16; i++) {
\r
122 buff[i] = ((uint)(inputBuffer[inputOffset+4*i]) << 24)
\r
123 | ((uint)(inputBuffer[inputOffset+4*i+1]) << 16)
\r
124 | ((uint)(inputBuffer[inputOffset+4*i+2]) << 8)
\r
125 | ((uint)(inputBuffer[inputOffset+4*i+3]));
\r
128 for (i=16; i<80; i++) {
\r
129 buff[i] = ((buff[i-3] ^ buff[i-8] ^ buff[i-14] ^ buff[i-16]) << 1)
\r
130 | ((buff[i-3] ^ buff[i-8] ^ buff[i-14] ^ buff[i-16]) >> 31);
\r
140 // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
\r
141 // Possibly roll up if this changes.
\r
143 // ---- Round 1 --------
\r
145 e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[0];
\r
146 b = (b << 30) | (b >> 2);
\r
148 d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[1];
\r
149 a = (a << 30) | (a >> 2);
\r
151 c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[2];
\r
152 e = (e << 30) | (e >> 2);
\r
154 b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[3];
\r
155 d = (d << 30) | (d >> 2);
\r
157 a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[4];
\r
158 c = (c << 30) | (c >> 2);
\r
160 e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[5];
\r
161 b = (b << 30) | (b >> 2);
\r
163 d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[6];
\r
164 a = (a << 30) | (a >> 2);
\r
166 c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[7];
\r
167 e = (e << 30) | (e >> 2);
\r
169 b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[8];
\r
170 d = (d << 30) | (d >> 2);
\r
172 a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[9];
\r
173 c = (c << 30) | (c >> 2);
\r
175 e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[10];
\r
176 b = (b << 30) | (b >> 2);
\r
178 d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[11];
\r
179 a = (a << 30) | (a >> 2);
\r
181 c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[12];
\r
182 e = (e << 30) | (e >> 2);
\r
184 b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[13];
\r
185 d = (d << 30) | (d >> 2);
\r
187 a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[14];
\r
188 c = (c << 30) | (c >> 2);
\r
190 e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[15];
\r
191 b = (b << 30) | (b >> 2);
\r
193 d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[16];
\r
194 a = (a << 30) | (a >> 2);
\r
196 c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[17];
\r
197 e = (e << 30) | (e >> 2);
\r
199 b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[18];
\r
200 d = (d << 30) | (d >> 2);
\r
202 a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[19];
\r
203 c = (c << 30) | (c >> 2);
\r
207 // ---- Round 2 --------
\r
209 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[20];
\r
210 b = (b << 30) | (b >> 2);
\r
212 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[21];
\r
213 a = (a << 30) | (a >> 2);
\r
215 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[22];
\r
216 e = (e << 30) | (e >> 2);
\r
218 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[23];
\r
219 d = (d << 30) | (d >> 2);
\r
221 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[24];
\r
222 c = (c << 30) | (c >> 2);
\r
224 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[25];
\r
225 b = (b << 30) | (b >> 2);
\r
227 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[26];
\r
228 a = (a << 30) | (a >> 2);
\r
230 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[27];
\r
231 e = (e << 30) | (e >> 2);
\r
233 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[28];
\r
234 d = (d << 30) | (d >> 2);
\r
236 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[29];
\r
237 c = (c << 30) | (c >> 2);
\r
239 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[30];
\r
240 b = (b << 30) | (b >> 2);
\r
242 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[31];
\r
243 a = (a << 30) | (a >> 2);
\r
245 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[32];
\r
246 e = (e << 30) | (e >> 2);
\r
248 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[33];
\r
249 d = (d << 30) | (d >> 2);
\r
251 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[34];
\r
252 c = (c << 30) | (c >> 2);
\r
254 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[35];
\r
255 b = (b << 30) | (b >> 2);
\r
257 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[36];
\r
258 a = (a << 30) | (a >> 2);
\r
260 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[37];
\r
261 e = (e << 30) | (e >> 2);
\r
263 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[38];
\r
264 d = (d << 30) | (d >> 2);
\r
266 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[39];
\r
267 c = (c << 30) | (c >> 2);
\r
271 // ---- Round 3 --------
\r
273 e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[40];
\r
274 b = (b << 30) | (b >> 2);
\r
276 d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[41];
\r
277 a = (a << 30) | (a >> 2);
\r
279 c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[42];
\r
280 e = (e << 30) | (e >> 2);
\r
282 b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[43];
\r
283 d = (d << 30) | (d >> 2);
\r
285 a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[44];
\r
286 c = (c << 30) | (c >> 2);
\r
288 e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[45];
\r
289 b = (b << 30) | (b >> 2);
\r
291 d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[46];
\r
292 a = (a << 30) | (a >> 2);
\r
294 c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[47];
\r
295 e = (e << 30) | (e >> 2);
\r
297 b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[48];
\r
298 d = (d << 30) | (d >> 2);
\r
300 a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[49];
\r
301 c = (c << 30) | (c >> 2);
\r
303 e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[50];
\r
304 b = (b << 30) | (b >> 2);
\r
306 d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[51];
\r
307 a = (a << 30) | (a >> 2);
\r
309 c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[52];
\r
310 e = (e << 30) | (e >> 2);
\r
312 b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[53];
\r
313 d = (d << 30) | (d >> 2);
\r
315 a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[54];
\r
316 c = (c << 30) | (c >> 2);
\r
318 e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[55];
\r
319 b = (b << 30) | (b >> 2);
\r
321 d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[56];
\r
322 a = (a << 30) | (a >> 2);
\r
324 c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[57];
\r
325 e = (e << 30) | (e >> 2);
\r
327 b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[58];
\r
328 d = (d << 30) | (d >> 2);
\r
330 a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[59];
\r
331 c = (c << 30) | (c >> 2);
\r
335 // ---- Round 4 --------
\r
337 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[60];
\r
338 b = (b << 30) | (b >> 2);
\r
340 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[61];
\r
341 a = (a << 30) | (a >> 2);
\r
343 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[62];
\r
344 e = (e << 30) | (e >> 2);
\r
346 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[63];
\r
347 d = (d << 30) | (d >> 2);
\r
349 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[64];
\r
350 c = (c << 30) | (c >> 2);
\r
352 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[65];
\r
353 b = (b << 30) | (b >> 2);
\r
355 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[66];
\r
356 a = (a << 30) | (a >> 2);
\r
358 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[67];
\r
359 e = (e << 30) | (e >> 2);
\r
361 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[68];
\r
362 d = (d << 30) | (d >> 2);
\r
364 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[69];
\r
365 c = (c << 30) | (c >> 2);
\r
367 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[70];
\r
368 b = (b << 30) | (b >> 2);
\r
370 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[71];
\r
371 a = (a << 30) | (a >> 2);
\r
373 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[72];
\r
374 e = (e << 30) | (e >> 2);
\r
376 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[73];
\r
377 d = (d << 30) | (d >> 2);
\r
379 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[74];
\r
380 c = (c << 30) | (c >> 2);
\r
382 e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[75];
\r
383 b = (b << 30) | (b >> 2);
\r
385 d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[76];
\r
386 a = (a << 30) | (a >> 2);
\r
388 c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[77];
\r
389 e = (e << 30) | (e >> 2);
\r
391 b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[78];
\r
392 d = (d << 30) | (d >> 2);
\r
394 a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[79];
\r
395 c = (c << 30) | (c >> 2);
\r
406 /// Pads and then processes the final block.
\r
409 /// <param name="inputBuffer">Buffer to grab data from.</param>
\r
410 /// <param name="inputOffset">Position in buffer in bytes to get data from.</param>
\r
411 /// <param name="inputCount">How much data in bytes in the buffer to use.</param>
\r
412 private void ProcessFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) {
\r
418 paddingSize = (int)(56 - (inputCount + count) % BLOCK_SIZE_BYTES);
\r
420 if (paddingSize < 1)
\r
421 paddingSize += BLOCK_SIZE_BYTES;
\r
423 fooBuffer = new byte[inputCount+paddingSize+8];
\r
425 for (i=0; i<inputCount; i++) {
\r
426 fooBuffer[i] = inputBuffer[i+inputOffset];
\r
429 fooBuffer[inputCount] = 0x80;
\r
430 for (i=inputCount+1; i<inputCount+paddingSize; i++) {
\r
431 fooBuffer[i] = 0x00;
\r
434 size = (uint)(count+inputCount);
\r
435 size *= 8; // I deal in bytes. They algorythm deals in bits.
\r
437 fooBuffer[inputCount+paddingSize] = 0x00;
\r
438 fooBuffer[inputCount+paddingSize+1] = 0x00;
\r
439 fooBuffer[inputCount+paddingSize+2] = 0x00;
\r
440 fooBuffer[inputCount+paddingSize+3] = 0x00;
\r
442 fooBuffer[inputCount+paddingSize+4] = (byte)((size) >> 24);
\r
443 fooBuffer[inputCount+paddingSize+5] = (byte)((size) >> 16);
\r
444 fooBuffer[inputCount+paddingSize+6] = (byte)((size) >> 8);
\r
445 fooBuffer[inputCount+paddingSize+7] = (byte)((size) >> 0);
\r
447 ProcessBlock(fooBuffer, 0);
\r
449 if (inputCount+paddingSize+8 == 128) {
\r
450 ProcessBlock(fooBuffer, 64);
\r