| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- //
- // System.Security.Cryptography MD5CryptoServiceProvider Class implementation
- //
- // Authors:
- // Matthew S. Ford ([email protected])
- //
- // Copyright 2001 by Matthew S. Ford.
- //
- using System.Security.Cryptography;
- namespace System.Security.Cryptography {
- /// <summary>
- /// C# implementation of the MD5 cryptographic hash function.
- /// </summary>
- public class MD5CryptoServiceProvider : MD5 {
- private const int BLOCK_SIZE_BYTES = 64;
- private const int HASH_SIZE_BYTES = 16;
- private const int HASH_SIZE_BITS = 128;
- protected uint[] _H;
- protected uint 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.
-
- /// <summary>
- /// Creates a new MD5CryptoServiceProvider.
- /// </summary>
- public MD5CryptoServiceProvider () {
- _H = new uint[4];
- HashSizeValue = HASH_SIZE_BITS;
- _ProcessingBuffer = new byte[BLOCK_SIZE_BYTES];
- Initialize();
- }
- /// <summary>
- /// Drives the hashing function.
- /// </summary>
- /// <param name="rgb">Byte array containing the data to hash.</param>
- /// <param name="start">Where in the input buffer to start.</param>
- /// <param name="size">Size in bytes of the data in the buffer to hash.</param>
- protected override void HashCore (byte[] rgb, int start, int size) {
- int i;
- State = 1;
- if (_ProcessingBufferCount != 0) {
- if (size < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
- System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, size);
- _ProcessingBufferCount += size;
- return;
- }
- else {
- i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
- System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, i);
- ProcessBlock (_ProcessingBuffer, 0);
- _ProcessingBufferCount = 0;
- start += i;
- size -= i;
- }
- }
- for (i=0; i<size-size%BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
- ProcessBlock (rgb, start+i);
- }
- if (size%BLOCK_SIZE_BYTES != 0) {
- System.Buffer.BlockCopy (rgb, size-size%BLOCK_SIZE_BYTES+start, _ProcessingBuffer, 0, size%BLOCK_SIZE_BYTES);
- _ProcessingBufferCount = size%BLOCK_SIZE_BYTES;
- }
- }
-
- /// <summary>
- /// This finalizes the hash. Takes the data from the chaining variables and returns it.
- /// </summary>
- protected override byte[] HashFinal () {
- byte[] hash = new byte[16];
- int i, j;
- ProcessFinalBlock(_ProcessingBuffer, 0, _ProcessingBufferCount);
- for (i=0; i<4; i++) {
- for (j=0; j<4; j++) {
- hash[i*4+j] = (byte)(_H[i] >> j*8);
- }
- }
- return hash;
- }
- /// <summary>
- /// Resets the class after use. Called automatically after hashing is done.
- /// </summary>
- public override void Initialize () {
- count = 0;
- _ProcessingBufferCount = 0;
- _H[0] = 0x67452301;
- _H[1] = 0xefcdab89;
- _H[2] = 0x98badcfe;
- _H[3] = 0x10325476;
- }
- /// <summary>
- /// This is the meat of the hash function. It is what processes each block one at a time.
- /// </summary>
- /// <param name="inputBuffer">Byte array to process data from.</param>
- /// <param name="inputOffset">Where in the byte array to start processing.</param>
- private void ProcessBlock(byte[] inputBuffer, int inputOffset) {
- uint[] buff = new uint[16];
- uint a, b, c, d;
- int i;
-
- count += BLOCK_SIZE_BYTES;
-
- for (i=0; i<16; i++) {
- buff[i] = (uint)(inputBuffer[inputOffset+4*i])
- | (((uint)(inputBuffer[inputOffset+4*i+1])) << 8)
- | (((uint)(inputBuffer[inputOffset+4*i+2])) << 16)
- | (((uint)(inputBuffer[inputOffset+4*i+3])) << 24);
- }
-
- a = _H[0];
- b = _H[1];
- c = _H[2];
- d = _H[3];
-
- // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
- // Possibly roll up if this changes.
- // ---- Round 1 --------
- a += (((c ^ d) & b) ^ d) + (uint) Constants.C0 + buff [0];
- a = (a << 7) | (a >> 25);
- a += b;
- d += (((b ^ c) & a) ^ c) + (uint) Constants.C1 + buff [1];
- d = (d << 12) | (d >> 20);
- d += a;
- c += (((a ^ b) & d) ^ b) + (uint) Constants.C2 + buff [2];
- c = (c << 17) | (c >> 15);
- c += d;
- b += (((d ^ a) & c) ^ a) + (uint) Constants.C3 + buff [3];
- b = (b << 22) | (b >> 10);
- b += c;
- a += (((c ^ d) & b) ^ d) + (uint) Constants.C4 + buff [4];
- a = (a << 7) | (a >> 25);
- a += b;
- d += (((b ^ c) & a) ^ c) + (uint) Constants.C5 + buff [5];
- d = (d << 12) | (d >> 20);
- d += a;
- c += (((a ^ b) & d) ^ b) + (uint) Constants.C6 + buff [6];
- c = (c << 17) | (c >> 15);
- c += d;
- b += (((d ^ a) & c) ^ a) + (uint) Constants.C7 + buff [7];
- b = (b << 22) | (b >> 10);
- b += c;
- a += (((c ^ d) & b) ^ d) + (uint) Constants.C8 + buff [8];
- a = (a << 7) | (a >> 25);
- a += b;
- d += (((b ^ c) & a) ^ c) + (uint) Constants.C9 + buff [9];
- d = (d << 12) | (d >> 20);
- d += a;
- c += (((a ^ b) & d) ^ b) + (uint) Constants.C10 + buff [10];
- c = (c << 17) | (c >> 15);
- c += d;
- b += (((d ^ a) & c) ^ a) + (uint) Constants.C11 + buff [11];
- b = (b << 22) | (b >> 10);
- b += c;
- a += (((c ^ d) & b) ^ d) + (uint) Constants.C12 + buff [12];
- a = (a << 7) | (a >> 25);
- a += b;
- d += (((b ^ c) & a) ^ c) + (uint) Constants.C13 + buff [13];
- d = (d << 12) | (d >> 20);
- d += a;
- c += (((a ^ b) & d) ^ b) + (uint) Constants.C14 + buff [14];
- c = (c << 17) | (c >> 15);
- c += d;
- b += (((d ^ a) & c) ^ a) + (uint) Constants.C15 + buff [15];
- b = (b << 22) | (b >> 10);
- b += c;
- // ---- Round 2 --------
-
- a += (((b ^ c) & d) ^ c) + (uint) Constants.C16 + buff [1];
- a = (a << 5) | (a >> 27);
- a += b;
- d += (((a ^ b) & c) ^ b) + (uint) Constants.C17 + buff [6];
- d = (d << 9) | (d >> 23);
- d += a;
- c += (((d ^ a) & b) ^ a) + (uint) Constants.C18 + buff [11];
- c = (c << 14) | (c >> 18);
- c += d;
- b += (((c ^ d) & a) ^ d) + (uint) Constants.C19 + buff [0];
- b = (b << 20) | (b >> 12);
- b += c;
- a += (((b ^ c) & d) ^ c) + (uint) Constants.C20 + buff [5];
- a = (a << 5) | (a >> 27);
- a += b;
- d += (((a ^ b) & c) ^ b) + (uint) Constants.C21 + buff [10];
- d = (d << 9) | (d >> 23);
- d += a;
- c += (((d ^ a) & b) ^ a) + (uint) Constants.C22 + buff [15];
- c = (c << 14) | (c >> 18);
- c += d;
- b += (((c ^ d) & a) ^ d) + (uint) Constants.C23 + buff [4];
- b = (b << 20) | (b >> 12);
- b += c;
- a += (((b ^ c) & d) ^ c) + (uint) Constants.C24 + buff [9];
- a = (a << 5) | (a >> 27);
- a += b;
- d += (((a ^ b) & c) ^ b) + (uint) Constants.C25 + buff [14];
- d = (d << 9) | (d >> 23);
- d += a;
- c += (((d ^ a) & b) ^ a) + (uint) Constants.C26 + buff [3];
- c = (c << 14) | (c >> 18);
- c += d;
- b += (((c ^ d) & a) ^ d) + (uint) Constants.C27 + buff [8];
- b = (b << 20) | (b >> 12);
- b += c;
- a += (((b ^ c) & d) ^ c) + (uint) Constants.C28 + buff [13];
- a = (a << 5) | (a >> 27);
- a += b;
- d += (((a ^ b) & c) ^ b) + (uint) Constants.C29 + buff [2];
- d = (d << 9) | (d >> 23);
- d += a;
- c += (((d ^ a) & b) ^ a) + (uint) Constants.C30 + buff [7];
- c = (c << 14) | (c >> 18);
- c += d;
- b += (((c ^ d) & a) ^ d) + (uint) Constants.C31 + buff [12];
- b = (b << 20) | (b >> 12);
- b += c;
- // ---- Round 3 --------
-
- a += (b ^ c ^ d) + (uint) Constants.C32 + buff [5];
- a = (a << 4) | (a >> 28);
- a += b;
- d += (a ^ b ^ c) + (uint) Constants.C33 + buff [8];
- d = (d << 11) | (d >> 21);
- d += a;
- c += (d ^ a ^ b) + (uint) Constants.C34 + buff [11];
- c = (c << 16) | (c >> 16);
- c += d;
- b += (c ^ d ^ a) + (uint) Constants.C35 + buff [14];
- b = (b << 23) | (b >> 9);
- b += c;
- a += (b ^ c ^ d) + (uint) Constants.C36 + buff [1];
- a = (a << 4) | (a >> 28);
- a += b;
- d += (a ^ b ^ c) + (uint) Constants.C37 + buff [4];
- d = (d << 11) | (d >> 21);
- d += a;
- c += (d ^ a ^ b) + (uint) Constants.C38 + buff [7];
- c = (c << 16) | (c >> 16);
- c += d;
- b += (c ^ d ^ a) + (uint) Constants.C39 + buff [10];
- b = (b << 23) | (b >> 9);
- b += c;
- a += (b ^ c ^ d) + (uint) Constants.C40 + buff [13];
- a = (a << 4) | (a >> 28);
- a += b;
- d += (a ^ b ^ c) + (uint) Constants.C41 + buff [0];
- d = (d << 11) | (d >> 21);
- d += a;
- c += (d ^ a ^ b) + (uint) Constants.C42 + buff [3];
- c = (c << 16) | (c >> 16);
- c += d;
- b += (c ^ d ^ a) + (uint) Constants.C43 + buff [6];
- b = (b << 23) | (b >> 9);
- b += c;
- a += (b ^ c ^ d) + (uint) Constants.C44 + buff [9];
- a = (a << 4) | (a >> 28);
- a += b;
- d += (a ^ b ^ c) + (uint) Constants.C45 + buff [12];
- d = (d << 11) | (d >> 21);
- d += a;
- c += (d ^ a ^ b) + (uint) Constants.C46 + buff [15];
- c = (c << 16) | (c >> 16);
- c += d;
- b += (c ^ d ^ a) + (uint) Constants.C47 + buff [2];
- b = (b << 23) | (b >> 9);
- b += c;
- // ---- Round 4 --------
-
- a += (((~d) | b) ^ c) + (uint) Constants.C48 + buff [0];
- a = (a << 6) | (a >> 26);
- a += b;
- d += (((~c) | a) ^ b) + (uint) Constants.C49 + buff [7];
- d = (d << 10) | (d >> 22);
- d += a;
- c += (((~b) | d) ^ a) + (uint) Constants.C50 + buff [14];
- c = (c << 15) | (c >> 17);
- c += d;
- b += (((~a) | c) ^ d) + (uint) Constants.C51 + buff [5];
- b = (b << 21) | (b >> 11);
- b += c;
- a += (((~d) | b) ^ c) + (uint) Constants.C52 + buff [12];
- a = (a << 6) | (a >> 26);
- a += b;
- d += (((~c) | a) ^ b) + (uint) Constants.C53 + buff [3];
- d = (d << 10) | (d >> 22);
- d += a;
- c += (((~b) | d) ^ a) + (uint) Constants.C54 + buff [10];
- c = (c << 15) | (c >> 17);
- c += d;
- b += (((~a) | c) ^ d) + (uint) Constants.C55 + buff [1];
- b = (b << 21) | (b >> 11);
- b += c;
- a += (((~d) | b) ^ c) + (uint) Constants.C56 + buff [8];
- a = (a << 6) | (a >> 26);
- a += b;
- d += (((~c) | a) ^ b) + (uint) Constants.C57 + buff [15];
- d = (d << 10) | (d >> 22);
- d += a;
- c += (((~b) | d) ^ a) + (uint) Constants.C58 + buff [6];
- c = (c << 15) | (c >> 17);
- c += d;
- b += (((~a) | c) ^ d) + (uint) Constants.C59 + buff [13];
- b = (b << 21) | (b >> 11);
- b += c;
- a += (((~d) | b) ^ c) + (uint) Constants.C60 + buff [4];
- a = (a << 6) | (a >> 26);
- a += b;
- d += (((~c) | a) ^ b) + (uint) Constants.C61 + buff [11];
- d = (d << 10) | (d >> 22);
- d += a;
- c += (((~b) | d) ^ a) + (uint) Constants.C62 + buff [2];
- c = (c << 15) | (c >> 17);
- c += d;
- b += (((~a) | c) ^ d) + (uint) Constants.C63 + buff [9];
- b = (b << 21) | (b >> 11);
- b += c;
- _H[0] += a;
- _H[1] += b;
- _H[2] += c;
- _H[3] += d;
- }
-
- /// <summary>
- /// Pads and then processes the final block.
- /// </summary>
- /// <param name="inputBuffer">Buffer to grab data from.</param>
- /// <param name="inputOffset">Position in buffer in bytes to get data from.</param>
- /// <param name="inputCount">How much data in bytes in the buffer to use.</param>
- private void ProcessFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) {
- byte[] fooBuffer;
- int paddingSize;
- int i;
- uint size;
- paddingSize = (int)(56 - (inputCount + count) % BLOCK_SIZE_BYTES);
- if (paddingSize < 1)
- paddingSize += BLOCK_SIZE_BYTES;
- fooBuffer = new byte[inputCount+paddingSize+8];
- for (i=0; i<inputCount; i++) {
- fooBuffer[i] = inputBuffer[i+inputOffset];
- }
- fooBuffer[inputCount] = 0x80;
- for (i=inputCount+1; i<inputCount+paddingSize; i++) {
- fooBuffer[i] = 0x00;
- }
- size = (uint)(count+inputCount);
- size *= 8;
- fooBuffer[inputCount+paddingSize] = (byte)((size) >> 0);
- fooBuffer[inputCount+paddingSize+1] = (byte)((size) >> 8);
- fooBuffer[inputCount+paddingSize+2] = (byte)((size) >> 16);
- fooBuffer[inputCount+paddingSize+3] = (byte)((size) >> 24);
- fooBuffer[inputCount+paddingSize+4] = 0x00;
- fooBuffer[inputCount+paddingSize+5] = 0x00;
- fooBuffer[inputCount+paddingSize+6] = 0x00;
- fooBuffer[inputCount+paddingSize+7] = 0x00;
- ProcessBlock(fooBuffer, 0);
- if (inputCount+paddingSize+8 == 128) {
- ProcessBlock(fooBuffer, 64);
- }
- }
-
- private enum Constants : uint {
- C0 = 0xd76aa478, C1 = 0xe8c7b756, C2 = 0x242070db,
- C3 = 0xc1bdceee, C4 = 0xf57c0faf, C5 = 0x4787c62a,
- C6 = 0xa8304613, C7 = 0xfd469501, C8 = 0x698098d8,
- C9 = 0x8b44f7af,C10 = 0xffff5bb1,C11 = 0x895cd7be,
- C12 = 0x6b901122,C13 = 0xfd987193,C14 = 0xa679438e,
- C15 = 0x49b40821,C16 = 0xf61e2562,C17 = 0xc040b340,
- C18 = 0x265e5a51,C19 = 0xe9b6c7aa,C20 = 0xd62f105d,
- C21 = 0x02441453,C22 = 0xd8a1e681,C23 = 0xe7d3fbc8,
- C24 = 0x21e1cde6,C25 = 0xc33707d6,C26 = 0xf4d50d87,
- C27 = 0x455a14ed,C28 = 0xa9e3e905,C29 = 0xfcefa3f8,
- C30 = 0x676f02d9,C31 = 0x8d2a4c8a,C32 = 0xfffa3942,
- C33 = 0x8771f681,C34 = 0x6d9d6122,C35 = 0xfde5380c,
- C36 = 0xa4beea44,C37 = 0x4bdecfa9,C38 = 0xf6bb4b60,
- C39 = 0xbebfbc70,C40 = 0x289b7ec6,C41 = 0xeaa127fa,
- C42 = 0xd4ef3085,C43 = 0x04881d05,C44 = 0xd9d4d039,
- C45 = 0xe6db99e5,C46 = 0x1fa27cf8,C47 = 0xc4ac5665,
- C48 = 0xf4292244,C49 = 0x432aff97,C50 = 0xab9423a7,
- C51 = 0xfc93a039,C52 = 0x655b59c3,C53 = 0x8f0ccc92,
- C54 = 0xffeff47d,C55 = 0x85845dd1,C56 = 0x6fa87e4f,
- C57 = 0xfe2ce6e0,C58 = 0xa3014314,C59 = 0x4e0811a1,
- C60 = 0xf7537e82,C61 = 0xbd3af235,C62 = 0x2ad7d2bb,
- C63 = 0xeb86d391
- }
- }
- }
|