This library implements some hash and cryptographic algorithms.

Dependents:   mBuinoBlinky PB_Emma_Ethernet SLOTrashHTTP Garagem ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MD4.cpp Source File

MD4.cpp

00001 #include "MD4.h"
00002 #include <string.h>
00003 
00004 static const uint32_t A = 0x67452301;
00005 static const uint32_t B = 0xefcdab89;
00006 static const uint32_t C = 0x98badcfe;
00007 static const uint32_t D = 0x10325476;
00008 
00009 #define F(X,Y,Z) ((X & Y) | ((~X) & Z))
00010 #define G(X,Y,Z) ((X & Y) | (X & Z) | (Y & Z))
00011 #define H(X,Y,Z) (X ^ Y ^ Z)
00012 
00013 
00014 #define ROTL(W,N) (((W) << N) | ((W) >> (32-N)))
00015 
00016 #define ROUND1(a,b,c,d,x,s) \
00017     a = ROTL(a + F(b,c,d) + x,s); 
00018 
00019 #define ROUND2(a,b,c,d,x,s) \
00020     a = ROTL(a + G(b,c,d) + x + 0x5A827999,s); 
00021 
00022 #define ROUND3(a,b,c,d,x,s) \
00023     a = ROTL(a + H(b,c,d) + x + 0x6ED9EBA1,s); 
00024 
00025 
00026     
00027 MD4::MD4():
00028 HashAlgorithm(),
00029 a(A),
00030 b(B),
00031 c(C),
00032 d(D),
00033 totalBufferLength(0),
00034 buffer(),
00035 bufferLength(0)
00036 {
00037 }
00038 
00039 uint8_t MD4::outputSize() const
00040 {
00041     return 16;
00042 }
00043 
00044 void MD4::update(uint8_t *data, uint32_t length)
00045 {
00046     if((int)length < 64-bufferLength)
00047     {
00048         memcpy(&buffer[bufferLength], data, length);
00049         bufferLength += length;
00050         totalBufferLength += length;
00051         return;
00052     }
00053     int offset = 64-bufferLength;
00054     memcpy(&buffer[bufferLength], data, offset);
00055     computeRounds(&a, &b, &c, &d, buffer);
00056     while(length-offset > 64)
00057     {
00058         memcpy(buffer, &data[offset], 64);
00059         computeRounds(&a, &b, &c, &d, buffer);
00060         offset += 64;
00061     }
00062     if(offset > (int)length)
00063         offset -= 64;
00064     bufferLength = length - offset;
00065     memcpy(buffer, &data[offset], bufferLength);
00066     totalBufferLength += length;
00067 }
00068 
00069 void MD4::finalize(uint8_t *hash)
00070 {
00071     uint32_t *hash2 = (uint32_t*)hash;
00072     uint16_t padding;
00073     if(totalBufferLength % 64 < 56)
00074         padding = 56 - (totalBufferLength % 64);
00075     else
00076         padding = 56 + (64 - (totalBufferLength % 64));
00077     buffer[bufferLength++] = 0x80;
00078     padding--;
00079     if(padding+bufferLength == 56)
00080         memset(&buffer[bufferLength], 0, padding);
00081     else
00082     {
00083         memset(&buffer[bufferLength], 0, 64-bufferLength);
00084         computeRounds(&a, &b, &c, &d, buffer);
00085         memset(buffer, 0, 56);
00086     }
00087     uint64_t lengthBit = totalBufferLength << 3;
00088     uint32_t lengthBitLow = lengthBit;
00089     uint32_t lengthBitHigh = lengthBit >> 32;
00090     memcpy(&buffer[56], &lengthBitLow, 4);
00091     memcpy(&buffer[60], &lengthBitHigh, 4);
00092     computeRounds(&a, &b, &c, &d, buffer);
00093 
00094     hash2[0] = a;
00095     hash2[1] = b;
00096     hash2[2] = c;
00097     hash2[3] = d;
00098     // reset state
00099     a = A;
00100     b = B;
00101     c = C;
00102     d = D;
00103     totalBufferLength = 0;
00104     bufferLength = 0;
00105 }
00106 
00107 
00108 void MD4::computeHash(uint8_t *hash, uint8_t *data, uint32_t length)
00109 {
00110     uint32_t *hash2 = (uint32_t*)hash;
00111     uint64_t lengthBit = length << 3;
00112     uint16_t padding;
00113     if(length % 64 < 56)
00114         padding = 56 - (length % 64);
00115     else
00116         padding = 56 + (64 - (length % 64));
00117         
00118     uint32_t a = A, b = B, c = C, d = D;
00119     while(length >= 64)
00120     {
00121         computeRounds(&a, &b, &c, &d, data);
00122         data += 64;
00123         length -= 64;
00124     }
00125     uint8_t buffer[64];
00126     memcpy(buffer, data, length);
00127     buffer[length++] = 0x80;
00128     padding--;
00129     if(padding+length == 56)
00130         memset(&buffer[length], 0, padding);
00131     else
00132     {
00133         memset(&buffer[length], 0, 64-length);
00134         computeRounds(&a, &b, &c, &d, data);
00135         memset(buffer, 0, 56);
00136     }
00137 
00138     uint32_t lengthBitLow = lengthBit;
00139     uint32_t lengthBitHigh = lengthBit >> 32;
00140     memcpy(&buffer[56], &lengthBitLow, 4);
00141     memcpy(&buffer[60], &lengthBitHigh, 4);
00142     
00143     computeRounds(&a, &b, &c, &d, buffer);
00144     
00145     hash2[0] = a;
00146     hash2[1] = b;
00147     hash2[2] = c;
00148     hash2[3] = d;
00149 }
00150 
00151 void MD4::computeRounds(uint32_t *a2, uint32_t *b2, uint32_t *c2, uint32_t *d2, uint8_t *buffer)
00152 {
00153     uint32_t a = *a2, b = *b2, c = *c2, d = *d2;
00154     uint32_t tmpA = a, tmpB = b, tmpC = c, tmpD = d;
00155 
00156     uint32_t *x = (uint32_t*)buffer;
00157        
00158     // Round 1
00159     ROUND1(a,b,c,d,x[0],3);     ROUND1(d,a,b,c,x[1],7);     ROUND1(c,d,a,b,x[2],11);    ROUND1(b,c,d,a,x[3],19);
00160     ROUND1(a,b,c,d,x[4],3);     ROUND1(d,a,b,c,x[5],7);     ROUND1(c,d,a,b,x[6],11);    ROUND1(b,c,d,a,x[7],19);
00161     ROUND1(a,b,c,d,x[8],3);     ROUND1(d,a,b,c,x[9],7);     ROUND1(c,d,a,b,x[10],11);   ROUND1(b,c,d,a,x[11],19);
00162     ROUND1(a,b,c,d,x[12],3);    ROUND1(d,a,b,c,x[13],7);    ROUND1(c,d,a,b,x[14],11);   ROUND1(b,c,d,a,x[15],19);
00163     
00164     // Round 2      
00165     ROUND2(a,b,c,d,x[0],3);     ROUND2(d,a,b,c,x[4],5);     ROUND2(c,d,a,b,x[8],9);     ROUND2(b,c,d,a,x[12],13);
00166     ROUND2(a,b,c,d,x[1],3);     ROUND2(d,a,b,c,x[5],5);     ROUND2(c,d,a,b,x[9],9);     ROUND2(b,c,d,a,x[13],13);
00167     ROUND2(a,b,c,d,x[2],3);     ROUND2(d,a,b,c,x[6],5);     ROUND2(c,d,a,b,x[10],9);    ROUND2(b,c,d,a,x[14],13);
00168     ROUND2(a,b,c,d,x[3],3);     ROUND2(d,a,b,c,x[7],5);     ROUND2(c,d,a,b,x[11],9);    ROUND2(b,c,d,a,x[15],13);
00169     
00170     // Round 3      
00171     ROUND3(a,b,c,d,x[0],3);     ROUND3(d,a,b,c,x[8],9);     ROUND3(c,d,a,b,x[4],11);    ROUND3(b,c,d,a,x[12],15);
00172     ROUND3(a,b,c,d,x[2],3);     ROUND3(d,a,b,c,x[10],9);    ROUND3(c,d,a,b,x[6],11);    ROUND3(b,c,d,a,x[14],15);
00173     ROUND3(a,b,c,d,x[1],3);     ROUND3(d,a,b,c,x[9],9);     ROUND3(c,d,a,b,x[5],11);    ROUND3(b,c,d,a,x[13],15);
00174     ROUND3(a,b,c,d,x[3],3);     ROUND3(d,a,b,c,x[11],9);    ROUND3(c,d,a,b,x[7],11);    ROUND3(b,c,d,a,x[15],15);
00175      
00176 
00177     *a2 = a + tmpA;
00178     *b2 = b + tmpB;
00179     *c2 = c + tmpC;
00180     *d2 = d + tmpD;
00181 }