哈希编码(Hashing)是一种将任意长度的数据转换成固定长度的数值或字符串的算法过程。
1. 基本原理
哈希编码通过哈希函数来实现。哈希函数是一种特殊的数学函数,它接收输入数据(可以是文本、数字、文件等各种形式的数据),然后按照一定的规则进行计算,最终输出一个固定长度的哈希值。例如,常见的哈希函数有 MD5,它会将输入数据转换成一个 128 位的哈希值,通常以 32 位十六进制数的形式表示。
哈希函数具有单向性,即从哈希值很难反向推导出原始数据。这是因为哈希函数的计算过程是复杂的,且可能存在多个不同的输入数据经过哈希函数计算后得到相同的哈希值(虽然这种情况在设计良好的哈希函数中发生的概率极低)。
2. 主要特点
固定长度输出
无论输入数据的大小如何,哈希函数的输出哈希值的长度是固定的。比如 SHA-256 算法,无论输入是一个字符还是一个很大的文件,输出的哈希值都是 256 位。
高效性
哈希函数的计算速度通常很快,能够在较短的时间内完成对输入数据的处理并得到哈希值。这使得哈希编码在很多需要快速处理数据的场景中非常有用。
高抗碰撞性
理想中的哈希函数应该很难找到两个不同的输入数据,使它们经过哈希函数计算后得到相同的哈希值。不过,由于输入数据的无限性和哈希值的有限性,碰撞(即不同的输入产生相同的哈希值)在理论上是不可避免的,但好的哈希函数会尽量降低碰撞的概率。
3. 算法示例
SHA-0 算法原理与示例
1. 数据填充
对输入数据进行补位,使总长度 ≡ 448 mod 512(补码规则:首位补 1,后续补 0)。 例:输入数据为 abc(二进制长度 24 位),需补 448-24=424 位,总长度 448 位。
2. 添加长度信息
在填充后的数据末尾附加原始数据长度(64 位无符号整数,若原始长度 > 2^64,则取低 64 位)。 例:abc 原始长度 24 位,附加 0x0000000000000018(24 的十六进制),总长度 512 位(1 个分组)。
3. 初始化哈希值(缓冲区)
用 5 个 32 位寄存器存储初始值: A=0x67452301, B=0xEFCDAB89, C=0x98BADCFE, D=0x10325476, E=0xC3D2E1F0。
4. 分组处理(循环迭代)
将数据分为 512 位分组,每组拆分为 16 个 32 位子块(W0W15),并扩展为 80 个子块(W0W79):
Wt = S^1(Wt-3 XOR Wt-8 XOR Wt-14 XOR Wt-16)(S^b 表示循环左移 b 位)。
对每个分组进行 80 轮迭代,每轮运算:
f = (B AND C) OR ((NOT B) AND D)(第 0~19 轮,逻辑函数)
temp = S^5(A) + f + E + Wt + 0x5A827999(常数随轮次变化)
E = D, D = C, C = S^30(B), B = A, A = temp。
5. 合并结果
所有分组处理完毕后,将 5 个寄存器的值串联,得到 160 位哈希值。
示例计算(简化版)
输入:a(ASCII 码 0x61,二进制 01100001)
1. 填充与长度附加
原始长度:8 位 → 填充后数据:01100001 1 000...0(补 440 个 0) + 0x0000000000000008 → 总长度 512 位。
2. 扩展子块(仅前 4 个)
W0=0x61000000, W1=0x00000000, ..., W15=0x00000008 W16 = S^1(W13 XOR W10 XOR W2 XOR W0)(实际需计算至 W79)。
3. 首轮迭代(t=0)
f = (B AND C) OR ((NOT B) AND D) = (0xEFCDAB89 AND 0x98BADCFE) OR ((NOT 0xEFCDAB89) AND 0x10325476) temp = S^5(A) + f + E + W0 + 0x5A827999(具体数值需按位运算计算)。
4. 迭代 80 轮
合并寄存器值得到最终哈希值(实际结果为 0x2ef7bde608ce5404e97d5f042f95f0c9f28f5ac3)。
5. 示例代码
因为 SHA-0 被弃用了,这里用 SHA-1 示例:
hashlib
message = .encode()
sha1_hash = hashlib.sha1(message).hexdigest()
(, sha1_hash)


