public static unsafe void GetDigest(byte *input, int length, Md5Digest *digest) { const int bytesPerBlock = 64; var blocksCount = (length + 8) / bytesPerBlock + 1; digest->A = 0x67452301; digest->B = 0xefcdab89; digest->C = 0x98badcfe; digest->D = 0x10325476; var paddingBlockData = default(Block); for (var blockIndex = 0; blockIndex < blocksCount; blockIndex++) { var offset = blockIndex * bytesPerBlock; var blockEnd = offset + bytesPerBlock; uint *blockPtr; if (blockEnd > length) // we're going to run out of input on this block { if (offset >= length) // we're already totally past the input at this point - this block is just padding, and definitely the final block { if (offset == length) { // the end of input perfectly lined up with a block - so this is the start of padding *(byte *)&paddingBlockData = 0x80; } else { // this is not the start of padding, so we need to clear out any data from the first padding block paddingBlockData = default(Block); } paddingBlockData.SetOriginalLength(length); } else // there is still some input left to consume before we get to padding { var bytesRemaining = bytesPerBlock - (blockEnd - length); var paddingPtr = (byte *)&paddingBlockData; Common.UnsafeMemoryCopy(&input[offset], paddingPtr, bytesRemaining); // add bit paddingPtr[bytesRemaining] = 0x80; // check if we can add the length if (bytesPerBlock - (bytesRemaining + 1) >= 8) { paddingBlockData.SetOriginalLength(length); } } blockPtr = (uint *)&paddingBlockData; } else { blockPtr = (uint *)&input[offset]; } var a = digest->A; var b = digest->B; var c = digest->C; var d = digest->D; uint f, dTemp; // 0 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xd76aa478 + blockPtr[0], 7); a = dTemp; // 1 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xe8c7b756 + blockPtr[1], 12); a = dTemp; // 2 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x242070db + blockPtr[2], 17); a = dTemp; // 3 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xc1bdceee + blockPtr[3], 22); a = dTemp; // 4 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xf57c0faf + blockPtr[4], 7); a = dTemp; // 5 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x4787c62a + blockPtr[5], 12); a = dTemp; // 6 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xa8304613 + blockPtr[6], 17); a = dTemp; // 7 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xfd469501 + blockPtr[7], 22); a = dTemp; // 8 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x698098d8 + blockPtr[8], 7); a = dTemp; // 9 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x8b44f7af + blockPtr[9], 12); a = dTemp; // 10 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xffff5bb1 + blockPtr[10], 17); a = dTemp; // 11 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x895cd7be + blockPtr[11], 22); a = dTemp; // 12 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x6b901122 + blockPtr[12], 7); a = dTemp; // 13 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xfd987193 + blockPtr[13], 12); a = dTemp; // 14 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xa679438e + blockPtr[14], 17); a = dTemp; // 15 f = (b & c) | (~b & d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x49b40821 + blockPtr[15], 22); a = dTemp; // 16 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xf61e2562 + blockPtr[(5 * 16 + 1) % 16], 5); a = dTemp; // 17 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xc040b340 + blockPtr[(5 * 17 + 1) % 16], 9); a = dTemp; // 18 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x265e5a51 + blockPtr[(5 * 18 + 1) % 16], 14); a = dTemp; // 19 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xe9b6c7aa + blockPtr[(5 * 19 + 1) % 16], 20); a = dTemp; // 20 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xd62f105d + blockPtr[(5 * 20 + 1) % 16], 5); a = dTemp; // 21 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x2441453 + blockPtr[(5 * 21 + 1) % 16], 9); a = dTemp; // 22 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xd8a1e681 + blockPtr[(5 * 22 + 1) % 16], 14); a = dTemp; // 23 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xe7d3fbc8 + blockPtr[(5 * 23 + 1) % 16], 20); a = dTemp; // 24 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x21e1cde6 + blockPtr[(5 * 24 + 1) % 16], 5); a = dTemp; // 25 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xc33707d6 + blockPtr[(5 * 25 + 1) % 16], 9); a = dTemp; // 26 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xf4d50d87 + blockPtr[(5 * 26 + 1) % 16], 14); a = dTemp; // 27 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x455a14ed + blockPtr[(5 * 27 + 1) % 16], 20); a = dTemp; // 28 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xa9e3e905 + blockPtr[(5 * 28 + 1) % 16], 5); a = dTemp; // 29 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xfcefa3f8 + blockPtr[(5 * 29 + 1) % 16], 9); a = dTemp; // 30 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x676f02d9 + blockPtr[(5 * 30 + 1) % 16], 14); a = dTemp; // 31 f = (d & b) | (~d & c); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x8d2a4c8a + blockPtr[(5 * 31 + 1) % 16], 20); a = dTemp; // 32 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xfffa3942 + blockPtr[(3 * 32 + 5) % 16], 4); a = dTemp; // 33 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x8771f681 + blockPtr[(3 * 33 + 5) % 16], 11); a = dTemp; // 34 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x6d9d6122 + blockPtr[(3 * 34 + 5) % 16], 16); a = dTemp; // 35 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xfde5380c + blockPtr[(3 * 35 + 5) % 16], 23); a = dTemp; // 36 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xa4beea44 + blockPtr[(3 * 36 + 5) % 16], 4); a = dTemp; // 37 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x4bdecfa9 + blockPtr[(3 * 37 + 5) % 16], 11); a = dTemp; // 38 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xf6bb4b60 + blockPtr[(3 * 38 + 5) % 16], 16); a = dTemp; // 39 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xbebfbc70 + blockPtr[(3 * 39 + 5) % 16], 23); a = dTemp; // 40 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x289b7ec6 + blockPtr[(3 * 40 + 5) % 16], 4); a = dTemp; // 41 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xeaa127fa + blockPtr[(3 * 41 + 5) % 16], 11); a = dTemp; // 42 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xd4ef3085 + blockPtr[(3 * 42 + 5) % 16], 16); a = dTemp; // 43 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x4881d05 + blockPtr[(3 * 43 + 5) % 16], 23); a = dTemp; // 44 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xd9d4d039 + blockPtr[(3 * 44 + 5) % 16], 4); a = dTemp; // 45 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xe6db99e5 + blockPtr[(3 * 45 + 5) % 16], 11); a = dTemp; // 46 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x1fa27cf8 + blockPtr[(3 * 46 + 5) % 16], 16); a = dTemp; // 47 f = b ^ c ^ d; dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xc4ac5665 + blockPtr[(3 * 47 + 5) % 16], 23); a = dTemp; // 48 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xf4292244 + blockPtr[(7 * 48) % 16], 6); a = dTemp; // 49 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x432aff97 + blockPtr[(7 * 49) % 16], 10); a = dTemp; // 50 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xab9423a7 + blockPtr[(7 * 50) % 16], 15); a = dTemp; // 51 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xfc93a039 + blockPtr[(7 * 51) % 16], 21); a = dTemp; // 52 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x655b59c3 + blockPtr[(7 * 52) % 16], 6); a = dTemp; // 53 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x8f0ccc92 + blockPtr[(7 * 53) % 16], 10); a = dTemp; // 54 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xffeff47d + blockPtr[(7 * 54) % 16], 15); a = dTemp; // 55 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x85845dd1 + blockPtr[(7 * 55) % 16], 21); a = dTemp; // 56 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x6fa87e4f + blockPtr[(7 * 56) % 16], 6); a = dTemp; // 57 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xfe2ce6e0 + blockPtr[(7 * 57) % 16], 10); a = dTemp; // 58 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xa3014314 + blockPtr[(7 * 58) % 16], 15); a = dTemp; // 59 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x4e0811a1 + blockPtr[(7 * 59) % 16], 21); a = dTemp; // 60 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xf7537e82 + blockPtr[(7 * 60) % 16], 6); a = dTemp; // 61 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xbd3af235 + blockPtr[(7 * 61) % 16], 10); a = dTemp; // 62 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0x2ad7d2bb + blockPtr[(7 * 62) % 16], 15); a = dTemp; // 63 f = c ^ (b | ~d); dTemp = d; d = c; c = b; b += LeftRotate(a + f + 0xeb86d391 + blockPtr[(7 * 63) % 16], 21); a = dTemp; digest->A += a; digest->B += b; digest->C += c; digest->D += d; } }
public static unsafe void GetDigest(byte *input, int length, Md5Digest *digest) { const int bytesPerBlock = 64; var blocksCount = (length + 8) / bytesPerBlock + 1; digest->A = 0x67452301; digest->B = 0xefcdab89; digest->C = 0x98badcfe; digest->D = 0x10325476; var paddingBlockData = default(Block); for (var blockIndex = 0; blockIndex < blocksCount; blockIndex++) { var offset = blockIndex * bytesPerBlock; var blockEnd = offset + bytesPerBlock; uint *blockPtr; if (blockEnd > length) // we're going to run out of input on this block { if (offset >= length) // we're already totally past the input at this point - this block is just padding, and definitely the final block { if (offset == length) { // the end of input perfectly lined up with a block - so this is the start of padding *(byte *)&paddingBlockData = 0x80; } else { // this is not the start of padding, so we need to clear out any data from the first padding block paddingBlockData = default(Block); } paddingBlockData.SetOriginalLength(length); } else // there is still some input left to consume before we get to padding { var bytesRemaining = bytesPerBlock - (blockEnd - length); var paddingPtr = (byte *)&paddingBlockData; Common.UnsafeMemoryCopy(&input[offset], paddingPtr, bytesRemaining); // add bit paddingPtr[bytesRemaining] = 0x80; // check if we can add the length if (bytesPerBlock - (bytesRemaining + 1) >= 8) { paddingBlockData.SetOriginalLength(length); } } blockPtr = (uint *)&paddingBlockData; } else { blockPtr = (uint *)&input[offset]; } var a = digest->A; var b = digest->B; var c = digest->C; var d = digest->D; uint f; // 0 (a, b, c, d) f = (c ^ d) & b ^ d; a += f + 0xd76aa478 + blockPtr[0]; a = b + ((a << 7) | (a >> (32 - 7))); // 1 (d, a, b, c) f = (b ^ c) & a ^ c; d += f + 0xe8c7b756 + blockPtr[1]; d = a + ((d << 12) | (d >> (32 - 12))); // 2 (c, d, a, b) f = (a ^ b) & d ^ b; c += f + 0x242070db + blockPtr[2]; c = d + ((c << 17) | (c >> (32 - 17))); // 3 (b, c, d, a) f = (d ^ a) & c ^ a; b += f + 0xc1bdceee + blockPtr[3]; b = c + ((b << 22) | (b >> (32 - 22))); // 4 (a, b, c, d) f = (c ^ d) & b ^ d; a += f + 0xf57c0faf + blockPtr[4]; a = b + ((a << 7) | (a >> (32 - 7))); // 5 (d, a, b, c) f = (b ^ c) & a ^ c; d += f + 0x4787c62a + blockPtr[5]; d = a + ((d << 12) | (d >> (32 - 12))); // 6 (c, d, a, b) f = (a ^ b) & d ^ b; c += f + 0xa8304613 + blockPtr[6]; c = d + ((c << 17) | (c >> (32 - 17))); // 7 (b, c, d, a) f = (d ^ a) & c ^ a; b += f + 0xfd469501 + blockPtr[7]; b = c + ((b << 22) | (b >> (32 - 22))); // 8 (a, b, c, d) f = (c ^ d) & b ^ d; a += f + 0x698098d8 + blockPtr[8]; a = b + ((a << 7) | (a >> (32 - 7))); // 9 (d, a, b, c) f = (b ^ c) & a ^ c; d += f + 0x8b44f7af + blockPtr[9]; d = a + ((d << 12) | (d >> (32 - 12))); // 10 (c, d, a, b) f = (a ^ b) & d ^ b; c += f + 0xffff5bb1 + blockPtr[10]; c = d + ((c << 17) | (c >> (32 - 17))); // 11 (b, c, d, a) f = (d ^ a) & c ^ a; b += f + 0x895cd7be + blockPtr[11]; b = c + ((b << 22) | (b >> (32 - 22))); // 12 (a, b, c, d) f = (c ^ d) & b ^ d; a += f + 0x6b901122 + blockPtr[12]; a = b + ((a << 7) | (a >> (32 - 7))); // 13 (d, a, b, c) f = (b ^ c) & a ^ c; d += f + 0xfd987193 + blockPtr[13]; d = a + ((d << 12) | (d >> (32 - 12))); // 14 (c, d, a, b) f = (a ^ b) & d ^ b; c += f + 0xa679438e + blockPtr[14]; c = d + ((c << 17) | (c >> (32 - 17))); // 15 (b, c, d, a) f = (d ^ a) & c ^ a; b += f + 0x49b40821 + blockPtr[15]; b = c + ((b << 22) | (b >> (32 - 22))); // 16 (a, b, c, d) f = (b ^ c) & d ^ c; a += f + 0xf61e2562 + blockPtr[(5 * 16 + 1) & 0xf]; a = b + ((a << 5) | (a >> (32 - 5))); // 17 (d, a, b, c) f = (a ^ b) & c ^ b; d += f + 0xc040b340 + blockPtr[(5 * 17 + 1) & 0xf]; d = a + ((d << 9) | (d >> (32 - 9))); // 18 (c, d, a, b) f = (d ^ a) & b ^ a; c += f + 0x265e5a51 + blockPtr[(5 * 18 + 1) & 0xf]; c = d + ((c << 14) | (c >> (32 - 14))); // 19 (b, c, d, a) f = (c ^ d) & a ^ d; b += f + 0xe9b6c7aa + blockPtr[(5 * 19 + 1) & 0xf]; b = c + ((b << 20) | (b >> (32 - 20))); // 20 (a, b, c, d) f = (b ^ c) & d ^ c; a += f + 0xd62f105d + blockPtr[(5 * 20 + 1) & 0xf]; a = b + ((a << 5) | (a >> (32 - 5))); // 21 (d, a, b, c) f = (a ^ b) & c ^ b; d += f + 0x2441453 + blockPtr[(5 * 21 + 1) & 0xf]; d = a + ((d << 9) | (d >> (32 - 9))); // 22 (c, d, a, b) f = (d ^ a) & b ^ a; c += f + 0xd8a1e681 + blockPtr[(5 * 22 + 1) & 0xf]; c = d + ((c << 14) | (c >> (32 - 14))); // 23 (b, c, d, a) f = (c ^ d) & a ^ d; b += f + 0xe7d3fbc8 + blockPtr[(5 * 23 + 1) & 0xf]; b = c + ((b << 20) | (b >> (32 - 20))); // 24 (a, b, c, d) f = (b ^ c) & d ^ c; a += f + 0x21e1cde6 + blockPtr[(5 * 24 + 1) & 0xf]; a = b + ((a << 5) | (a >> (32 - 5))); // 25 (d, a, b, c) f = (a ^ b) & c ^ b; d += f + 0xc33707d6 + blockPtr[(5 * 25 + 1) & 0xf]; d = a + ((d << 9) | (d >> (32 - 9))); // 26 (c, d, a, b) f = (d ^ a) & b ^ a; c += f + 0xf4d50d87 + blockPtr[(5 * 26 + 1) & 0xf]; c = d + ((c << 14) | (c >> (32 - 14))); // 27 (b, c, d, a) f = (c ^ d) & a ^ d; b += f + 0x455a14ed + blockPtr[(5 * 27 + 1) & 0xf]; b = c + ((b << 20) | (b >> (32 - 20))); // 28 (a, b, c, d) f = (b ^ c) & d ^ c; a += f + 0xa9e3e905 + blockPtr[(5 * 28 + 1) & 0xf]; a = b + ((a << 5) | (a >> (32 - 5))); // 29 (d, a, b, c) f = (a ^ b) & c ^ b; d += f + 0xfcefa3f8 + blockPtr[(5 * 29 + 1) & 0xf]; d = a + ((d << 9) | (d >> (32 - 9))); // 30 (c, d, a, b) f = (d ^ a) & b ^ a; c += f + 0x676f02d9 + blockPtr[(5 * 30 + 1) & 0xf]; c = d + ((c << 14) | (c >> (32 - 14))); // 31 (b, c, d, a) f = (c ^ d) & a ^ d; b += f + 0x8d2a4c8a + blockPtr[(5 * 31 + 1) & 0xf]; b = c + ((b << 20) | (b >> (32 - 20))); // 32 (a, b, c, d) f = b ^ c ^ d; a += f + 0xfffa3942 + blockPtr[(3 * 32 + 5) & 0xf]; a = b + ((a << 4) | (a >> (32 - 4))); // 33 (d, a, b, c) f = a ^ b ^ c; d += f + 0x8771f681 + blockPtr[(3 * 33 + 5) & 0xf]; d = a + ((d << 11) | (d >> (32 - 11))); // 34 (c, d, a, b) f = d ^ a ^ b; c += f + 0x6d9d6122 + blockPtr[(3 * 34 + 5) & 0xf]; c = d + ((c << 16) | (c >> (32 - 16))); // 35 (b, c, d, a) f = c ^ d ^ a; b += f + 0xfde5380c + blockPtr[(3 * 35 + 5) & 0xf]; b = c + ((b << 23) | (b >> (32 - 23))); // 36 (a, b, c, d) f = b ^ c ^ d; a += f + 0xa4beea44 + blockPtr[(3 * 36 + 5) & 0xf]; a = b + ((a << 4) | (a >> (32 - 4))); // 37 (d, a, b, c) f = a ^ b ^ c; d += f + 0x4bdecfa9 + blockPtr[(3 * 37 + 5) & 0xf]; d = a + ((d << 11) | (d >> (32 - 11))); // 38 (c, d, a, b) f = d ^ a ^ b; c += f + 0xf6bb4b60 + blockPtr[(3 * 38 + 5) & 0xf]; c = d + ((c << 16) | (c >> (32 - 16))); // 39 (b, c, d, a) f = c ^ d ^ a; b += f + 0xbebfbc70 + blockPtr[(3 * 39 + 5) & 0xf]; b = c + ((b << 23) | (b >> (32 - 23))); // 40 (a, b, c, d) f = b ^ c ^ d; a += f + 0x289b7ec6 + blockPtr[(3 * 40 + 5) & 0xf]; a = b + ((a << 4) | (a >> (32 - 4))); // 41 (d, a, b, c) f = a ^ b ^ c; d += f + 0xeaa127fa + blockPtr[(3 * 41 + 5) & 0xf]; d = a + ((d << 11) | (d >> (32 - 11))); // 42 (c, d, a, b) f = d ^ a ^ b; c += f + 0xd4ef3085 + blockPtr[(3 * 42 + 5) & 0xf]; c = d + ((c << 16) | (c >> (32 - 16))); // 43 (b, c, d, a) f = c ^ d ^ a; b += f + 0x4881d05 + blockPtr[(3 * 43 + 5) & 0xf]; b = c + ((b << 23) | (b >> (32 - 23))); // 44 (a, b, c, d) f = b ^ c ^ d; a += f + 0xd9d4d039 + blockPtr[(3 * 44 + 5) & 0xf]; a = b + ((a << 4) | (a >> (32 - 4))); // 45 (d, a, b, c) f = a ^ b ^ c; d += f + 0xe6db99e5 + blockPtr[(3 * 45 + 5) & 0xf]; d = a + ((d << 11) | (d >> (32 - 11))); // 46 (c, d, a, b) f = d ^ a ^ b; c += f + 0x1fa27cf8 + blockPtr[(3 * 46 + 5) & 0xf]; c = d + ((c << 16) | (c >> (32 - 16))); // 47 (b, c, d, a) f = c ^ d ^ a; b += f + 0xc4ac5665 + blockPtr[(3 * 47 + 5) & 0xf]; b = c + ((b << 23) | (b >> (32 - 23))); // 48 (a, b, c, d) f = c ^ (b | ~d); a += f + 0xf4292244 + blockPtr[(7 * 48) & 0xf]; a = b + ((a << 6) | (a >> (32 - 6))); // 49 (d, a, b, c) f = b ^ (a | ~c); d += f + 0x432aff97 + blockPtr[(7 * 49) & 0xf]; d = a + ((d << 10) | (d >> (32 - 10))); // 50 (c, d, a, b) f = a ^ (d | ~b); c += f + 0xab9423a7 + blockPtr[(7 * 50) & 0xf]; c = d + ((c << 15) | (c >> (32 - 15))); // 51 (b, c, d, a) f = d ^ (c | ~a); b += f + 0xfc93a039 + blockPtr[(7 * 51) & 0xf]; b = c + ((b << 21) | (b >> (32 - 21))); // 52 (a, b, c, d) f = c ^ (b | ~d); a += f + 0x655b59c3 + blockPtr[(7 * 52) & 0xf]; a = b + ((a << 6) | (a >> (32 - 6))); // 53 (d, a, b, c) f = b ^ (a | ~c); d += f + 0x8f0ccc92 + blockPtr[(7 * 53) & 0xf]; d = a + ((d << 10) | (d >> (32 - 10))); // 54 (c, d, a, b) f = a ^ (d | ~b); c += f + 0xffeff47d + blockPtr[(7 * 54) & 0xf]; c = d + ((c << 15) | (c >> (32 - 15))); // 55 (b, c, d, a) f = d ^ (c | ~a); b += f + 0x85845dd1 + blockPtr[(7 * 55) & 0xf]; b = c + ((b << 21) | (b >> (32 - 21))); // 56 (a, b, c, d) f = c ^ (b | ~d); a += f + 0x6fa87e4f + blockPtr[(7 * 56) & 0xf]; a = b + ((a << 6) | (a >> (32 - 6))); // 57 (d, a, b, c) f = b ^ (a | ~c); d += f + 0xfe2ce6e0 + blockPtr[(7 * 57) & 0xf]; d = a + ((d << 10) | (d >> (32 - 10))); // 58 (c, d, a, b) f = a ^ (d | ~b); c += f + 0xa3014314 + blockPtr[(7 * 58) & 0xf]; c = d + ((c << 15) | (c >> (32 - 15))); // 59 (b, c, d, a) f = d ^ (c | ~a); b += f + 0x4e0811a1 + blockPtr[(7 * 59) & 0xf]; b = c + ((b << 21) | (b >> (32 - 21))); // 60 (a, b, c, d) f = c ^ (b | ~d); a += f + 0xf7537e82 + blockPtr[(7 * 60) & 0xf]; a = b + ((a << 6) | (a >> (32 - 6))); // 61 (d, a, b, c) f = b ^ (a | ~c); d += f + 0xbd3af235 + blockPtr[(7 * 61) & 0xf]; d = a + ((d << 10) | (d >> (32 - 10))); // 62 (c, d, a, b) f = a ^ (d | ~b); c += f + 0x2ad7d2bb + blockPtr[(7 * 62) & 0xf]; c = d + ((c << 15) | (c >> (32 - 15))); // 63 (b, c, d, a) f = d ^ (c | ~a); b += f + 0xeb86d391 + blockPtr[(7 * 63) & 0xf]; b = c + ((b << 21) | (b >> (32 - 21))); digest->A += a; digest->B += b; digest->C += c; digest->D += d; } }
public static unsafe void GetDigest(byte *input, int length, Md5Digest *digest) { const int bytesPerBlock = 64; var blocksCount = (length + 8) / bytesPerBlock + 1; digest->A = 0x67452301; digest->B = 0xefcdab89; digest->C = 0x98badcfe; digest->D = 0x10325476; var paddingBlockData = default(Block); for (var blockIndex = 0; blockIndex < blocksCount; blockIndex++) { var offset = blockIndex * bytesPerBlock; var blockEnd = offset + bytesPerBlock; uint *blockPtr; if (blockEnd > length) // we're going to run out of input on this block { if (offset >= length) // we're already totally past the input at this point - this block is just padding, and definitely the final block { if (offset == length) { // the end of input perfectly lined up with a block - so this is the start of padding *(byte *)&paddingBlockData = 0x80; } else { // this is not the start of padding, so we need to clear out any data from the first padding block paddingBlockData = default(Block); } paddingBlockData.SetOriginalLength(length); } else // there is still some input left to consume before we get to padding { var bytesRemaining = bytesPerBlock - (blockEnd - length); var paddingPtr = (byte *)&paddingBlockData; Common.UnsafeMemoryCopy(&input[offset], paddingPtr, bytesRemaining); // add bit paddingPtr[bytesRemaining] = 0x80; // check if we can add the length if (bytesPerBlock - (bytesRemaining + 1) >= 8) { paddingBlockData.SetOriginalLength(length); } } blockPtr = (uint *)&paddingBlockData; } else { blockPtr = (uint *)&input[offset]; } var a = digest->A; var b = digest->B; var c = digest->C; var d = digest->D; FF(ref a, b, c, d, blockPtr[0], 7, 0xd76aa478); // 0 FF(ref d, a, b, c, blockPtr[1], 12, 0xe8c7b756); // 1 FF(ref c, d, a, b, blockPtr[2], 17, 0x242070db); // 2 FF(ref b, c, d, a, blockPtr[3], 22, 0xc1bdceee); // 3 FF(ref a, b, c, d, blockPtr[4], 7, 0xf57c0faf); // 4 FF(ref d, a, b, c, blockPtr[5], 12, 0x4787c62a); // 5 FF(ref c, d, a, b, blockPtr[6], 17, 0xa8304613); // 6 FF(ref b, c, d, a, blockPtr[7], 22, 0xfd469501); // 7 FF(ref a, b, c, d, blockPtr[8], 7, 0x698098d8); // 8 FF(ref d, a, b, c, blockPtr[9], 12, 0x8b44f7af); // 9 FF(ref c, d, a, b, blockPtr[10], 17, 0xffff5bb1); // 10 FF(ref b, c, d, a, blockPtr[11], 22, 0x895cd7be); // 11 FF(ref a, b, c, d, blockPtr[12], 7, 0x6b901122); // 12 FF(ref d, a, b, c, blockPtr[13], 12, 0xfd987193); // 13 FF(ref c, d, a, b, blockPtr[14], 17, 0xa679438e); // 14 FF(ref b, c, d, a, blockPtr[15], 22, 0x49b40821); // 15 GG(ref a, b, c, d, blockPtr[(5 * 16 + 1) & 0xf], 5, 0xf61e2562); // 16 GG(ref d, a, b, c, blockPtr[(5 * 17 + 1) & 0xf], 9, 0xc040b340); // 17 GG(ref c, d, a, b, blockPtr[(5 * 18 + 1) & 0xf], 14, 0x265e5a51); // 18 GG(ref b, c, d, a, blockPtr[(5 * 19 + 1) & 0xf], 20, 0xe9b6c7aa); // 19 GG(ref a, b, c, d, blockPtr[(5 * 20 + 1) & 0xf], 5, 0xd62f105d); // 20 GG(ref d, a, b, c, blockPtr[(5 * 21 + 1) & 0xf], 9, 0x2441453); // 21 GG(ref c, d, a, b, blockPtr[(5 * 22 + 1) & 0xf], 14, 0xd8a1e681); // 22 GG(ref b, c, d, a, blockPtr[(5 * 23 + 1) & 0xf], 20, 0xe7d3fbc8); // 23 GG(ref a, b, c, d, blockPtr[(5 * 24 + 1) & 0xf], 5, 0x21e1cde6); // 24 GG(ref d, a, b, c, blockPtr[(5 * 25 + 1) & 0xf], 9, 0xc33707d6); // 25 GG(ref c, d, a, b, blockPtr[(5 * 26 + 1) & 0xf], 14, 0xf4d50d87); // 26 GG(ref b, c, d, a, blockPtr[(5 * 27 + 1) & 0xf], 20, 0x455a14ed); // 27 GG(ref a, b, c, d, blockPtr[(5 * 28 + 1) & 0xf], 5, 0xa9e3e905); // 28 GG(ref d, a, b, c, blockPtr[(5 * 29 + 1) & 0xf], 9, 0xfcefa3f8); // 29 GG(ref c, d, a, b, blockPtr[(5 * 30 + 1) & 0xf], 14, 0x676f02d9); // 30 GG(ref b, c, d, a, blockPtr[(5 * 31 + 1) & 0xf], 20, 0x8d2a4c8a); // 31 HH(ref a, b, c, d, blockPtr[(3 * 32 + 5) & 0xf], 4, 0xfffa3942); // 32 HH(ref d, a, b, c, blockPtr[(3 * 33 + 5) & 0xf], 11, 0x8771f681); // 33 HH(ref c, d, a, b, blockPtr[(3 * 34 + 5) & 0xf], 16, 0x6d9d6122); // 34 HH(ref b, c, d, a, blockPtr[(3 * 35 + 5) & 0xf], 23, 0xfde5380c); // 35 HH(ref a, b, c, d, blockPtr[(3 * 36 + 5) & 0xf], 4, 0xa4beea44); // 36 HH(ref d, a, b, c, blockPtr[(3 * 37 + 5) & 0xf], 11, 0x4bdecfa9); // 37 HH(ref c, d, a, b, blockPtr[(3 * 38 + 5) & 0xf], 16, 0xf6bb4b60); // 38 HH(ref b, c, d, a, blockPtr[(3 * 39 + 5) & 0xf], 23, 0xbebfbc70); // 39 HH(ref a, b, c, d, blockPtr[(3 * 40 + 5) & 0xf], 4, 0x289b7ec6); // 40 HH(ref d, a, b, c, blockPtr[(3 * 41 + 5) & 0xf], 11, 0xeaa127fa); // 41 HH(ref c, d, a, b, blockPtr[(3 * 42 + 5) & 0xf], 16, 0xd4ef3085); // 42 HH(ref b, c, d, a, blockPtr[(3 * 43 + 5) & 0xf], 23, 0x4881d05); // 43 HH(ref a, b, c, d, blockPtr[(3 * 44 + 5) & 0xf], 4, 0xd9d4d039); // 44 HH(ref d, a, b, c, blockPtr[(3 * 45 + 5) & 0xf], 11, 0xe6db99e5); // 45 HH(ref c, d, a, b, blockPtr[(3 * 46 + 5) & 0xf], 16, 0x1fa27cf8); // 46 HH(ref b, c, d, a, blockPtr[(3 * 47 + 5) & 0xf], 23, 0xc4ac5665); // 47 II(ref a, b, c, d, blockPtr[(7 * 48) & 0xf], 6, 0xf4292244); // 48 II(ref d, a, b, c, blockPtr[(7 * 49) & 0xf], 10, 0x432aff97); // 49 II(ref c, d, a, b, blockPtr[(7 * 50) & 0xf], 15, 0xab9423a7); // 50 II(ref b, c, d, a, blockPtr[(7 * 51) & 0xf], 21, 0xfc93a039); // 51 II(ref a, b, c, d, blockPtr[(7 * 52) & 0xf], 6, 0x655b59c3); // 52 II(ref d, a, b, c, blockPtr[(7 * 53) & 0xf], 10, 0x8f0ccc92); // 53 II(ref c, d, a, b, blockPtr[(7 * 54) & 0xf], 15, 0xffeff47d); // 54 II(ref b, c, d, a, blockPtr[(7 * 55) & 0xf], 21, 0x85845dd1); // 55 II(ref a, b, c, d, blockPtr[(7 * 56) & 0xf], 6, 0x6fa87e4f); // 56 II(ref d, a, b, c, blockPtr[(7 * 57) & 0xf], 10, 0xfe2ce6e0); // 57 II(ref c, d, a, b, blockPtr[(7 * 58) & 0xf], 15, 0xa3014314); // 58 II(ref b, c, d, a, blockPtr[(7 * 59) & 0xf], 21, 0x4e0811a1); // 59 II(ref a, b, c, d, blockPtr[(7 * 60) & 0xf], 6, 0xf7537e82); // 60 II(ref d, a, b, c, blockPtr[(7 * 61) & 0xf], 10, 0xbd3af235); // 61 II(ref c, d, a, b, blockPtr[(7 * 62) & 0xf], 15, 0x2ad7d2bb); // 62 II(ref b, c, d, a, blockPtr[(7 * 63) & 0xf], 21, 0xeb86d391); // 63 digest->A += a; digest->B += b; digest->C += c; digest->D += d; } }
public static void GetDigest(byte *input, int length, Md5Digest *digest) { if (s_sinesPtr == null) { Initialize(); } const int bytesPerBlock = 64; var blocksCount = (length + 8) / bytesPerBlock + 1; digest->A = 0x67452301; digest->B = 0xefcdab89; digest->C = 0x98badcfe; digest->D = 0x10325476; var paddingBlockData = default(Block); for (var blockIndex = 0; blockIndex < blocksCount; blockIndex++) { var offset = blockIndex * bytesPerBlock; var blockEnd = offset + bytesPerBlock; uint *blockPtr; if (blockEnd > length) // we're going to run out of input on this block { if (offset >= length) // we're already totally past the input at this point - this block is just padding, and definitely the final block { if (offset == length) { // the end of input perfectly lined up with a block - so this is the start of padding *(byte *)&paddingBlockData = 0x80; } else { // this is not the start of padding, so we need to clear out any data from the first padding block paddingBlockData = default(Block); } paddingBlockData.SetOriginalLength(length); } else // there is still some input left to consume before we get to padding { var bytesRemaining = bytesPerBlock - (blockEnd - length); var paddingPtr = (byte *)&paddingBlockData; Common.UnsafeMemoryCopy(&input[offset], paddingPtr, bytesRemaining); // add bit paddingPtr[bytesRemaining] = 0x80; // check if we can add the length if (bytesPerBlock - (bytesRemaining + 1) >= 8) { paddingBlockData.SetOriginalLength(length); } } blockPtr = (uint *)&paddingBlockData; } else { blockPtr = (uint *)&input[offset]; } var a = digest->A; var b = digest->B; var c = digest->C; var d = digest->D; uint f, dTemp; int g; // 0 f = (b & c) | (~b & d); g = 0; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[0] + blockPtr[g], s_shiftsPtr[0]); a = dTemp; // 1 f = (b & c) | (~b & d); g = 1; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[1] + blockPtr[g], s_shiftsPtr[1]); a = dTemp; // 2 f = (b & c) | (~b & d); g = 2; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[2] + blockPtr[g], s_shiftsPtr[2]); a = dTemp; // 3 f = (b & c) | (~b & d); g = 3; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[3] + blockPtr[g], s_shiftsPtr[3]); a = dTemp; // 4 f = (b & c) | (~b & d); g = 4; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[4] + blockPtr[g], s_shiftsPtr[4]); a = dTemp; // 5 f = (b & c) | (~b & d); g = 5; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[5] + blockPtr[g], s_shiftsPtr[5]); a = dTemp; // 6 f = (b & c) | (~b & d); g = 6; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[6] + blockPtr[g], s_shiftsPtr[6]); a = dTemp; // 7 f = (b & c) | (~b & d); g = 7; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[7] + blockPtr[g], s_shiftsPtr[7]); a = dTemp; // 8 f = (b & c) | (~b & d); g = 8; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[8] + blockPtr[g], s_shiftsPtr[8]); a = dTemp; // 9 f = (b & c) | (~b & d); g = 9; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[9] + blockPtr[g], s_shiftsPtr[9]); a = dTemp; // 10 f = (b & c) | (~b & d); g = 10; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[10] + blockPtr[g], s_shiftsPtr[10]); a = dTemp; // 11 f = (b & c) | (~b & d); g = 11; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[11] + blockPtr[g], s_shiftsPtr[11]); a = dTemp; // 12 f = (b & c) | (~b & d); g = 12; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[12] + blockPtr[g], s_shiftsPtr[12]); a = dTemp; // 13 f = (b & c) | (~b & d); g = 13; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[13] + blockPtr[g], s_shiftsPtr[13]); a = dTemp; // 14 f = (b & c) | (~b & d); g = 14; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[14] + blockPtr[g], s_shiftsPtr[14]); a = dTemp; // 15 f = (b & c) | (~b & d); g = 15; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[15] + blockPtr[g], s_shiftsPtr[15]); a = dTemp; // 16 f = (d & b) | (~d & c); g = (5 * 16 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[16] + blockPtr[g], s_shiftsPtr[16]); a = dTemp; // 17 f = (d & b) | (~d & c); g = (5 * 17 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[17] + blockPtr[g], s_shiftsPtr[17]); a = dTemp; // 18 f = (d & b) | (~d & c); g = (5 * 18 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[18] + blockPtr[g], s_shiftsPtr[18]); a = dTemp; // 19 f = (d & b) | (~d & c); g = (5 * 19 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[19] + blockPtr[g], s_shiftsPtr[19]); a = dTemp; // 20 f = (d & b) | (~d & c); g = (5 * 20 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[20] + blockPtr[g], s_shiftsPtr[20]); a = dTemp; // 21 f = (d & b) | (~d & c); g = (5 * 21 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[21] + blockPtr[g], s_shiftsPtr[21]); a = dTemp; // 22 f = (d & b) | (~d & c); g = (5 * 22 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[22] + blockPtr[g], s_shiftsPtr[22]); a = dTemp; // 23 f = (d & b) | (~d & c); g = (5 * 23 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[23] + blockPtr[g], s_shiftsPtr[23]); a = dTemp; // 24 f = (d & b) | (~d & c); g = (5 * 24 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[24] + blockPtr[g], s_shiftsPtr[24]); a = dTemp; // 25 f = (d & b) | (~d & c); g = (5 * 25 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[25] + blockPtr[g], s_shiftsPtr[25]); a = dTemp; // 26 f = (d & b) | (~d & c); g = (5 * 26 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[26] + blockPtr[g], s_shiftsPtr[26]); a = dTemp; // 27 f = (d & b) | (~d & c); g = (5 * 27 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[27] + blockPtr[g], s_shiftsPtr[27]); a = dTemp; // 28 f = (d & b) | (~d & c); g = (5 * 28 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[28] + blockPtr[g], s_shiftsPtr[28]); a = dTemp; // 29 f = (d & b) | (~d & c); g = (5 * 29 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[29] + blockPtr[g], s_shiftsPtr[29]); a = dTemp; // 30 f = (d & b) | (~d & c); g = (5 * 30 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[30] + blockPtr[g], s_shiftsPtr[30]); a = dTemp; // 31 f = (d & b) | (~d & c); g = (5 * 31 + 1) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[31] + blockPtr[g], s_shiftsPtr[31]); a = dTemp; // 32 f = b ^ c ^ d; g = (3 * 32 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[32] + blockPtr[g], s_shiftsPtr[32]); a = dTemp; // 33 f = b ^ c ^ d; g = (3 * 33 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[33] + blockPtr[g], s_shiftsPtr[33]); a = dTemp; // 34 f = b ^ c ^ d; g = (3 * 34 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[34] + blockPtr[g], s_shiftsPtr[34]); a = dTemp; // 35 f = b ^ c ^ d; g = (3 * 35 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[35] + blockPtr[g], s_shiftsPtr[35]); a = dTemp; // 36 f = b ^ c ^ d; g = (3 * 36 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[36] + blockPtr[g], s_shiftsPtr[36]); a = dTemp; // 37 f = b ^ c ^ d; g = (3 * 37 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[37] + blockPtr[g], s_shiftsPtr[37]); a = dTemp; // 38 f = b ^ c ^ d; g = (3 * 38 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[38] + blockPtr[g], s_shiftsPtr[38]); a = dTemp; // 39 f = b ^ c ^ d; g = (3 * 39 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[39] + blockPtr[g], s_shiftsPtr[39]); a = dTemp; // 40 f = b ^ c ^ d; g = (3 * 40 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[40] + blockPtr[g], s_shiftsPtr[40]); a = dTemp; // 41 f = b ^ c ^ d; g = (3 * 41 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[41] + blockPtr[g], s_shiftsPtr[41]); a = dTemp; // 42 f = b ^ c ^ d; g = (3 * 42 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[42] + blockPtr[g], s_shiftsPtr[42]); a = dTemp; // 43 f = b ^ c ^ d; g = (3 * 43 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[43] + blockPtr[g], s_shiftsPtr[43]); a = dTemp; // 44 f = b ^ c ^ d; g = (3 * 44 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[44] + blockPtr[g], s_shiftsPtr[44]); a = dTemp; // 45 f = b ^ c ^ d; g = (3 * 45 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[45] + blockPtr[g], s_shiftsPtr[45]); a = dTemp; // 46 f = b ^ c ^ d; g = (3 * 46 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[46] + blockPtr[g], s_shiftsPtr[46]); a = dTemp; // 47 f = b ^ c ^ d; g = (3 * 47 + 5) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[47] + blockPtr[g], s_shiftsPtr[47]); a = dTemp; // 48 f = c ^ (b | ~d); g = (7 * 48) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[48] + blockPtr[g], s_shiftsPtr[48]); a = dTemp; // 49 f = c ^ (b | ~d); g = (7 * 49) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[49] + blockPtr[g], s_shiftsPtr[49]); a = dTemp; // 50 f = c ^ (b | ~d); g = (7 * 50) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[50] + blockPtr[g], s_shiftsPtr[50]); a = dTemp; // 51 f = c ^ (b | ~d); g = (7 * 51) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[51] + blockPtr[g], s_shiftsPtr[51]); a = dTemp; // 52 f = c ^ (b | ~d); g = (7 * 52) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[52] + blockPtr[g], s_shiftsPtr[52]); a = dTemp; // 53 f = c ^ (b | ~d); g = (7 * 53) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[53] + blockPtr[g], s_shiftsPtr[53]); a = dTemp; // 54 f = c ^ (b | ~d); g = (7 * 54) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[54] + blockPtr[g], s_shiftsPtr[54]); a = dTemp; // 55 f = c ^ (b | ~d); g = (7 * 55) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[55] + blockPtr[g], s_shiftsPtr[55]); a = dTemp; // 56 f = c ^ (b | ~d); g = (7 * 56) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[56] + blockPtr[g], s_shiftsPtr[56]); a = dTemp; // 57 f = c ^ (b | ~d); g = (7 * 57) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[57] + blockPtr[g], s_shiftsPtr[57]); a = dTemp; // 58 f = c ^ (b | ~d); g = (7 * 58) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[58] + blockPtr[g], s_shiftsPtr[58]); a = dTemp; // 59 f = c ^ (b | ~d); g = (7 * 59) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[59] + blockPtr[g], s_shiftsPtr[59]); a = dTemp; // 60 f = c ^ (b | ~d); g = (7 * 60) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[60] + blockPtr[g], s_shiftsPtr[60]); a = dTemp; // 61 f = c ^ (b | ~d); g = (7 * 61) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[61] + blockPtr[g], s_shiftsPtr[61]); a = dTemp; // 62 f = c ^ (b | ~d); g = (7 * 62) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[62] + blockPtr[g], s_shiftsPtr[62]); a = dTemp; // 63 f = c ^ (b | ~d); g = (7 * 63) % 16; dTemp = d; d = c; c = b; b += LeftRotate(a + f + s_sinesPtr[63] + blockPtr[g], s_shiftsPtr[63]); a = dTemp; digest->A += a; digest->B += b; digest->C += c; digest->D += d; } }
public static unsafe void GetDigest(byte *input, int length, Md5Digest *digest) { const int bytesPerBlock = 64; var blocksCount = (length + 8) / bytesPerBlock + 1; digest->A = 0x67452301; digest->B = 0xefcdab89; digest->C = 0x98badcfe; digest->D = 0x10325476; var paddingBlockData = default(Block); for (var blockIndex = 0; blockIndex < blocksCount; blockIndex++) { var offset = blockIndex * bytesPerBlock; var blockEnd = offset + bytesPerBlock; uint *blockPtr; if (blockEnd > length) // we're going to run out of input on this block { if (offset >= length) // we're already totally past the input at this point - this block is just padding, and definitely the final block { if (offset == length) { // the end of input perfectly lined up with a block - so this is the start of padding *(byte *)&paddingBlockData = 0x80; } else { // this is not the start of padding, so we need to clear out any data from the first padding block paddingBlockData = default(Block); } paddingBlockData.SetOriginalLength(length); } else // there is still some input left to consume before we get to padding { var bytesRemaining = bytesPerBlock - (blockEnd - length); var paddingPtr = (byte *)&paddingBlockData; Common.UnsafeMemoryCopy(&input[offset], paddingPtr, bytesRemaining); // add bit paddingPtr[bytesRemaining] = 0x80; // check if we can add the length if (bytesPerBlock - (bytesRemaining + 1) >= 8) { paddingBlockData.SetOriginalLength(length); } } blockPtr = (uint *)&paddingBlockData; } else { blockPtr = (uint *)&input[offset]; } var a = digest->A; var b = digest->B; var c = digest->C; var d = digest->D; for (var i = 0; i < bytesPerBlock; i++) { uint f; int g; if (i < 16) { f = (b & c) | (~b & d); g = i; } else if (i < 32) { f = (d & b) | (~d & c); g = (5 * i + 1) % 16; } else if (i < 48) { f = b ^ c ^ d; g = (3 * i + 5) % 16; } else { f = c ^ (b | ~d); g = (7 * i) % 16; } var dTemp = d; d = c; c = b; var k = s_sines[i]; var s = s_shifts[i]; var m = blockPtr[g]; b += LeftRotate(a + f + k + m, s); a = dTemp; } digest->A += a; digest->B += b; digest->C += c; digest->D += d; } }