2012-09-07 27 views
0

我正在使用C++中的程序來執行md5校驗和。我這樣做主要是因爲我認爲我會學習關於C++,校驗和,OOP以及其他任何我遇到的很多不同的事情。我如何使用c/C++來填充我的md5消息

我有麻煩檢查總和,我認爲問題是在功能padbuff做消息填充。

#include "HashMD5.h" 

int leftrotate(int x, int y); 
void padbuff(uchar * buffer); 

//HashMD5 constructor 
HashMD5::HashMD5() 
{ 
    Type = "md5"; 
    Hash = ""; 
} 

HashMD5::HashMD5(const char * hashfile) 
{ 
    Type = "md5"; 
    std::ifstream filestr; 
    filestr.open(hashfile, std::fstream::in | std::fstream::binary); 
    if(filestr.fail()) 
    { 
    std::cerr << "File " << hashfile << " was not opened.\n"; 
    std::cerr << "Open failed with error "; 
    } 
} 

std::string HashMD5::GetType() 
{ 
    return this->Type; 
} 

std::string HashMD5::GetHash() 
{ 
    return this->Hash; 
} 

bool HashMD5::is_open() 
{ 
    return !((this->filestr).fail()); 
} 

void HashMD5::CalcHash(unsigned int * hash) 
{ 
    unsigned int *r, *k; 
    int r2[4] = {0, 4, 9, 15}; 
    int r3[4] = {0, 7, 12, 19}; 
    int r4[4] = {0, 4, 9, 15}; 
    uchar * buffer; 
    int bufLength = (2<<20)*8; 
    int f,g,a,b,c,d, temp; 
    int *head; 
    uint32_t maxint = 1<<31; 

    //Initialized states 
    unsigned int h[4]{ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476}; 

    r = new unsigned int[64]; 
    k = new unsigned int[64]; 
    buffer = new uchar[bufLength]; 
    if(r==NULL || k==NULL || buffer==NULL) 
    { 
    std::cerr << "One of the dyn alloc failed\n"; 
    } 

    // r specifies the per-round shift amounts 
    for(int i = 0; i<16; i++) 
    r[i] = 7 + (5 * ((i)%4)); 

    for(int i = 16; i < 32; i++) 
    r[i] = 5 + r2[i%4]; 

    for(int i = 32; i< 48; i++) 
    r[i] = 4 + r3[i%4]; 

    for(int i = 48; i < 63; i++) 
    r[i] = 6 + r4[i%4]; 

    for(int i = 0; i < 63; i++) 
    { 
    k[i] = floor(fabs(sin(i + 1)) * maxint); 
    } 

    while(!(this->filestr).eof()) 
    { 
    //Read in 512 bits 
    (this->filestr).read((char *)buffer, bufLength-512); 

    padbuff(buffer); 

    //The 512 bits are now 16 32-bit ints 
    head = (int *)buffer; 

    for(int i = 0; i < 64; i++) 
    { 
     if(i >=0 && i <=15) 
     { 
     f = (b & c) | (~b & d); 
     g = i; 
     } 
     else if(i >= 16 && i <=31) 
     { 
     f = (d & b) | (~d & b); 
     g = (5*i +1) % 16; 
     } 
     else if(i >=32 && i<=47) 
     { 
     f = b^c^d; 
     g = (3*i + 5) % 16; 
     } 
     else 
     { 
     f = c^(b | ~d); 
     g = (7*i) % 16; 
     } 

     temp = d; 
     d = c; 
     c = b; 
     b = b + leftrotate((a + f + k[i] + head[g]), r[i]); 
     a = temp; 

    } 

    h[0] +=a; 
    h[1] +=b; 
    h[2] +=c; 
    h[3] +=d;   
    } 


    delete[] r; 
    delete[] k; 

    hash = h; 
} 

int leftrotate(int x, int y) 
{ 
    return(x<<y) | (x >> (32 -y)); 
} 

void padbuff(uchar* buffer) 
{ 
    int lack; 
    int length = strlen((char *)buffer); 
    uint64_t mes_size = length % UINT64_MAX; 
    if((lack = (112 - (length % 128)))>0) 
    { 
    *(buffer + length) = ('\0'+1) << 3; 
    memset((buffer + length + 1),0x0,lack); 
    memcpy((void*)(buffer+112),(void *)&mes_size, 64); 
    } 

} 

在我的測試程序中,我在一條空的消息上運行它。因此,在padbuff中的length爲0.然後,當我做*(buffer + length) = ('\0'+1) << 3;時,我試圖用1填充消息。在Netbeans調試器中,我將buffer作爲uint64_t並且它說buffer=8。我試圖把1 bit放在最重要的緩衝區,所以我的演員應該是UINT64_MAX。它不是,所以我很困惑我的填充代碼如何工作。有人能告訴我我在做什麼以及我應該在padbuff中做什麼嗎?謝謝,我對這個漫長的問題表示歉意。

只是爲了清楚填充應該做什麼,這裏是來自Wikipedia的填充摘錄: 消息被填充以使其長度可以被512整除。填充的工作原理如下:首先一個位,1被添加到消息的末尾。接着是所需要的零,以使消息的長度多達64位,少於512的倍數。其餘位填充64位,表示原始消息的長度,模264。

我主要是在尋找padbuff的幫助,但是因爲我正在努力學習所有的評論都很感謝。

回答

1

第一個問題是你做了什麼:

  1. length % UINT64_MAX沒有意義,因爲在所有的長度是字節,最大的是你可以在UINT64存儲的值。
  2. 你認爲把1位放在最重要的位上會給出最大值。事實上,你需要把所有的位都放1。
  3. 您將1移3。它只是字節長度的一半。
  4. 緩衝區指向的字節在小端中是最不重要的。 (因爲調試器顯示8,所以我假設你有小端)。

第二個問題應該如何工作。 我不知道究竟padbuff應該做的,但如果你想墊,並得到UINT64_MAX,你需要的東西是這樣的:

int length = strlen((char *)buffer); 
int len_of_padding = sizeof(uint64_t) - length % sizeof(uint64_t); 
if(len_of_padding > 0) 
{ 
    memset((void*)(buffer + length), 0xFF, len_of_padding); 
} 

你有兩個UINT64值的長度工作。可能是你想零下一個:

uint64_t *after = (uint64_t*)(buffer + length + len_of_padding); 
*after = 0; 
相關問題