TAY
Fork of Crypto_light by
Diff: MD5.cpp
- Revision:
- 0:7a1237bd2d13
- Child:
- 1:14a7cea431aa
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MD5.cpp Sat Sep 07 23:47:28 2013 +0000 @@ -0,0 +1,231 @@ +#include "MD5.h" +#include <string.h> + +static const uint32_t T[] = +{ + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 +}; + +static const uint32_t A = 0x67452301; +static const uint32_t B = 0xefcdab89; +static const uint32_t C = 0x98badcfe; +static const uint32_t D = 0x10325476; + +static uint32_t F(uint32_t x, uint32_t y, uint32_t z) +{ + return (x & y) | ((~x) & z); +} + +static uint32_t G(uint32_t x, uint32_t y, uint32_t z) +{ + return (x & z) | (y & (~z)); +} + +static uint32_t H(uint32_t x, uint32_t y, uint32_t z) +{ + return x ^ y ^ z; +} + +static uint32_t I(uint32_t x, uint32_t y, uint32_t z) +{ + return y ^ (x | (~z)); +} + +static uint32_t rotLeft(uint32_t w, uint8_t s) +{ + return (w << s) | (w >> (32-s)); +} + +#define ROUND1(a,b,c,d,k,s,i) \ + a += F(b,c,d) + x[k] + T[i-1]; \ + a = rotLeft(a,s);\ + a += b; +#define ROUND2(a,b,c,d,k,s,i) \ + a += G(b,c,d) + x[k] + T[i-1]; \ + a = rotLeft(a,s);\ + a += b; +#define ROUND3(a,b,c,d,k,s,i) \ + a += H(b,c,d) + x[k] + T[i-1]; \ + a = rotLeft(a,s);\ + a += b; +#define ROUND4(a,b,c,d,k,s,i) \ + a += I(b,c,d) + x[k] + T[i-1]; \ + a = rotLeft(a,s);\ + a += b; + + +MD5::MD5(): +HashAlgorithm(), +a(A), +b(B), +c(C), +d(D), +totalBufferLength(0), +buffer(), +bufferLength(0) +{ +} + +uint8_t MD5::outputSize() const +{ + return 16; +} + +void MD5::add(uint8_t *in, uint32_t length) +{ + if(length < 64-bufferLength) + { + memcpy(&buffer[bufferLength], in, length); + bufferLength += length; + totalBufferLength += length; + return; + } + int offset = 64-bufferLength; + memcpy(&buffer[bufferLength], in, offset); + uint32_t tmpA = a, tmpB = b, tmpC = c, tmpD = d; + computeRounds(&a, &b, &c, &d, buffer); + a += tmpA; + b += tmpB; + c += tmpC; + d += tmpD; + while(length-offset > 64) + { + memcpy(buffer, &in[offset], 64); + tmpA = a; + tmpB = b; + tmpC = c; + tmpD = d; + computeRounds(&a, &b, &c, &d, buffer); + a += tmpA; + b += tmpB; + c += tmpC; + d += tmpD; + offset += 64; + } + if(offset > length) + offset -= 64; + bufferLength = length - offset; + memcpy(buffer, &in[offset], bufferLength); + totalBufferLength += length; +} + +void MD5::computeDigest(uint8_t *digest) +{ + uint16_t padding; + if(totalBufferLength % 64 < 56) + padding = 56 - (totalBufferLength % 64); + else + padding = 56 + (64 - (totalBufferLength % 64)); + uint8_t val = 0x80; + add(&val, 1); + val = 0; + for(int i = 0; i < padding-1; ++i) + add(&val,1); + totalBufferLength -= padding; + uint64_t lengthBit = totalBufferLength * 8; + uint32_t lengthBitLow = lengthBit; + uint32_t lengthBitHigh = lengthBit >> 32; + add((uint8_t*)&lengthBitLow,4); + add((uint8_t*)&lengthBitHigh,4); + + memcpy(digest, &a, 4); + memcpy(&digest[4], &b, 4); + memcpy(&digest[8], &c, 4); + memcpy(&digest[12], &d, 4); + // reset state + a = A; + b = B; + c = C; + d = D; + totalBufferLength = 0; + bufferLength = 0; +} + +void MD5::computeRounds(uint32_t *a2, uint32_t *b2, uint32_t *c2, uint32_t *d2, uint8_t *buffer) +{ + uint32_t a = *a2, b = *b2, c = *c2, d = *d2; + uint32_t x[16]; + for(int j = 0; j < 16; ++j) + memcpy(&x[j], &buffer[j*4], 4); + + // Round 1 + ROUND1(a,b,c,d,0,7,1); ROUND1(d,a,b,c,1,12,2); ROUND1(c,d,a,b,2,17,3); ROUND1(b,c,d,a,3,22,4); + ROUND1(a,b,c,d,4,7,5); ROUND1(d,a,b,c,5,12,6); ROUND1(c,d,a,b,6,17,7); ROUND1(b,c,d,a,7,22,8); + ROUND1(a,b,c,d,8,7,9); ROUND1(d,a,b,c,9,12,10); ROUND1(c,d,a,b,10,17,11); ROUND1(b,c,d,a,11,22,12); + ROUND1(a,b,c,d,12,7,13); ROUND1(d,a,b,c,13,12,14); ROUND1(c,d,a,b,14,17,15); ROUND1(b,c,d,a,15,22,16); + + // Round 2 + ROUND2(a,b,c,d,1,5,17); ROUND2(d,a,b,c,6,9,18); ROUND2(c,d,a,b,11,14,19); ROUND2(b,c,d,a,0,20,20); + ROUND2(a,b,c,d,5,5,21); ROUND2(d,a,b,c,10,9,22); ROUND2(c,d,a,b,15,14,23); ROUND2(b,c,d,a,4,20,24); + ROUND2(a,b,c,d,9,5,25); ROUND2(d,a,b,c,14,9,26); ROUND2(c,d,a,b,3,14,27); ROUND2(b,c,d,a,8,20,28); + ROUND2(a,b,c,d,13,5,29); ROUND2(d,a,b,c,2,9,30); ROUND2(c,d,a,b,7,14,31); ROUND2(b,c,d,a,12,20,32); + + // Round 3 + ROUND3(a,b,c,d,5,4,33); ROUND3(d,a,b,c,8,11,34); ROUND3(c,d,a,b,11,16,35); ROUND3(b,c,d,a,14,23,36); + ROUND3(a,b,c,d,1,4,37); ROUND3(d,a,b,c,4,11,38); ROUND3(c,d,a,b,7,16,39); ROUND3(b,c,d,a,10,23,40); + ROUND3(a,b,c,d,13,4,41); ROUND3(d,a,b,c,0,11,42); ROUND3(c,d,a,b,3,16,43); ROUND3(b,c,d,a,6,23,44); + ROUND3(a,b,c,d,9,4,45); ROUND3(d,a,b,c,12,11,46); ROUND3(c,d,a,b,15,16,47); ROUND3(b,c,d,a,2,23,48); + + // Round 4 + ROUND4(a,b,c,d,0,6,49); ROUND4(d,a,b,c,7,10,50); ROUND4(c,d,a,b,14,15,51); ROUND4(b,c,d,a,5,21,52); + ROUND4(a,b,c,d,12,6,53); ROUND4(d,a,b,c,3,10,54); ROUND4(c,d,a,b,10,15,55); ROUND4(b,c,d,a,1,21,56); + ROUND4(a,b,c,d,8,6,57); ROUND4(d,a,b,c,15,10,58); ROUND4(c,d,a,b,6,15,59); ROUND4(b,c,d,a,13,21,60); + ROUND4(a,b,c,d,4,6,61); ROUND4(d,a,b,c,11,10,62); ROUND4(c,d,a,b,2,15,63); ROUND4(b,c,d,a,9,21,64); + + *a2 = a; + *b2 = b; + *c2 = c; + *d2 = d; +} + +void MD5::computeDigest(uint8_t *digest, uint8_t *msg, uint32_t length) +{ + uint16_t padding; + if(length % 64 < 56) + padding = 56 - (length % 64); + else + padding = 56 + (64 - (length % 64)); + uint32_t totalLength = length + padding + 8; + uint8_t *buffer = new uint8_t[totalLength]; + memcpy(buffer, msg, length); + buffer[length] = 0x80; + memset(&buffer[length+1], 0, padding-1); + uint64_t lengthBit = length * 8; + uint32_t lengthBitLow = lengthBit; + uint32_t lengthBitHigh = lengthBit >> 32; + memcpy(&buffer[length+padding], &lengthBitLow, 4); + memcpy(&buffer[length+padding+4], &lengthBitHigh, 4); + + uint32_t a = A, b = B, c = C, d = D; + for(int i = 0; i < totalLength/64; ++i) + { + uint32_t tmpA = a, tmpB = b, tmpC = c, tmpD = d; + computeRounds(&a, &b, &c, &d, &buffer[64*i]); + + a += tmpA; + b += tmpB; + c += tmpC; + d += tmpD; + } + delete[] buffer; + + memcpy(digest, &a, 4); + memcpy(&digest[4], &b, 4); + memcpy(&digest[8], &c, 4); + memcpy(&digest[12], &d, 4); +} \ No newline at end of file