2011-10-02 40 views
30

Tôi đã tìm thấy một số mã md5 bao gồm các nguyên mẫu sau ...Làm thế nào để tạo một băm md5 của một chuỗi trong C?

Tôi đã cố gắng tìm ra nơi tôi phải đặt chuỗi tôi muốn băm, những chức năng nào tôi cần gọi và nơi để tìm chuỗi khi nó đã được băm. Tôi đang bối rối liên quan đến những gì uint32 buf [4] và uint32 bit [2] là trong cấu trúc.

struct MD5Context { 
    uint32 buf[4]; 
    uint32 bits[2]; 
    unsigned char in[64]; 
}; 

/* 
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious 
* initialization constants. 
*/ 
void MD5Init(struct MD5Context *context); 

/* 
* Update context to reflect the concatenation of another buffer full 
* of bytes. 
*/ 
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len); 

/* 
* Final wrapup - pad to 64-byte boundary with the bit pattern 
* 1 0* (64-bit count of bits processed, MSB-first) 
*/ 
void MD5Final(unsigned char digest[16], struct MD5Context *context); 

/* 
* The core of the MD5 algorithm, this alters an existing MD5 hash to 
* reflect the addition of 16 longwords of new data. MD5Update blocks 
* the data and converts bytes into longwords for this routine. 
*/ 
void MD5Transform(uint32 buf[4], uint32 const in[16]); 

Trả lời

35

Tôi không biết thư viện cụ thể này, nhưng tôi đã sử dụng các cuộc gọi rất giống nhau. Vì vậy, đây là dự đoán tốt nhất của tôi:

unsigned char digest[16]; 
const char* string = "Hello World"; 
struct MD5Context context; 
MD5Init(&context); 
MD5Update(&context, string, strlen(string)); 
MD5Final(digest, &context); 

Điều này sẽ cung cấp cho bạn một biểu diễn số nguyên của hàm băm. Sau đó bạn có thể biến điều này thành một biểu diễn hex nếu bạn muốn truyền nó như một chuỗi.

char md5string[33]; 
for(int i = 0; i < 16; ++i) 
    sprintf(&md5string[i*2], "%02x", (unsigned int)digest[i]); 
+0

Nice nghĩ, trưng bày các chuyển đổi của các hash thành một chuỗi. – dmckee

+0

Hmm, tôi nhận được 'lỗi: kích thước lưu trữ của‘ ngữ cảnh ’không được xác định’ Tôi bao gồm '#include ' –

+0

@SSHTi tôi không tin rằng mã OPs đang sử dụng openssl. –

5

Thành thật mà nói, các nhận xét đi kèm với nguyên mẫu có vẻ đủ rõ ràng. Một cái gì đó như thế này nên làm như lừa:

void compute_md5(char *str, unsigned char digest[16]) { 
    MD5Context ctx; 
    MD5Init(&ctx); 
    MD5Update(&ctx, str, strlen(str)); 
    MD5Final(digest, &ctx); 
} 

nơi str là một chuỗi C bạn muốn băm của, và digest là kết quả MD5 tiêu hóa.

1

Nó sẽ xuất hiện mà bạn nên

  • Tạo một struct MD5context và vượt qua nó để MD5Init để có được nó vào một điều kiện khởi đầu đúng đắn
  • Gọi MD5Update với bối cảnh và dữ liệu của bạn
  • Gọi MD5Final để nhận được kết quả băm

Ba chức năng này và định nghĩa cấu trúc tạo một giao diện trừu tượng tốt đẹp cho thuật toán băm. Tôi không chắc chắn lý do tại sao bạn được hiển thị chức năng chuyển đổi lõi trong tiêu đề đó vì bạn có lẽ không nên tương tác trực tiếp với nó.

Tác giả có thể thực hiện ẩn nấp nhiều hơn bằng cách làm cho cấu trúc trở thành một loại trừu tượng, nhưng sau đó bạn sẽ bị buộc phải phân bổ cấu trúc trên heap mỗi lần (trái ngược với bây giờ bạn có thể đặt nó trên nếu bạn muốn).

7

Như câu trả lời khác đã đề cập, các cuộc gọi sau đây sẽ tính toán hash:

MD5Context md5; 
MD5Init(&md5); 
MD5Update(&md5, data, datalen); 
MD5Final(digest, &md5); 

Mục đích của việc tách nó ra thành nhiều chức năng là để cho bạn dòng bộ dữ liệu lớn.

Ví dụ: nếu bạn đang băm nhỏ tệp 10 GB và nó không vừa với ram, dưới đây là cách bạn thực hiện. Bạn sẽ đọc tệp theo các đoạn nhỏ hơn và gọi số MD5Update trên chúng.

MD5Context md5; 
MD5Init(&md5); 

fread(/* Read a block into data. */) 
MD5Update(&md5, data, datalen); 

fread(/* Read the next block into data. */) 
MD5Update(&md5, data, datalen); 

fread(/* Read the next block into data. */) 
MD5Update(&md5, data, datalen); 

... 

// Now finish to get the final hash value. 
MD5Final(digest, &md5); 
31

Dưới đây là một ví dụ hoàn chỉnh:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#if defined(__APPLE__) 
# define COMMON_DIGEST_FOR_OPENSSL 
# include <CommonCrypto/CommonDigest.h> 
# define SHA1 CC_SHA1 
#else 
# include <openssl/md5.h> 
#endif 

char *str2md5(const char *str, int length) { 
    int n; 
    MD5_CTX c; 
    unsigned char digest[16]; 
    char *out = (char*)malloc(33); 

    MD5_Init(&c); 

    while (length > 0) { 
     if (length > 512) { 
      MD5_Update(&c, str, 512); 
     } else { 
      MD5_Update(&c, str, length); 
     } 
     length -= 512; 
     str += 512; 
    } 

    MD5_Final(digest, &c); 

    for (n = 0; n < 16; ++n) { 
     snprintf(&(out[n*2]), 16*2, "%02x", (unsigned int)digest[n]); 
    } 

    return out; 
} 

    int main(int argc, char **argv) { 
     char *output = str2md5("hello", strlen("hello")); 
     printf("%s\n", output); 
     free(output); 
     return 0; 
    } 
+0

Hãy coi chừng, việc sử dụng '16 * 2' trong' sprintf' không hợp lệ, bạn nên sử dụng '3' thay thế (giả sử rằng' out' đủ lớn). – Lekensteyn

+1

'MD5_Update' lấy độ dài theo đơn vị byte. Bạn cũng có thể sử dụng 'MD5 (str, strlen (str), digest);' vì bạn biết độ dài onbeforehand. ('MD5' có sẵn trong tất cả các phiên bản OpenSSL theo trang hướng dẫn sử dụng). – Lekensteyn

Các vấn đề liên quan