取任意長度的消息,生成一個固定長度的散列值,或者叫做摘要。哈希函數的實現都是公開的,它廣泛應用於文件完整性檢測、數字簽名中。登錄密碼也有用到哈希函數,一般網站在數據庫中不是直接存儲的用戶密碼,而是密碼的哈希值,這樣即使數據庫暴露,攻擊者仍然是不知道密碼的明文的。

這要求Hash函數擁有以下特性:一是單向性,即不可逆性,我們無法從哈希值反過來得到原文。二是衝突碰撞抵禦能力,即找到兩個不同的消息原文,他們的哈希值相同,這在計算上不可行。

實際上,MD5已經不再安全。在2005年,我國山東大學王小雲教授成功破解MD5算法,使得使用普通電腦在數小時內即可找到哈希碰撞,這在國際密碼學領域引發地震。

雖然在高保密安全領域已經被其他算法替代,MD5在普通生活中仍然廣泛使用。openssl中提供了MD5的實現,下面是一個示例程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/*
* md5.cc
* - Using md5 with openSSL. MD5 returns a 128-bit hash value from a string.
*/
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/md5.h>
 
int main(int argc, char** argv) {
    MD5_CTX hash_ctx;
    char input_string[128];
    unsigned char hash_ret[16];
    int i;
 
    // check usage
    if (argc != 2) {
        fprintf(stderr, "%s <input string>\n", argv[0]);
        exit(-1);
    }
 
    // set the input string
    snprintf(input_string, sizeof(input_string), "%s\n", argv[1]);
 
    // initialize a hash context 
    MD5_Init(&hash_ctx);
 
    // update the input string to the hash context (you can update
    // more string to the hash context)
    MD5_Update(&hash_ctx, input_string, strlen(input_string));
 
    // compute the hash result
    MD5_Final(hash_ret, &hash_ctx);
 
    // print
    printf("Input string: %s", input_string);
    printf("Output string: ");
    for (i=0; i<32; ++i) {
        if (i % 2 == 0) {
            printf("%x", (hash_ret[i/2] >> 4) & 0xf);
        } else {
            printf("%x", (hash_ret[i/2]) & 0xf);
        }
    }
    printf("\n");
 
    return 0;
}

編譯Makefile:

CC=g++
CFLAGS=-Wall -g -O2
LIBS=-lcrypto
 
all: md5
 
md5: md5.cc
    $(CC) $(CFLAGS) md5.cc -o $@ $(LIBS)
 
clean:
    @rm -f md5