MD2哈希算法的填充与校验和计算过程详解
字数 2552 2025-12-23 20:23:32
MD2哈希算法的填充与校验和计算过程详解
我将为你讲解MD2哈希算法中两个关键且独特的设计:其独特的填充规则,以及它特有的“校验和(Checksum)”追加步骤。这两个步骤是MD2区别于其他早期哈希算法(如MD5)的重要特征。
1. 算法背景与概述
MD2由罗纳德·李维斯特(Ronald Rivest)于1989年设计,是MD系列(MD2, MD4, MD5)中的第一个。它输出一个128位(16字节)的哈希值。MD2的一个显著特点是其在处理消息后,会先计算一个16字节的校验和,并将该校验和追加到填充后的消息末尾,再进行最终的哈希压缩。这使得即使对消息进行简单的附加字符攻击也变得更加困难。
2. 第一步:消息填充(Padding)
在开始任何计算之前,必须先将原始消息填充为特定长度的整数倍。
- 目标长度:填充后消息的总字节数必须是 16 的整数倍。
- 填充规则:假设原始消息长度为
L字节。- 计算需要填充的字节数
k。k = 16 - (L mod 16)。如果L正好是16的倍数,则k = 16。 - 填充的每个字节的值都是
k。 - 因此,填充字节数为
k,每个填充字节的值也是k。
- 计算需要填充的字节数
举例说明:
假设原始消息为 “ABC” (3个字节,ASCII值分别为 65, 66, 67)。
L = 3。3 mod 16 = 3,所以k = 16 - 3 = 13。- 需要填充13个字节,每个字节的值都是13(十六进制为
0x0D)。 - 填充后的消息(用十进制和十六进制表示)为:
65, 66, 67, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13
0x41, 0x42, 0x43, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
这个填充规则是确定性的,确保了任何消息在经过填充后,其末尾的最后一个字节的值直接揭示了填充的长度。
3. 第二步:计算校验和(Checksum)
这是MD2最具特色的步骤。算法会对填充后的消息(注意,不是原始消息)计算一个16字节的校验和,并将这个校验和块追加到消息的末尾。
- 初始化:准备一个长度为16字节的校验和数组
C,初始值全部设为0。同时,MD2定义了一个大小为256的置换表S,其值是0-255的一个伪随机排列(基于圆周率π的数字构造)。 - 处理过程:将填充后的消息按16字节分块。设共有
N个块:M[0],M[1], …,M[N-1]。- 设置一个临时变量
L = 0。 - 对于每一个消息块
i(从0到N-1):- 对于块中的每一个字节位置
j(从0到15):L = S[ M[i][j] XOR L ]C[j] = C[j] XOR L- 这里的
M[i][j]是第i块的第j个字节。 S[...]表示查找置换表S。
- 对于块中的每一个字节位置
- 处理完所有
N个消息块后,数组C中的16个字节就是计算出的校验和。
- 设置一个临时变量
过程理解:
- 变量
L充当了“状态”或“记忆”,它依赖于之前处理过的所有字节。这使得校验和的计算是串行的、依赖于顺序的。 - 最终得到的校验和
C是原始消息(已填充)所有字节经过复杂非线性变换后的一个“摘要”。 - 关键点:计算完校验和后,将
C作为一个新的16字节块,追加到已填充的消息后面。现在,待处理的总块数变成了N+1块(原来的N个消息块 + 1个校验和块)。
4. 第三步:初始化哈希压缩
- 初始化一个48字节的缓冲区
B,分为三部分:- 第一部分(0-15字节):初始化为固定的初始化向量
IV(全为0)。 - 第二部分(16-31字节):用于存放正在处理的16字节消息/校验和块。
- 第三部分(32-47字节):是前两部分的XOR结果。
- 第一部分(0-15字节):初始化为固定的初始化向量
- 初始化最终的128位哈希值(16字节)
H为IV。
5. 第四步:压缩处理(包含校验和块)
现在,我们对 N+1 个块(N个填充消息块 + 1个校验和块)进行处理。
对于每一个块 M_block(按顺序):
- 加载块:将当前16字节的
M_block复制到缓冲区B的第二部分(16-31字节)。 - 计算XOR:将缓冲区
B的第一部分(0-15字节)与第二部分(16-31字节)进行按字节异或(XOR),结果存入第三部分(32-47字节)。此时,B中有了48字节的数据。 - 18轮置换:对48字节的缓冲区
B进行18轮变换。每一轮中:- 对于
B中的每一个位置j(从0到47):B[j] = S[ B[j] XOR t ],其中t是一个0-255的值(在每一轮中,t的值是(当前轮次 + j) mod 256在置换表S中对应的值?)。(更准确的描述是:t直接取值为(当前轮次 + j) mod 256,然后B[j] = S[ B[j] XOR t ])
- 对于
- 更新哈希值:一轮处理完所有
N+1个块后,取缓冲区B的第一部分(0-15字节)作为新的中间哈希值。
处理完最后一个块(即校验和块)后,缓冲区 B 的第一部分(0-15字节)就是最终的128位MD2哈希值。
总结与核心特点
- 填充:确保消息长度为16字节的倍数,填充值为填充长度本身。
- 校验和:对填充后的消息计算一个16字节的非线性校验和,并追加到消息末尾。这是MD2的“第二道防线”,增加了对消息进行简单修改(如附加数据)的复杂度。
- 压缩:使用一个48字节的缓冲区,结合一个256字节的固定置换表
S,进行18轮字节级的混淆操作。
MD2因其较慢的速度(18轮/块,且包含校验和步骤)和已被发现的碰撞攻击而被认为不安全,早已被MD4、MD5以及更安全的SHA系列算法所取代。但其设计中的“校验和”步骤,作为对消息完整性的额外保障,在密码学算法设计历史上留下了独特的一笔。