MD5(Message Digest Algorithm 5)摘要算法讲解

MD5(Message Digest Algorithm 5)是一种哈希函数(摘要算法),不是加密算法,它的本质作用是将任意长度的数据压缩成一个128位(16字节)固定长度的散列值(hash值),广泛用于:

  • 文件完整性校验

  • 数字签名

  • 密码摘要(如用户登录系统)

  • 防篡改检测

一、MD5 的特点

特性说明
不可逆从散列值无法还原原始数据
碰撞风险不同数据可能产生相同的 MD5 值(称为“碰撞”)
速度快算法高效,适合大批量数据处理
安全性已被发现存在漏洞(如彩虹表攻击、碰撞攻击),不适合用于高安全场景

MD5作为一种常用的摘要算法(或指纹算法),其具有以下几个重要的特点:

  • 输入任意长度信息,输出长度固定:
    MD5 可输入任意长度的信息,其输出均为128位(bit)固定长度的二进制数据
  • 运算速度快:
    MD5的运算均为32位 与、或、非、位移等位运算,因此其运算速率快,几乎不消耗CPU时间。
  • 不可逆:
    根据MD5的的散列结果无法计算原始数据(查字典除外)。
  • 碰撞性:
    原始数据与其MD5散列结果非一一对应,存在多个原始数据MD5结果相同的可能性
  • 不安全:
    2011年,RFC 6151 禁止MD5用作密钥散列消息认证码。

二、MD5 的工作流程

  1. 预处理阶段(Pre-processing)

    • 将原始信息补齐到长度为 512 的倍数(以 bit 为单位)

    • 填充方式:加一个 1 再加若干个 0,最后加上原始消息的长度(64 bit)

  2. 初始化缓冲区(Initialize MD Buffer)

    • 使用四个 32 位变量 A、B、C、D 作为寄存器,初始值为固定常数:

A = 0x67452301
B = 0xefcdab89
C = 0x98badcfe
D = 0x10325476

3.处理每个512位块(Main Loop)

  • 每个块分为 16 个 32 位子块 X[0] ~ X[15]

  • 对每个块进行 4轮操作(每轮 16 次,共 64 次迭代)

    每一轮使用一种逻辑函数(F/G/H/I):

  • F(x, y, z) = (x & y) | ((~x) & z)
    G(x, y, z) = (x & z) | (y & ~z)
    H(x, y, z) = x ^ y ^ z
    I(x, y, z) = y ^ (x | ~z)
    
  • 这些函数目的是增加非线性,提高散列的不可预测性。

  • 每步操作形式如下(以FF为例):

FF(a, b, c, d, x, s, ac) {
    a = a + F(b, c, d) + X[k] + ac;
    a = 左循环移位 s 位 (ROTATE_LEFT(a, s));
    a = a + b;
}

输出(Digest Output)

  • 所有处理完后,将 A、B、C、D 连接成最终的 128 位 MD5 散列结果

总结一下你该记住的:

名称作用
F/G/H/I4种混合逻辑函数
FF/GG/HH/II每一步的完整计算公式(包括加法、移位)
x当前的消息数据块
ac固定的魔法常数
s左移的位数,打乱顺序
a, b, c, d当前的4个变量,是 MD5 的“状态值”

三、用途举例

✅ 文件完整性验证:

对文件计算 MD5 值,下载后再算一次,比对两个值是否一致。

✅ 数字签名系统中:

签名前先对原文做 MD5 摘要,再对摘要进行加密,减小签名长度。

✅ 密码校验:

把用户密码做 MD5,存入数据库。登录时再 MD5 比较是否一致。


四、MD5 的安全性

  • 不可逆性:不能反推原文

  • 抗碰撞性(已破坏):不同输入应产生不同的输出,但MD5已被证明可构造碰撞

  • 攻击手段

    • 彩虹表攻击:预先计算常见密码的 MD5 值库

    • 撞库攻击:如把 "123456"、"password" 等常用密码先建库,对比 MD5 值

建议措施

  • 不要使用简单密码

  • 加“盐”(salt)值增加随机性

  • 替代方案:使用更安全的散列算法如 SHA-256、bcrypt、Argon2 等

✅ 🌟 简化版 MD5(C++)教学示例

只做:

  • Padding 补齐

  • 处理一个 512 位块(64 字节)

  • 使用前 4 步的 F 函数 + 左移操作
    (完整的 64 步我们暂时不实现)

#include <iostream>
#include <vector>
#include <cstring>
#include <cstdint>

using namespace std;

// 左循环移位
uint32_t leftRotate(uint32_t x, int s) {
    return (x << s) | (x >> (32 - s));
}

// F函数(MD5 第1轮使用)
uint32_t F(uint32_t x, uint32_t y, uint32_t z) {
    return (x & y) | (~x & z);
}

// 对消息进行填充(只处理英文字符)
vector<uint8_t> md5_padding(const string& input) {
    vector<uint8_t> msg(input.begin(), input.end());

    // 记录原始长度(单位:比特)
    uint64_t bit_len = msg.size() * 8;

    // 添加 0x80(10000000)
    msg.push_back(0x80);

    // 补零直到长度 % 512 == 448
    while ((msg.size() * 8) % 512 != 448) {
        msg.push_back(0x00);
    }

    // 追加 64 位小端的原始长度
    for (int i = 0; i < 8; i++) {
        msg.push_back((bit_len >> (8 * i)) & 0xFF);
    }

    return msg;
}

// 处理一个块(64字节)
void processBlock(uint8_t block[64], uint32_t& A, uint32_t& B, uint32_t& C, uint32_t& D) {
    uint32_t M[16];
    for (int i = 0; i < 16; ++i) {
        // 每4字节拼成一个32位整数,小端模式
        M[i] = block[i*4] | (block[i*4 + 1] << 8) | (block[i*4 + 2] << 16) | (block[i*4 + 3] << 24);
    }

    // 保存初始值
    uint32_t a = A, b = B, c = C, d = D;

    uint32_t s[] = {7, 12, 17, 22};  // 位移参数(只用前4步)
    uint32_t k = 0xd76aa478;         // 第一步使用的常数

    // 模拟前 4 步
    for (int i = 0; i < 4; ++i) {
        uint32_t f = F(b, c, d);
        uint32_t temp = a + f + M[i] + k;
        a = d;
        d = c;
        c = b;
        b = b + leftRotate(temp, s[i]);
    }

    // 更新结果
    A += a;
    B += b;
    C += c;
    D += d;
}

// 主函数
int main() {
    string input = "abc";
    vector<uint8_t> padded = md5_padding(input);

    // 初始化变量
    uint32_t A = 0x67452301;
    uint32_t B = 0xefcdab89;
    uint32_t C = 0x98badcfe;
    uint32_t D = 0x10325476;

    // 处理第一个块(简化:只处理一个)
    processBlock(&padded[0], A, B, C, D);

    // 输出结果
    printf("简化 MD5 输出:%08x%08x%08x%08x\n", A, B, C, D);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值