哈希算法是一种将输入数据(通常是任意长度的消息)转换为固定长度的字符串或数字的方法。这种转换过程通常是通过一系列复杂的数学运算实现的。哈希算法广泛应用于数据加密、数据校验、文件完整性验证等领域。
哈希算法的工作原理
哈希算法的核心在于将输入的任意长度数据,通过一系列不可逆的数学操作,生成一个固定长度的输出。这种输出通常被称为哈希值或摘要。哈希算法具有以下几个重要特性:
-
确定性:相同的输入总是会生成相同的输出。这意味着,对于任何给定的输入数据,无论你执行多少次哈希运算,结果都是相同的。
-
不可逆性:哈希算法的运算过程是单向的,从哈希值几乎不可能反推出原始输入数据。即使拥有相同的哈希算法和结果,也无法直接得知输入数据的内容。
-
抗碰撞性:不同的输入数据不应该生成相同的哈希值。这一特性对于确保数据唯一性非常重要,尽管实际应用中,总有可能存在极少量的碰撞,但好的哈希算法应该极大地减少碰撞的概率。
-
敏感性:输入的微小改变会导致输出哈希值的巨大变化。例如,将一个文件的某个字节由
0
改为1
,生成的哈希值将与原始文件完全不同。这一特性在数据完整性验证中非常有用。
常见的哈希算法
目前,常用的哈希算法有以下几种:
-
MD5(Message Digest Algorithm 5):产生128位的哈希值,曾经广泛用于校验数据完整性。然而,随着时间推移,MD5被发现存在严重的安全漏洞,尤其是易于产生碰撞,因此在安全领域逐渐被弃用。
-
SHA-1(Secure Hash Algorithm 1):产生160位的哈希值,相比MD5安全性有所提升。然而,随着计算能力的提升,SHA-1也被发现存在安全风险,已不再推荐用于敏感数据的哈希操作。
-
SHA-256:属于SHA-2系列,产生256位的哈希值,目前被广泛应用于数据加密和数字签名等领域。SHA-256被认为是目前较为安全的哈希算法之一。
1. MD5(Message Digest Algorithm 5)
公式步骤:
-
输入消息 $M$ 被填充到长度为 $512$ 的倍数,分为 $L$ 个块,每个块 $512$ 位。
-
初始的4个32位寄存器 $A_0$, $B_0$, $C_0$, $D_0$ 被设定为固定常数值。
-
对于每个消息块 $M_i$,MD5 进行四轮处理,每轮有16次操作。每次操作使用以下函数之一:
- \[F(B, C, D) = (B \land C) \lor (\neg B \land D)\]
- \[G(B, C, D) = (B \land D) \lor (C \land \neg D)\]
- \[H(B, C, D) = B \oplus C \oplus D\]
- \[I(B, C, D) = C \oplus (B \lor \neg D)\]
-
每轮的数学表达式为:
\[A = B + \left( (A + F(B, C, D) + M[k] + T[i]) \ll s \right)\]其中,$M[k]$ 是当前消息块中的数据,$T[i]$ 是固定表中的常数,$s$ 是向左旋转的位数。
-
最终的哈希值是所有块处理完毕后的 $A$, $B$, $C$, $D$ 的组合。
2. SHA-1(Secure Hash Algorithm 1)
公式步骤:
-
输入消息 $M$ 被填充到长度为 $512$ 的倍数,分为 $L$ 个块,每个块 $512$ 位。
-
初始5个32位寄存器 $H_0$, $H_1$, $H_2$, $H_3$, $H_4$ 被设定为固定常数值。
-
对于每个消息块 $M_i$,SHA-1 进行80轮处理。每轮使用以下函数之一:
- \[Ch(x, y, z) = (x \land y) \oplus (\neg x \land z)\]
- \[Maj(x, y, z) = (x \land y) \oplus (x \land z) \oplus (y \land z)\]
- \[Par(x, y, z) = x \oplus y \oplus z\]
-
每轮的数学表达式为:
\[T = (H_{i-1} \ll 5) + f(H_{i-2}, H_{i-3}, H_{i-4}) + H_{i-5} + W[t] + K[t]\]其中,$W[t]$ 是消息块的扩展数据,$K[t]$ 是固定表中的常数。
-
最终的哈希值是所有块处理完毕后的 $H_0$, $H_1$, $H_2$, $H_3$, $H_4$ 的组合。
3. SHA-256
公式步骤:
-
输入消息 $M$ 被填充到长度为 $512$ 的倍数,分为 $L$ 个块,每个块 $512$ 位。
-
初始8个32位寄存器 $H_0$, $H_1$, $H_2$, $H_3$, $H_4$, $H_5$, $H_6$, $H_7$ 被设定为固定常数值。
-
对于每个消息块 $M_i$,SHA-256 进行64轮处理。每轮使用以下函数之一:
- \[Ch(x, y, z) = (x \land y) \oplus (\neg x \land z)\]
- \[Maj(x, y, z) = (x \land y) \oplus (x \land z) \oplus (y \land z)\]
- \[\Sigma_0(x) = ROTR^2(x) \oplus ROTR^{13}(x) \oplus ROTR^{22}(x)\]
- \[\Sigma_1(x) = ROTR^6(x) \oplus ROTR^{11}(x) \oplus ROTR^{25}(x)\]
- \[\sigma_0(x) = ROTR^7(x) \oplus ROTR^{18}(x) \oplus SHR^3(x)\]
- \[\sigma_1(x) = ROTR^{17}(x) \oplus ROTR^{19}(x) \oplus SHR^{10}(x)\]
-
每轮的数学表达式为:
\(T_1 = H_{i-7} + \Sigma_1(H_{i-2}) + Ch(H_{i-3}, H_{i-4}, H_{i-5}) + K[t] + W[t]\) \(T_2 = \Sigma_0(H_{i-1}) + Maj(H_{i-2}, H_{i-3}, H_{i-4})\)
其中,$W[t]$ 是消息块的扩展数据,$K[t]$ 是固定表中的常数。
-
最终的哈希值是所有块处理完毕后的 $H_0$, $H_1$, $H_2$, $H_3$, $H_4$, $H_5$, $H_6$, $H_7$ 的组合。
哈希算法的应用场景
-
数据校验和完整性验证:在文件传输或存储过程中,哈希算法用于生成文件的哈希值。接收方可以通过计算接收到的文件哈希值,并与发送方提供的哈希值进行比较,来验证文件是否被篡改。
-
密码存储:在用户认证系统中,哈希算法用于将用户的密码哈希后存储在数据库中。即使数据库被攻击者获取,由于哈希值不可逆,攻击者也无法轻易还原用户的明文密码。
-
数字签名:数字签名技术通过哈希算法确保消息的完整性和不可否认性。发送方对消息生成哈希值并使用私钥进行签名,接收方使用公钥验证签名,从而确认消息的来源和完整性。