private byte[] Finish(Md5State pms) { var pad = new byte[64] { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; var data = new byte[8]; /* Save the length before padding. */ for (var i = 0; i < 8; ++i) { data[i] = (byte)(pms.Count[i >> 2] >> ((i & 3) << 3)); } /* Pad to 56 bytes mod 64. */ Append(pms, pad, (int)(((55 - (pms.Count[0] >> 3)) & 63) + 1)); /* Append the length. */ Append(pms, data, 8); var digest = new byte[16]; for (var i = 0; i < 16; ++i) { digest[i] = (byte)(pms.Abcd[i >> 2] >> ((i & 3) << 3)); } return(digest); }
private void Init(Md5State pms) { pms.Count[0] = pms.Count[1] = 0; pms.Abcd[0] = 0x67452301; pms.Abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; pms.Abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; pms.Abcd[3] = 0x10325476; }
private void Append(Md5State pms, byte[] data, int nbytes) { if (nbytes <= 0) { return; } var p = 0; var left = nbytes; var offset = (int)(pms.Count[0] >> 3) & 63; var nbits = (uint)(nbytes << 3); /* Update the message length. */ pms.Count[1] += (uint)nbytes >> 29; pms.Count[0] += nbits; if (pms.Count[0] < nbits) { pms.Count[1]++; } /* Process an initial partial block. */ if (offset != 0) { var copy = offset + nbytes > 64 ? 64 - offset : nbytes; Buffer.BlockCopy(data, 0, pms.Buf, offset, copy); if (offset + copy < 64) { return; } p += copy; left -= copy; Process(pms, pms.Buf); } /* Process full blocks. */ for (; left >= 64; p += 64, left -= 64) { var chunk = new byte[64]; Buffer.BlockCopy(data, p, chunk, 0, 64); Process(pms, chunk); } /* Process a final partial block. */ if (left != 0) { Buffer.BlockCopy(data, p, pms.Buf, 0, left); } }
public Md5() { _state = new Md5State(); Init(_state); }
private void Process(Md5State pms, byte[] data /*[64]*/) { uint a = pms.Abcd[0], b = pms.Abcd[1], c = pms.Abcd[2], d = pms.Abcd[3]; if (BitConverter.IsLittleEndian) { /* * On little-endian machines, we can just copy the data to the buffer. */ Buffer.BlockCopy(data, 0, X, 0, 64); } else { /* * On big-endian machines, we must arrange the bytes in the * right order. */ for (int i = 0, j = 0; i < 16; ++i, j += 4) { X[i] = (uint)(data[j] + (data[j + 1] << 8) + (data[j + 2] << 16) + (data[j + 3] << 24)); } } /* Round 1. */ /* Let [abcd k s i] denote the operation * a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ SetF(ref a, b, c, d, 0, 7, T1); SetF(ref d, a, b, c, 1, 12, T2); SetF(ref c, d, a, b, 2, 17, T3); SetF(ref b, c, d, a, 3, 22, T4); SetF(ref a, b, c, d, 4, 7, T5); SetF(ref d, a, b, c, 5, 12, T6); SetF(ref c, d, a, b, 6, 17, T7); SetF(ref b, c, d, a, 7, 22, T8); SetF(ref a, b, c, d, 8, 7, T9); SetF(ref d, a, b, c, 9, 12, T10); SetF(ref c, d, a, b, 10, 17, T11); SetF(ref b, c, d, a, 11, 22, T12); SetF(ref a, b, c, d, 12, 7, T13); SetF(ref d, a, b, c, 13, 12, T14); SetF(ref c, d, a, b, 14, 17, T15); SetF(ref b, c, d, a, 15, 22, T16); /* Round 2. */ /* Let [abcd k s i] denote the operation * a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ SetG(ref a, b, c, d, 1, 5, T17); SetG(ref d, a, b, c, 6, 9, T18); SetG(ref c, d, a, b, 11, 14, T19); SetG(ref b, c, d, a, 0, 20, T20); SetG(ref a, b, c, d, 5, 5, T21); SetG(ref d, a, b, c, 10, 9, T22); SetG(ref c, d, a, b, 15, 14, T23); SetG(ref b, c, d, a, 4, 20, T24); SetG(ref a, b, c, d, 9, 5, T25); SetG(ref d, a, b, c, 14, 9, T26); SetG(ref c, d, a, b, 3, 14, T27); SetG(ref b, c, d, a, 8, 20, T28); SetG(ref a, b, c, d, 13, 5, T29); SetG(ref d, a, b, c, 2, 9, T30); SetG(ref c, d, a, b, 7, 14, T31); SetG(ref b, c, d, a, 12, 20, T32); /* Round 3. */ /* Let [abcd k s t] denote the operation * a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ SetH(ref a, b, c, d, 5, 4, T33); SetH(ref d, a, b, c, 8, 11, T34); SetH(ref c, d, a, b, 11, 16, T35); SetH(ref b, c, d, a, 14, 23, T36); SetH(ref a, b, c, d, 1, 4, T37); SetH(ref d, a, b, c, 4, 11, T38); SetH(ref c, d, a, b, 7, 16, T39); SetH(ref b, c, d, a, 10, 23, T40); SetH(ref a, b, c, d, 13, 4, T41); SetH(ref d, a, b, c, 0, 11, T42); SetH(ref c, d, a, b, 3, 16, T43); SetH(ref b, c, d, a, 6, 23, T44); SetH(ref a, b, c, d, 9, 4, T45); SetH(ref d, a, b, c, 12, 11, T46); SetH(ref c, d, a, b, 15, 16, T47); SetH(ref b, c, d, a, 2, 23, T48); /* Round 4. */ /* Let [abcd k s t] denote the operation * a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ SetI(ref a, b, c, d, 0, 6, T49); SetI(ref d, a, b, c, 7, 10, T50); SetI(ref c, d, a, b, 14, 15, T51); SetI(ref b, c, d, a, 5, 21, T52); SetI(ref a, b, c, d, 12, 6, T53); SetI(ref d, a, b, c, 3, 10, T54); SetI(ref c, d, a, b, 10, 15, T55); SetI(ref b, c, d, a, 1, 21, T56); SetI(ref a, b, c, d, 8, 6, T57); SetI(ref d, a, b, c, 15, 10, T58); SetI(ref c, d, a, b, 6, 15, T59); SetI(ref b, c, d, a, 13, 21, T60); SetI(ref a, b, c, d, 4, 6, T61); SetI(ref d, a, b, c, 11, 10, T62); SetI(ref c, d, a, b, 2, 15, T63); SetI(ref b, c, d, a, 9, 21, T64); /* Then perform the following additions. (That is increment each * of the four registers by the value it had before this block * was started.) */ pms.Abcd[0] += a; pms.Abcd[1] += b; pms.Abcd[2] += c; pms.Abcd[3] += d; }