void ProcessMessageBlock(Context ctx)
{
uint[] w = new uint[80];
for (int t = 0; t < 16; t++)
{
w[t] |= (uint)ctx.MessageBlock[t * 4 + 0] << 24;
w[t] |= (uint)ctx.MessageBlock[t * 4 + 1] << 16;
w[t] |= (uint)ctx.MessageBlock[t * 4 + 2] << 08;
w[t] |= (uint)ctx.MessageBlock[t * 4 + 3];
}
for (int t = 16; t < 80; t++)
w[t] = CircularShift(1, w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]);
ctx.A = ctx.IntermediateHash[0];
ctx.B = ctx.IntermediateHash[1];
ctx.C = ctx.IntermediateHash[2];
ctx.D = ctx.IntermediateHash[3];
ctx.E = ctx.IntermediateHash[4];
for (int t = 0; t < 20; t++)
RotateWordBuffers(ctx, (b, c, d) => (b & c) | ((~b) & d), w[t], K0);
for (int t = 20; t < 40; t++)
RotateWordBuffers(ctx, (b, c, d) => b ^ c ^ d, w[t], K1);
for (int t = 40; t < 60; t++)
RotateWordBuffers(ctx, (b, c, d) => (b & c) | (b & d) | (c & d), w[t], K2);
for (int t = 60; t < 80; t++)
RotateWordBuffers(ctx, (b, c, d) => b ^ c ^ d, w[t], K3);
ctx.IntermediateHash[0] += ctx.A;
ctx.IntermediateHash[1] += ctx.B;
ctx.IntermediateHash[2] += ctx.C;
ctx.IntermediateHash[3] += ctx.D;
ctx.IntermediateHash[4] += ctx.E;
ctx.MessageBlockIndex = 0;
}