本网站是本人的个人博客网站海外站,国内网站为https://suyihang15.com,本网站主要面对海外用户

MD5工具

项目地址: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 填充:加一下乱七八糟的干扰

  1. 先贴一个 0x80(二进制 1000 0000)当”到此为止”的标记;
  2. 再塞 0x00 当泡沫,塞到总长度对 64 取模刚好剩 56(也就是 448 bit);
  3. 最后在箱子侧面写张纸条:原来这包料有多重(按位算的长度,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 两层对答案

  1. 证明没写错:算完用 hashlib.md5(data).hexdigest() 对一遍,一致才显示”一致 ✓”,这是验证算法写对的硬标准;
  2. 证明没被改:把结果和你手头已知的 MD5 比对,判断内容有没有被动过。

4.6 界面

我用的是 tkinter(Python 自带,不用额外装)搭的,朴素、单色字体,个人是喜欢这个样子的,当然你也可以自己改的,毕竟核心是算法,不想学其他第三方库了。


5. 代码结构

名字作用
_rotl(x, n)32 位循环左移(”转圈搅一下”)
_F/_G/_H/_I四轮非线性函数(四种”搅法”)
_K64 个常量(由 sin 生成的”固定配方”)
_S64 个循环左移位数(”转几圈”)
_word_index(i)第 i 步取哪一块料(消息字下标 g)
_pad(msg)填充(打包塞泡沫)
md5(data, trace_blocks)主函数,返回摘要 + 过程 + 填充后消息 + 块数 + 最终寄存器
describe(...)把过程渲染成能看懂的文本
PRINCIPLE内置的原理说明文本
MD5App界面类:_compute(算+对答案)、_verify(给定值比对)、_pick_file_copy 等

7. 验证结果

核心算法和标准库 hashlib 逐一对照,以下测试向量全部一致:

输入MD5
(空串)d41d8cd98f00b204e9800998ecf8427e
abc900150983cd24fb0d6963f7d28e17f72
The quick brown fox jumps over the lazy dog9e107d9d372bb6826bd81d3542a419d6
message digestf96b697d7cb7938d525a2f31aaf161d0

8. 注意事项

  • MD5 已经不安全了:现在能造出”两个不同的东西、指纹却一样”的情况(叫”碰撞”),所以它只适合验完整性或学习,别拿来存密码、做数字签名;要安全就用 SHA-256 这类,虽然早年间也有用这个的,但是现在基本上都更新了,起码别明文传输就行。
  • 文件是整块读进内存的,超大文件会吃内存,而且过程只显示前 4 块(结果不受影响)。
  • 文本统一按 UTF-8 编码,和”原始字节”对应的 MD5 是同一个东西的两面,没有额外处理,只算是简单的加密吧。
  • 本人没有专门系统性的学过这个,参考了很多其他人的思路,来设计这个,希望有大佬指点一下。

8. 效果展示

0 条对“MD5工具”的回复

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

© 2026 苏的小站

Go to top