void wc_Md4Final(Md4* md4, byte* hash) { byte* local = (byte*)md4->buffer; AddLength(md4, md4->buffLen); /* before adding pads */ local[md4->buffLen++] = 0x80; /* add 1 */ /* pad with zeros */ if (md4->buffLen > MD4_PAD_SIZE) { XMEMSET(&local[md4->buffLen], 0, MD4_BLOCK_SIZE - md4->buffLen); md4->buffLen += MD4_BLOCK_SIZE - md4->buffLen; #ifdef BIG_ENDIAN_ORDER ByteReverseWords(md4->buffer, md4->buffer, MD4_BLOCK_SIZE); #endif Transform(md4); md4->buffLen = 0; } XMEMSET(&local[md4->buffLen], 0, MD4_PAD_SIZE - md4->buffLen); /* put lengths in bits */ md4->hiLen = (md4->loLen >> (8*sizeof(md4->loLen) - 3)) + (md4->hiLen << 3); md4->loLen = md4->loLen << 3; /* store lengths */ #ifdef BIG_ENDIAN_ORDER ByteReverseWords(md4->buffer, md4->buffer, MD4_BLOCK_SIZE); #endif /* ! length ordering dependent on digest endian type ! */ XMEMCPY(&local[MD4_PAD_SIZE], &md4->loLen, sizeof(word32)); XMEMCPY(&local[MD4_PAD_SIZE + sizeof(word32)], &md4->hiLen, sizeof(word32)); Transform(md4); #ifdef BIG_ENDIAN_ORDER ByteReverseWords(md4->digest, md4->digest, MD4_DIGEST_SIZE); #endif XMEMCPY(hash, md4->digest, MD4_DIGEST_SIZE); wc_InitMd4(md4); /* reset state */ }
int md4_test(void) { Md4 md4; byte hash[MD4_DIGEST_SIZE]; testVector a, b, c, d, e, f, g; testVector test_md4[7]; int times = sizeof(test_md4) / sizeof(testVector), i; a.input = ""; a.output = "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31\xb7\x3c\x59\xd7\xe0\xc0\x89" "\xc0"; a.inLen = XSTRLEN(a.input); a.outLen = XSTRLEN(a.output); b.input = "a"; b.output = "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46\x24\x5e\x05\xfb\xdb\xd6\xfb" "\x24"; b.inLen = XSTRLEN(b.input); b.outLen = XSTRLEN(b.output); c.input = "abc"; c.output = "\xa4\x48\x01\x7a\xaf\x21\xd8\x52\x5f\xc1\x0a\xe8\x7a\xa6\x72" "\x9d"; c.inLen = XSTRLEN(c.input); c.outLen = XSTRLEN(c.output); d.input = "message digest"; d.output = "\xd9\x13\x0a\x81\x64\x54\x9f\xe8\x18\x87\x48\x06\xe1\xc7\x01" "\x4b"; d.inLen = XSTRLEN(d.input); d.outLen = XSTRLEN(d.output); e.input = "abcdefghijklmnopqrstuvwxyz"; e.output = "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd\xee\xa8\xed\x63\xdf\x41\x2d" "\xa9"; e.inLen = XSTRLEN(e.input); e.outLen = XSTRLEN(e.output); f.input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345" "6789"; f.output = "\x04\x3f\x85\x82\xf2\x41\xdb\x35\x1c\xe6\x27\xe1\x53\xe7\xf0" "\xe4"; f.inLen = XSTRLEN(f.input); f.outLen = XSTRLEN(f.output); g.input = "1234567890123456789012345678901234567890123456789012345678" "9012345678901234567890"; g.output = "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19\x9c\x3e\x7b\x16\x4f\xcc\x05" "\x36"; g.inLen = XSTRLEN(g.input); g.outLen = XSTRLEN(g.output); test_md4[0] = a; test_md4[1] = b; test_md4[2] = c; test_md4[3] = d; test_md4[4] = e; test_md4[5] = f; test_md4[6] = g; wc_InitMd4(&md4); for (i = 0; i < times; ++i) { wc_Md4Update(&md4, (byte*)test_md4[i].input, (word32)test_md4[i].inLen); wc_Md4Final(&md4, hash); if (XMEMCMP(hash, test_md4[i].output, MD4_DIGEST_SIZE) != 0) return -205 - i; } return 0; }