项目地址:https://github.com/suyihang15/md5_tool
下载链接:https://github.com/suyihang15/md5_tool/releases/download/1.0.0/md5_tool.exe
MD5 严格讲不是加密,而是”取指纹 / 盖章”。
所以 MD5 只能用来”验真假”(看东西有没有被改过)
1. 工具的作用
- 给任意文字(UTF-8 编码)或文件算一个 MD5 指纹(128 bit,即 32 个十六进制字符)。
- 把”这个指纹是怎么算出来的”每一步都展示给你看
- 把 Python 自带
hashlib的结果对一遍,证明自己手写的算法没算错; - 和你手头已知的 MD5 对一遍,看文件有没有被人动过手脚(完整性校验)。
2. 功能清单
| 功能 | 说明 |
|---|---|
| 文本计算 | 输入文本,按 UTF-8 编码后算 MD5 |
| 文件计算 | 选文件,按二进制读进来算 MD5 |
| 大写显示 | 同时给出小写和大写两种形式 |
| 逐步过程 | 「算法步骤」页展示填充、切块、64 步搅拌的全过程 |
| 原理说明 | 「原理说明」页内置 MD5 算法文字说明 |
| 结果复制 | 一键复制结果到剪贴板 |
| 标准库对照 | 算完自动和 hashlib.md5 对一遍,显示一致/不一致 |
| 给定值校验 | 粘贴一个已知 MD5 比对,显示匹配/不匹配 |
3. MD5 原理
3.1 填充:加一下乱七八糟的干扰
- 先贴一个
0x80(二进制1000 0000)当”到此为止”的标记; - 再塞
0x00当泡沫,塞到总长度对 64 取模刚好剩 56(也就是 448 bit); - 最后在箱子侧面写张纸条:原来这包料有多重(按位算的长度,64 位小端序)。
3.2 分块:切成 512 位大块,再切 16 小块
打包好的东西切成一个个 512 位的大块,每块再切成 16 个 32 位的小块(代码里叫 M[0]..M[15])。
3.3 随机排列
先准备 4 个固定初值的桶:
A = 0x67452301 B = 0xEFCDAB89
C = 0x98BADCFE D = 0x10325476
这 4 个桶就是后面搅拌的主战场,最终答案从这 4 个桶里倒出来。(这四个初值其实是我随便取的常数。)
3.4 主循环:每块搅 64 下
每一步(对应代码第 107 行)大概干这么件事:
把 A + 一个函数值 + 一个常量 K + 一小块料 M,全加在一起,
再"转圈搅一下"(循环左移),最后倒进 B 桶;
然后 A/B/C/D 四个桶轮流转一圈(D→A、A→B、B→C、C→D)。
三样”配料”是提前准备好的:
- K[i](固定配方):用正弦函数
sin算出来的 64 个数。看着挺随机,其实每次都一模一样,保证”同样的料永远同一个味”; - S[i](转几圈):每一步往左转多少位,有张固定表(每轮 4 个值,各重复 4 次);
- M[g](取哪块料):这一步去取 16 小块里的哪一块,每轮取法不一样,这样 16 块料被反复、不同顺序地用到。
搅完 64 下,把这 4 个桶的值倒回大锅(代码里 A += a; B += b; ... 那段)。这就是”蝴蝶效应”的来源——某一块料的改动会一层层传染到所有块。
3.5 组合
所有块都搅完之后,把 a/b/c/d 按小端序拼起来,转成十六进制,就是那串 32 位的 MD5。比如 "abc" 出来是 900150983cd24fb0d6963f7d28e17f72。
4. 实现思路
4.1 怎么把数字锁在 32 位内
Python 的数字可以无限大,但 MD5 要求每一步都只能 32 位。所以:
- 每次加减完都
& 0xFFFFFFFF砍到 32 位; - 循环左移
_rotl前后都砍; - 长度字段用
& 0xFFFFFFFFFFFFFFFF砍到 64 位。
4.3 小端序怎么处理
用 struct 的 < 前缀一次性搞定:'<16I' 把 64 字节拆成 16 个倒着读的 32 位数,'<4I' 把 4 个寄存器倒着拼回字节,'<Q' 处理 64 位长度。
4.4 过程展示怎么不撑爆界面
md5(data, trace_blocks=4) 里,前 4 个块边算边记每一步(步号、函数名、消息字下标、左移位数、更新后的 A/B/C/D),后面的块只算不记。两条路走的是同一套运算,只是要不要顺手记一笔的区别——所以记不记都不影响结果,大文件也不会卡死界面。
4.5 两层对答案
- 证明没写错:算完用
hashlib.md5(data).hexdigest()对一遍,一致才显示”一致 ✓”,这是验证算法写对的硬标准; - 证明没被改:把结果和你手头已知的 MD5 比对,判断内容有没有被动过。
4.6 界面
我用的是 tkinter(Python 自带,不用额外装)搭的,朴素、单色字体,个人是喜欢这个样子的,当然你也可以自己改的,毕竟核心是算法,不想学其他第三方库了。
5. 代码结构
| 名字 | 作用 |
|---|---|
_rotl(x, n) | 32 位循环左移(”转圈搅一下”) |
_F/_G/_H/_I | 四轮非线性函数(四种”搅法”) |
_K | 64 个常量(由 sin 生成的”固定配方”) |
_S | 64 个循环左移位数(”转几圈”) |
_word_index(i) | 第 i 步取哪一块料(消息字下标 g) |
_pad(msg) | 填充(打包塞泡沫) |
md5(data, trace_blocks) | 主函数,返回摘要 + 过程 + 填充后消息 + 块数 + 最终寄存器 |
describe(...) | 把过程渲染成能看懂的文本 |
PRINCIPLE | 内置的原理说明文本 |
MD5App | 界面类:_compute(算+对答案)、_verify(给定值比对)、_pick_file、_copy 等 |
7. 验证结果
核心算法和标准库 hashlib 逐一对照,以下测试向量全部一致:
| 输入 | MD5 |
|---|---|
| (空串) | d41d8cd98f00b204e9800998ecf8427e |
abc | 900150983cd24fb0d6963f7d28e17f72 |
The quick brown fox jumps over the lazy dog | 9e107d9d372bb6826bd81d3542a419d6 |
message digest | f96b697d7cb7938d525a2f31aaf161d0 |
8. 注意事项
- MD5 已经不安全了:现在能造出”两个不同的东西、指纹却一样”的情况(叫”碰撞”),所以它只适合验完整性或学习,别拿来存密码、做数字签名;要安全就用 SHA-256 这类,虽然早年间也有用这个的,但是现在基本上都更新了,起码别明文传输就行。
- 文件是整块读进内存的,超大文件会吃内存,而且过程只显示前 4 块(结果不受影响)。
- 文本统一按 UTF-8 编码,和”原始字节”对应的 MD5 是同一个东西的两面,没有额外处理,只算是简单的加密吧。
- 本人没有专门系统性的学过这个,参考了很多其他人的思路,来设计这个,希望有大佬指点一下。
8. 效果展示


0 条对“MD5工具”的回复