C中的MD4实现 - 一致但错误的输出

时间:2009-06-22 20:44:15

标签: c hash cryptography

我似乎无法让我的md4实现正常工作。关于什么是错的任何想法?另外,我不是在这个项目被分配到的班级。我只是为了踢。我也宁愿你给我提示而不是直截了当的回答。谢谢!

编辑:具体(我知道),我的输出与RFC1320提供的测试向量不匹配。例如:

From RFC -- MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d 
Mine -- DIGEST: ed763b1deb753a9d8fc7e3f1a653a954 -- 32 BYTES

然而,我从输出哈希值(32字节)中获得正确的大小

如果还有其他需要澄清的内容,请发表评论!

/**
  hThreat @ http://auburn.edu/~dac0007/blog/
  "MD4 hashing algorithm -- beginning project 1"
**/

// References
    //http://tools.ietf.org/html/rfc1320

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// define 3 auxiliary functions (Copied from RFC1320)
#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 ROTL(x, n) (((x) << (n)) | ((x) >> (32-(n))))

BYTE* stepOne(int bitLen, int byteLen, BYTE* pMsg)
{

    /*  STEP ONE
     *
     **/
    printf("\n\n\n STEP 1\n--------\n");

    // find amount to pad message (assuming it's not already 448 bits)
    for(int i=0; i<512 && bitLen%512!=448; i++)
        bitLen++;

    // amount of data that will be appended
    int tPad = (bitLen/8)-byteLen;

    // create a memory block of appropriate size
    BYTE* bloc = (BYTE*)malloc(tPad+byteLen);   // ie 56 bytes
    memset(bloc,0,tPad+byteLen);                // zero everything out, 0x80, 0x00,...,0x00
    printf("Created %d BYTE block\n",tPad+byteLen);

    // Set elements of bloc = to elements of pMsg
    for(int i=0; i<byteLen; i++)
        bloc[i] = pMsg[i];
    printf("Set bloc <=> pMsg; bloc = \"%s\"\n",(char*)bloc);

    // Pad bloc to spec,
    bloc[byteLen] = 0x80;                       // first byte should be: 1000 0000b
    // memset took care of the rest..
    printf("-> %s PADDED TO %d BYTES\n","bloc", byteLen+tPad);
    printf("-> bloc = \"%s\"\n",(char*)bloc);

    // Set pMsg = bloc
    pMsg = bloc;
    printf("Set pMsg = bloc; pMsg = \"%s\"\n",(char*)pMsg);

    return pMsg;
    // end step 1
}

BYTE* stepTwo(int bitLen, int byteLen, BYTE* pMsg)
{
    printf("\n\n\n STEP 2\n--------\n");
    printf("Set pMsg = bloc; pMsg = \"%s\"\n",(char*)pMsg);

    // Assuming that the original byteLen of message < 2^64
    int originalLen = byteLen;
    int tByteLen = (bitLen/8);

    // create 64 bit representation of byteLen (b bits)
    unsigned long long int uint64 = (unsigned long long int)originalLen*8;
    int pdSz = sizeof(uint64);

    // create a memory block of appropriate size (Multiple of 512/8)
    BYTE* bloc = (BYTE*)malloc(tByteLen + pdSz);// ie 56 + 8 = 64 bytes
    memset(bloc,0,tByteLen + pdSz);             // zero everything out
    printf("Created %d BYTE block\n",tByteLen+pdSz);

    // Set elements of bloc = to elements of pMsg
    for(int i=0; i<tByteLen; i++)
        bloc[i] = pMsg[i];
    printf("Set bloc <=> pMsg; bloc = \"%s\"\n",(char*)bloc);

    // Append low order DWORD first, as specified
    for(int i=0; i<pdSz; i++)
        bloc[i+tByteLen] = (BYTE)(uint64 >> i*pdSz);

    printf("-> %s PADDED TO %d BYTES\n","bloc", tByteLen+pdSz);
    printf("-> bloc = \"%s\"\n",(char*)bloc);

    // Set pMsg = bloc
    pMsg = bloc;
    printf("Set pMsg = bloc; pMsg = \"%s\"\n",(char*)pMsg);

    return pMsg;
    // step 2 complete
}

void stepThreeFourFive(int bitLen, BYTE* pMsg)
{
    /*  STEP THREE
     *
     **/
    printf("\n\n\n STEP 3\n--------\n");

    // Initialize 4 DWORD buffer
    DWORD A = 0x67452301;
    DWORD B = 0xefcdab89;
    DWORD C = 0x98badcfe;
    DWORD D = 0x10325476;

    DWORD AA;
    DWORD BB;
    DWORD CC;
    DWORD DD;

    printf("(Defined 4 DWORD buffer)");
    // end step 3 

    /*  STEP FOUR
     *
     **/
    printf("\n\n\n STEP 4\n--------\n");

    // process each 16-word block
    BYTE* X = (BYTE*)malloc(4*sizeof(DWORD));

    for(int i=0; i<((bitLen/8)/32)-1; i++)
    {
        // Copy block i into X
        for(int j=0; j<16; j++)
            X[j] = pMsg[i*16+j];

        // save to spec
        AA = A;
        BB = B;
        CC = C;
        DD = D;

        /* Round 1 */
        printf("ROUND 1 ");
        A = ROTL((A + F(B,C,D) + X[0]),3);
        D = ROTL((D + F(A,B,C) + X[1]),7);
        C = ROTL((C + F(D,A,B) + X[2]),11);
        B = ROTL((B + F(C,D,A) + X[3]),19);
        //
        A = ROTL((A + F(B,C,D) + X[4]),3);
        D = ROTL((D + F(A,B,C) + X[5]),7);
        C = ROTL((C + F(D,A,B) + X[6]),11);
        B = ROTL((B + F(C,D,A) + X[7]),19);
        //
        A = ROTL((A + F(B,C,D) + X[8]),3);
        D = ROTL((D + F(A,B,C) + X[9]),7);
        C = ROTL((C + F(D,A,B) + X[10]),11);
        B = ROTL((B + F(C,D,A) + X[11]),19);
        //
        A = ROTL((A + F(B,C,D) + X[12]),3);
        D = ROTL((D + F(A,B,C) + X[13]),7);
        C = ROTL((C + F(D,A,B) + X[14]),11);
        B = ROTL((B + F(C,D,A) + X[15]),19);
        printf("COMPLETE\n");

        /* Round 2 */
        printf("ROUND 2 ");
        A = ROTL((A + G(B,C,D) + X[0] + 0x5A827999),3);
        D = ROTL((D + G(A,B,C) + X[4] + 0x5A827999),5);
        C = ROTL((C + G(D,A,B) + X[8] + 0x5A827999),9);
        B = ROTL((B + G(C,D,A) + X[12] + 0x5A827999),13);
        //
        A = ROTL((A + G(B,C,D) + X[1] + 0x5A827999),3);
        D = ROTL((D + G(A,B,C) + X[5] + 0x5A827999),5);
        C = ROTL((C + G(D,A,B) + X[9] + 0x5A827999),9);
        B = ROTL((B + G(C,D,A) + X[13] + 0x5A827999),13);
        //
        A = ROTL((A + G(B,C,D) + X[2] + 0x5A827999),3);
        D = ROTL((D + G(A,B,C) + X[6] + 0x5A827999),5);
        C = ROTL((C + G(D,A,B) + X[10] + 0x5A827999),9);
        B = ROTL((B + G(C,D,A) + X[14] + 0x5A827999),13);
        //
        A = ROTL((A + G(B,C,D) + X[3] + 0x5A827999),3);
        D = ROTL((D + G(A,B,C) + X[7] + 0x5A827999),5);
        C = ROTL((C + G(D,A,B) + X[11] + 0x5A827999),9);
        B = ROTL((B + G(C,D,A) + X[15] + 0x5A827999),13);
        printf("COMPLETE\n");

            /* Round 3 */
        printf("ROUND 3 ");
        A = ROTL((A + H(B,C,D) + X[0] + 0x6ED9EBA1),3);
        D = ROTL((D + H(A,B,C) + X[8] + 0x6ED9EBA1),9);
        C = ROTL((C + H(D,A,B) + X[4] + 0x6ED9EBA1),11);
        B = ROTL((B + H(C,D,A) + X[12] + 0x6ED9EBA1),15);
        //
        A = ROTL((A + H(B,C,D) + X[2] + 0x6ED9EBA1),3);
        D = ROTL((D + H(A,B,C) + X[10] + 0x6ED9EBA1),9);
        C = ROTL((C + H(D,A,B) + X[6] + 0x6ED9EBA1),11);
        B = ROTL((B + H(C,D,A) + X[14] + 0x6ED9EBA1),15);
        //
        A = ROTL((A + H(B,C,D) + X[1] + 0x6ED9EBA1),3);
        D = ROTL((D + H(A,B,C) + X[9] + 0x6ED9EBA1),9);
        C = ROTL((C + H(D,A,B) + X[5] + 0x6ED9EBA1),11);
        B = ROTL((B + H(C,D,A) + X[13] + 0x6ED9EBA1),15);
        //
        A = ROTL((A + H(B,C,D) + X[3] + 0x6ED9EBA1),3);
        D = ROTL((D + H(A,B,C) + X[11] + 0x6ED9EBA1),9);
        C = ROTL((C + H(D,A,B) + X[7] + 0x6ED9EBA1),11);
        B = ROTL((B + H(C,D,A) + X[15] + 0x6ED9EBA1),15);
        printf("COMPLETE\n\n");

        // increment registers
        A = A + AA;
        B = B + BB;
        C = C + CC;
        D = D + DD;
    }
    // end step 4

    /*  STEP FIVE
     *
     **/
    printf("\n\n STEP 5\n--------\n");

    // Create a 16 byte buffer for the digest
    BYTE* digest = (BYTE*)malloc(4*sizeof(DWORD));
    memset(digest,0,4*sizeof(DWORD));

    /* output beginning with low order byte of A and ending with high order byte of D */

    // fill the buffer

    for(int i=0; i<sizeof(DWORD); i++)
    {
        digest[i] = (BYTE)(A >> i);
        digest[i+4] = (BYTE)(B >> i);
        digest[i+8] = (BYTE)(C >> i);
        digest[i+12] = (BYTE)(D >> i);
    }   

    // print the digest
    printf("DIGEST: ");
    for(int i=0; i<(4*sizeof(DWORD)); i++)
        printf("%x", digest[i]);

    printf(" -- %d BYTES", strlen((char*)digest));

    free(digest);
    free(X);

    // end step 5

}

int main()
{
    printf("\n STEP 0\n--------\n");

    BYTE msg[] = "abc";

    int byteLen = strlen((char*)msg);
    int bitLen = byteLen*8;

    // get a pointer to the byte containing message
    BYTE* pMsg = &msg[0];

    printf("Message to Digest: \"%s\"\n", pMsg);
    printf("Size of Message: %d", byteLen);

    pMsg = stepOne(bitLen, byteLen, pMsg);
    pMsg = stepTwo(448, byteLen, pMsg);
    stepThreeFourFive(512, pMsg);

    while(true)
        Sleep(1000);
    return 0;
}

1 个答案:

答案 0 :(得分:2)

为什么不在每一步打印A,B,C,D的结果,并与每行的标准实施结果(RFC 1320)进行比较。

这是我过去使用MD5在调整生成方式或更改实现语言时所做的。