/* * * Author: George Mossessian * https://rosettacode.org/wiki/MD4 * * The MD4 hash algorithm, as described in https://tools.ietf.org/html/rfc1320 */ #include #include #include #include "md4.h" typedef struct string{ char *c; int len; char sign; }string; static uint32_t *MD4Digest(uint32_t *w, int len); static void setMD4Registers(uint32_t AA, uint32_t BB, uint32_t CC, uint32_t DD); static uint32_t changeEndianness(uint32_t x); static void resetMD4Registers(void); static string stringCat(string first, string second); static string uint32ToString(uint32_t l); static uint32_t stringToUint32(string s); static const char *BASE16 = "0123456789abcdef="; #define F(X,Y,Z) (((X)&(Y))|((~(X))&(Z))) #define G(X,Y,Z) (((X)&(Y))|((X)&(Z))|((Y)&(Z))) #define H(X,Y,Z) ((X)^(Y)^(Z)) #define LEFTROTATE(A,N) ((A)<<(N))|((A)>>(32-(N))) #define MD4ROUND1(a,b,c,d,x,s) a += F(b,c,d) + x; a = LEFTROTATE(a, s); #define MD4ROUND2(a,b,c,d,x,s) a += G(b,c,d) + x + (uint32_t)0x5A827999; a = LEFTROTATE(a, s); #define MD4ROUND3(a,b,c,d,x,s) a += H(b,c,d) + x + (uint32_t)0x6ED9EBA1; a = LEFTROTATE(a, s); static uint32_t A = 0x67452301; static uint32_t B = 0xefcdab89; static uint32_t C = 0x98badcfe; static uint32_t D = 0x10325476; string newString(char * c, int t) { string r; int i; if(c!=NULL){ r.len = (t<=0)?strlen(c):t; r.c=(char *)malloc(sizeof(char)*(r.len+1)); for(i=0; i>4)]; out.c[j++]=BASE16[(in.c[i] & 0x0F)]; } out.c[j]='\0'; return out; } string uint32ToString(uint32_t l){ string s = newString(NULL,4); int i; for(i=0; i<4; i++){ s.c[i] = (l >> (8*(3-i))) & 0xFF; } return s; } uint32_t stringToUint32(string s){ uint32_t l; int i; l=0; for(i=0; i<4; i++){ l = l|(((uint32_t)((unsigned char)s.c[i]))<<(8*(3-i))); } return l; } char *MD4(char *str, int len){ string m=newString(str, len); string digest; uint32_t *w; uint32_t *hash; uint64_t mlen=m.len; unsigned char oneBit = 0x80; int i, wlen; string s = newString((char *)&oneBit,1); string ss = stringCat(m, s); free(m.c); m=ss; free(s.c); //append 0 ≤ k < 512 bits '0', such that the resulting message length in bits // is congruent to −64 ≡ 448 (mod 512)4 i=((56-m.len)%64); if(i<0) i+=64; s = newString(NULL, i); ss = stringCat(m,s); free(m.c); m=ss; free(s.c); w = malloc(sizeof(uint32_t)*(m.len/4+2)); //append length, in bits (hence <<3), least significant word first for(i=0; i>29) & 0xFFFFFFFF; wlen=i; free(m.c); //change endianness, but not for the appended message length, for some reason? for(i=0; i> 8) | ((x & 0xFF000000) >> 24); } void setMD4Registers(uint32_t AA, uint32_t BB, uint32_t CC, uint32_t DD){ A=AA; B=BB; C=CC; D=DD; } void resetMD4Registers(void){ setMD4Registers(0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476); }