/* Implemented, with great difficulty, according to the description in RFC 1321 Function md5() parameters: char *digest: an output buffer for the binary message digest (16 bytes) char *message: a buffer containing the message data. int length: the length of the message, in bytes. No return value. It just does what it does and that's it. Written for a little-endian architecture. Big endian sucks! Released under the antivirial license. Basically, you can do anything you want with it as long as what you want doesn't involve the GNU GPL. See http://www.ecstaticlyrics.com/antiviral/ for more information. */ #include static void process(void *, void *); // Buffer to store last two blocks, since they require // modification to add the padding and message length. void md5(void *_digest, void *_message, unsigned int length) { unsigned int _buffer[32]; // Cast everything to pointers of various types, in order // to avoid having to repeatedly type cast in the code below. // Placing the "const" after the "*" seems to be the way to // tell the compiler that it is the pointer, and not the // data it points to, which is constant. Thus it will know // that we're simply defining another name for the pointer. unsigned char * const digest_chars = (unsigned char *) _digest; unsigned int * const digest_ints = (unsigned int *) _digest; unsigned char * const message_chars = (unsigned char *) _message; unsigned int * const message_ints = (unsigned int *) _message; unsigned char * const buffer_chars = (unsigned char *) _buffer; unsigned int * const buffer_ints = (unsigned int *) _buffer; // To pad the message, copy its last partial block (if any) to a // zero-filled buffer, then add the padding and length to the buffer. int source_block_count = length >> 6; int buffer_block_count = (((length % 64) + 8) >> 6) + 1; memset(buffer_chars, 0, 128); memmove(buffer_chars, message_chars + 64 * source_block_count, length % 64); buffer_chars[length % 64] = 0x80; // Then append the length, in bits. buffer_ints[16 * buffer_block_count - 2] = length << 3; buffer_ints[16 * buffer_block_count - 1] = length >> 29; // Then just compute the digest! digest_ints[0] = 0x67452301; digest_ints[1] = 0xEFCDAB89; digest_ints[2] = 0x98BADCFE; digest_ints[3] = 0x10325476; for (int i = 0; i < source_block_count; i++) { process(digest_chars, message_chars + 64 * i); }; for (int i = 0; i < buffer_block_count; i++) { process(digest_chars, buffer_chars + 64 * i); }; // That was so easy! }; static void process(void *_digest, void *_message) { int * const digest = (int *) _digest; int * const message = (int *) _message; unsigned int a, b, c, d; a = digest[0]; b = digest[1]; c = digest[2]; d = digest[3]; a += ((b & c) | (~b & d)) + message[0] + 3614090360; a = b + ((a << 7) | (a >> 25)); d += ((a & b) | (~a & c)) + message[1] + 3905402710; d = a + ((d << 12) | (d >> 20)); c += ((d & a) | (~d & b)) + message[2] + 606105819; c = d + ((c << 17) | (c >> 15)); b += ((c & d) | (~c & a)) + message[3] + 3250441966; b = c + ((b << 22) | (b >> 10)); a += ((b & c) | (~b & d)) + message[4] + 4118548399; a = b + ((a << 7) | (a >> 25)); d += ((a & b) | (~a & c)) + message[5] + 1200080426; d = a + ((d << 12) | (d >> 20)); c += ((d & a) | (~d & b)) + message[6] + 2821735955; c = d + ((c << 17) | (c >> 15)); b += ((c & d) | (~c & a)) + message[7] + 4249261313; b = c + ((b << 22) | (b >> 10)); a += ((b & c) | (~b & d)) + message[8] + 1770035416; a = b + ((a << 7) | (a >> 25)); d += ((a & b) | (~a & c)) + message[9] + 2336552879; d = a + ((d << 12) | (d >> 20)); c += ((d & a) | (~d & b)) + message[10] + 4294925233; c = d + ((c << 17) | (c >> 15)); b += ((c & d) | (~c & a)) + message[11] + 2304563134; b = c + ((b << 22) | (b >> 10)); a += ((b & c) | (~b & d)) + message[12] + 1804603682; a = b + ((a << 7) | (a >> 25)); d += ((a & b) | (~a & c)) + message[13] + 4254626195; d = a + ((d << 12) | (d >> 20)); c += ((d & a) | (~d & b)) + message[14] + 2792965006; c = d + ((c << 17) | (c >> 15)); b += ((c & d) | (~c & a)) + message[15] + 1236535329; b = c + ((b << 22) | (b >> 10)); a += ((b & d) | (c & ~d)) + message[1] + 4129170786; a = b + ((a << 5) | (a >> 27)); d += ((a & c) | (b & ~c)) + message[6] + 3225465664; d = a + ((d << 9) | (d >> 23)); c += ((d & b) | (a & ~b)) + message[11] + 643717713; c = d + ((c << 14) | (c >> 18)); b += ((c & a) | (d & ~a)) + message[0] + 3921069994; b = c + ((b << 20) | (b >> 12)); a += ((b & d) | (c & ~d)) + message[5] + 3593408605; a = b + ((a << 5) | (a >> 27)); d += ((a & c) | (b & ~c)) + message[10] + 38016083; d = a + ((d << 9) | (d >> 23)); c += ((d & b) | (a & ~b)) + message[15] + 3634488961; c = d + ((c << 14) | (c >> 18)); b += ((c & a) | (d & ~a)) + message[4] + 3889429448; b = c + ((b << 20) | (b >> 12)); a += ((b & d) | (c & ~d)) + message[9] + 568446438; a = b + ((a << 5) | (a >> 27)); d += ((a & c) | (b & ~c)) + message[14] + 3275163606; d = a + ((d << 9) | (d >> 23)); c += ((d & b) | (a & ~b)) + message[3] + 4107603335; c = d + ((c << 14) | (c >> 18)); b += ((c & a) | (d & ~a)) + message[8] + 1163531501; b = c + ((b << 20) | (b >> 12)); a += ((b & d) | (c & ~d)) + message[13] + 2850285829; a = b + ((a << 5) | (a >> 27)); d += ((a & c) | (b & ~c)) + message[2] + 4243563512; d = a + ((d << 9) | (d >> 23)); c += ((d & b) | (a & ~b)) + message[7] + 1735328473; c = d + ((c << 14) | (c >> 18)); b += ((c & a) | (d & ~a)) + message[12] + 2368359562; b = c + ((b << 20) | (b >> 12)); a += (b ^ c ^ d) + message[5] + 4294588738; a = b + ((a << 4) | (a >> 28)); d += (a ^ b ^ c) + message[8] + 2272392833; d = a + ((d << 11) | (d >> 21)); c += (d ^ a ^ b) + message[11] + 1839030562; c = d + ((c << 16) | (c >> 16)); b += (c ^ d ^ a) + message[14] + 4259657740; b = c + ((b << 23) | (b >> 9)); a += (b ^ c ^ d) + message[1] + 2763975236; a = b + ((a << 4) | (a >> 28)); d += (a ^ b ^ c) + message[4] + 1272893353; d = a + ((d << 11) | (d >> 21)); c += (d ^ a ^ b) + message[7] + 4139469664; c = d + ((c << 16) | (c >> 16)); b += (c ^ d ^ a) + message[10] + 3200236656; b = c + ((b << 23) | (b >> 9)); a += (b ^ c ^ d) + message[13] + 681279174; a = b + ((a << 4) | (a >> 28)); d += (a ^ b ^ c) + message[0] + 3936430074; d = a + ((d << 11) | (d >> 21)); c += (d ^ a ^ b) + message[3] + 3572445317; c = d + ((c << 16) | (c >> 16)); b += (c ^ d ^ a) + message[6] + 76029189; b = c + ((b << 23) | (b >> 9)); a += (b ^ c ^ d) + message[9] + 3654602809; a = b + ((a << 4) | (a >> 28)); d += (a ^ b ^ c) + message[12] + 3873151461; d = a + ((d << 11) | (d >> 21)); c += (d ^ a ^ b) + message[15] + 530742520; c = d + ((c << 16) | (c >> 16)); b += (c ^ d ^ a) + message[2] + 3299628645; b = c + ((b << 23) | (b >> 9)); a += (c ^ (b | ~d)) + message[0] + 4096336452; a = b + ((a << 6) | (a >> 26)); d += (b ^ (a | ~c)) + message[7] + 1126891415; d = a + ((d << 10) | (d >> 22)); c += (a ^ (d | ~b)) + message[14] + 2878612391; c = d + ((c << 15) | (c >> 17)); b += (d ^ (c | ~a)) + message[5] + 4237533241; b = c + ((b << 21) | (b >> 11)); a += (c ^ (b | ~d)) + message[12] + 1700485571; a = b + ((a << 6) | (a >> 26)); d += (b ^ (a | ~c)) + message[3] + 2399980690; d = a + ((d << 10) | (d >> 22)); c += (a ^ (d | ~b)) + message[10] + 4293915773; c = d + ((c << 15) | (c >> 17)); b += (d ^ (c | ~a)) + message[1] + 2240044497; b = c + ((b << 21) | (b >> 11)); a += (c ^ (b | ~d)) + message[8] + 1873313359; a = b + ((a << 6) | (a >> 26)); d += (b ^ (a | ~c)) + message[15] + 4264355552; d = a + ((d << 10) | (d >> 22)); c += (a ^ (d | ~b)) + message[6] + 2734768916; c = d + ((c << 15) | (c >> 17)); b += (d ^ (c | ~a)) + message[13] + 1309151649; b = c + ((b << 21) | (b >> 11)); a += (c ^ (b | ~d)) + message[4] + 4149444226; a = b + ((a << 6) | (a >> 26)); d += (b ^ (a | ~c)) + message[11] + 3174756917; d = a + ((d << 10) | (d >> 22)); c += (a ^ (d | ~b)) + message[2] + 718787259; c = d + ((c << 15) | (c >> 17)); b += (d ^ (c | ~a)) + message[9] + 3951481745; b = c + ((b << 21) | (b >> 11)); digest[0] += a; digest[1] += b; digest[2] += c; digest[3] += d; };