前言

上一篇文章说了如何使用 OpenSSL 进行 Base64 编码,这篇文章来说一说如何进行 MD5 计算

MD5

MD5(Message-Digest Algorithm 5,消息摘要算法第五版)是一种广泛使用的密码散列函数,用于生成一个128位(16字节)的哈希值或消息摘要。

通常被用来验证文件的完整性。

原理

  • 填充:如果输入数据的长度(以比特计)对512取余的结果不是448,则需要进行填充,使得其长度达到512比特的倍数减去64比特。填充的第一个比特是1,其余都是0。
  • 附加原始长度:在填充后的数据后面追加一个64比特的块,表示原始消息的长度(不包含填充)。这样做的目的是确保即使两个不同的消息仅在最后一个比特不同,它们也会有不同的摘要。
  • 初始化缓冲区:使用四个32位整数A、B、C、D来初始化缓冲区,这些值是固定的常量。
  • 处理消息:对于每个512比特的块,执行一系列复杂的非线性变换。这个过程分为四轮,每一轮又包含了16个基本的操作,总共64次操作。每次操作都涉及到对当前块的一部分和缓冲区中的值进行计算。

上代码

使用 MD5 的大致流程是:先创建一个上下文,然后进行初始化,接着填入数据,最后计算结果。

代码如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
string data = "测试 Md5 数据";
unsigned char out[1024] = {0};

MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, data.data(), data.length());
MD5_Final(out, &ctx);

for (int i = 0; i < 16; ++i) {
    cout << hex << (int)out[i];
}
1
43603754bc1756949ea186ef2394b2

更简单的方法

每次计算 MD5 都要创建上下文挺麻烦的,而且这些步骤都是固定的。

所以 OpenSSL 提供了一个简单方法可以直接使用,不需要麻烦的创建上下文,初始化的一堆操作。

如下所示

1
2
3
4
5
6
7
8
string data = "测试 Md5 数据";
unsigned char out[1024] = {0};

MD5(reinterpret_cast<const unsigned char*>(data.data()), data.length(), out);

for (int i = 0; i < 16; ++i) {
    cout << hex << (int)out[i];
}
1
43603754bc1756949ea186ef2394b2

总结

由于其速度快且易于实现,MD5仍然被广泛应用于非安全性关键领域,例如检查文件完整性或版本控制系统的快照比较等。 但是在涉及加密存储重要隐私数据时就不太合适了。