资讯动态

哈希算法原理图解:从MD5到SHA-3,一张图看懂数据摘要的生成流程

发布时间:2026/10/20 16:05:12 来源:尧图企业网站定制
我第一次认真看哈希算法原理图时说实话有点懵满屏的方块、箭头、异或符号、循环移位完全不知道主干在哪。后来我发现问题不在图而在看图的顺序。哈希算法这个词做技术的人都天天见文件完整性校验、接口签名、密码存储、区块链区块哈希背后都是它在运行。但真要说清楚它的原理很多人只会背一句不可逆的散列函数。这篇文章就把常用哈希算法——MD5、SHA-1、SHA-2、SHA-3、SM3、BLAKE2——的原理图拆开讲一遍告诉你图里哪些是主干哪些可以暂时忽略整张图到底应该从左往右看还是从下往上看。适合想搞懂哈希到底怎么运作、又不想啃数学公式和标准文档的人。1. 为什么一张合适的原理图比读十篇文字更能讲清哈希算法哈希算法的标准文档动辄几十页里面全是轮的次数、常数的取值、位移的位数。大多数工程人员并不需要背这些只需要理解数据是怎么被搅成一段固定长度摘要的。原理图的价值在于把过程压缩成一条主链让人一眼看到数据从哪进、往哪走、从哪出。1.1 一张哈希原理图里到底画了什么多数原理图可以拆成三个层次来看。第一层是主流程也就是整张图的大框架输入数据、填充、分块、迭代、输出。这层决定了哈希函数的整体形态。第二层是压缩函数的内部细节通常画成一个放大的方框里面有异或、加法、移位、查表之类的操作。对绝大多数使用者来说这一层可以暂时不看它解释的是具体怎么搅而不是整个流程怎么走。第三层是状态寄存器通常画成一排小格子代表计算过程中一直在变化的那几个中间值。我建议看图的顺序是固定的先找到输入箭头从哪里进入再顺着箭头找到填充区然后看分块之后的循环结构最后看输出箭头从哪里离开。只要把这条路径走通整张图的主干就清楚了。1.2 看图的顺序先主流程再轮函数很多人犯的错误是一上来就盯住轮函数不放想搞懂每一个异或和移位为什么那样设计。结果看了半小时连数据从哪个口进、从哪个口出都没找到。我自己最初看SHA-256的图也是这样盯着一个加号看了很久最后才意识到那条贯穿全图的长箭头才是真正的主角。实际操作中只有当你需要排查安全漏洞、做性能优化或者自己实现算法时才有必要深入轮函数。日常做接口签名、文件校验、数据完整性检查理解主流程就足够。原理图里最粗的那条线通常就是数据从填充到分块再到迭代的主链沿着它走一遍胜过读十段文字描述。2. 哈希的三个反直觉特性是所有原理图的前提在看图之前有件事必须想明白哈希函数到底在做什么。它做的事情可以概括成一句话——把任意长度的输入变成一段固定长度的、看起来和输入没有任何规律的输出。这句话里有三个点都很反直觉而原理图上所有方块和箭头都是为了实现这三个点。2.1 特性一输出长度固定输入大小和输出长度没关系不管输入是一个字节还是一个1GB的文件SHA-256的输出永远是256位也就是32个字节写成十六进制是64个字符。MD5输出永远是128位16个字节。SHA-1输出永远是160位20个字节。原理图上处理大文件时数据被切成很多块一块一块地处理但每一块都在更新同一组状态值最终输出的只是这组状态值的最终快照。用生活里的例子类比就像一个寄存处你存一张纸条也好存一箱书也好最后给你的取件码长度都一样。取件码不能代表包裹的大小只代表有这么一件东西存在过。2.2 特性二雪崩效应改一个比特输出就完全变样哈希函数还有个奇怪的性质输入只改动一个比特输出就会面目全非大约一半的输出位会发生变化。这就是常说的雪崩效应。原理图里的压缩函数做的大量移位、异或、加法操作本质上就是在做两件事扩散和混淆。扩散是把输入的影响铺开到整个状态混淆是让输出和输入之间的关系变得极其复杂。你可以想象一本书只改了其中一个标点符号但整本书的指纹却完全变了。这也是哈希能做完整性校验的根本原因只要数据被篡改哪怕只有一丁点算出来的摘要就和原来的对不上。2.3 特性三单向不可逆哈希绝不是加密这是新手最容易混淆的地方。加密是可逆的你有密钥就可以把密文还原成明文。哈希是不可逆的从摘要反推原始输入基本不可能。原理图上为什么画得那么复杂因为每一步压缩都在丢失信息丢掉的信息无法找回相当于把一本书磨成粉末再告诉你粉末的重量但没法从重量还原书的内容。所以记住一个判断标准任何声称可解密的哈希都是伪概念。哈希不是加密而是摘要、指纹、消息的浓缩。它适合用来验证东西有没有变不适合用来传递机密信息。3. 从输入到摘要一张图里的五段主干流程现在可以正式进入那张图了。大多数传统哈希算法的原理图主干都可以分成五段消息填充、分块、状态初始化、逐块迭代压缩、输出截断。下面按数据流动的顺序逐段说。3.1 第一段消息填充与长度登记压缩函数有个硬性要求每次处理的输入长度必须是固定的不能多也不能少。比如SHA-256的压缩函数一次处理512位也就是64字节。原始数据长度几乎不可能正好是64的倍数所以第一步必须做填充。填充规则在不同算法里细节不同但思路一致先在消息末尾补一个1再补一串0直到长度差不多够用最后还要留出固定位置来登记原始消息的比特长度。SHA-256会在末尾留出64位来记录原始长度。这一步看着不起眼作用却很大。它保证了两个不同长度的消息不会被填成同样的内容同时这个长度信息也参与了最后的计算让输出对原始长度敏感。为什么图里一定会有这一步因为如果没有填充最后一块数据不满64字节压缩函数就无法处理。填充区通常画在整张图的左上角就是从输入箭头出来的第一个方框。3.2 第二段分块与状态初始化填充完成后消息被切成一个个大小相同的块。SHA-256每块64字节SHA-512每块128字节MD5和SHA-1每块64字节。这些块会按顺序一块接一块地进入后面的循环。注意处理顺序绝对不能乱因为后一块的计算依赖前一块的结果这也是为什么哈希计算很难并行加速的核心原因。在开始处理第一个块之前算法还要初始化一组状态寄存器。SHA-256有8个32位的寄存器初始值是固定的所有计算都从这组值出发。你可以把这组初始值理解成搅拌机的初始状态机器是新的里面是空的但运行规则已经设定好。原理图里这组值通常画在循环区左边标着IV或者Initial Value。3.3 第三段逐块压缩图的心脏这是整张图最重要的部分。每一块消息进入后都和当前的状态值做一次压缩计算产生新的状态值然后下一块接着和新的状态值计算。整个过程像一条链子环环相扣所以这种结构被称作迭代式压缩结构通常缩写为M-D结构。MD5、SHA-1、SHA-2、SM3用的都是这个骨架。我可以把一个块的处理过程粗略理解成把新到的消息块和当前状态这盆水放在一起搅拌一轮得到一盆新的水。下一块消息再倒进去继续搅。图里通常画成一个大的循环框框里有几十轮小操作。SHA-256内部会做64轮SHA-1做80轮MD5做64轮。轮数越多搅拌次数越多雪崩效应通常也越充分。在这一段图里常常出现叉号、加号、方框等符号代表位运算和查表。你不需要知道每个符号的具体含义只需要抓住一点每一轮都在把消息块的信息往状态值里揉揉得越碎输出的随机性越好安全性越高。3.4 第四段海绵结构SHA-3的另一种画法SHA-3没有沿用M-D结构而是采用了海绵结构。原理图画起来也完全不同。海绵结构分成两个阶段吸收阶段和挤出阶段。吸收阶段把消息切成一段一段的逐段吸进一个大状态里每吸一段就做一次置换运算把所有消息块都吸收完后状态里已经包含了全部输入的信息。然后进入挤出阶段从状态里不断取出数据形成摘要。对比一下两种图M-D结构是从左往右的一条链像流水线一样一块一块处理海绵结构更像一个水槽消息从上方被吸收进去摘要从另一侧被挤出来可以按需设定输出长度。这也是为什么SHA-3的输出长度是可变的而SHA-256固定256位。3.5 第五段输出截断与最终摘要所有消息块处理完之后状态寄存器里装着最终的结果。这一步做的事很简单把状态值按顺序拼接起来变成最终的摘要。SHA-256有8个32位寄存器拼起来就是256位输出64个十六进制字符。SHA-512有8个64位寄存器拼起来就是512位。有些图在输出端画得很随意好像摘要可以随便截取。在标准算法里输出格式是严格定义的哪位寄存器在前、哪个字节在后都有规定。如果你自己在实现哈希时需要截取或截断必须参考标准文档否则做出来的摘要和别人对不上。这五段走完一张主流哈希原理图的基本逻辑就清楚了。接下来看看不同算法之间到底差在哪。4. 主流哈希算法的血统图同源与分家把MD5、SHA-1、SHA-2、SHA-3、SM3、BLAKE2摆在一起你会发现它们的关系像一张家族谱有的是亲兄弟有的只是远房亲戚还有的是半路出家另立门户。4.1 MD系列与SHA-1、SHA-2同一个骨架的三次改装MD4和MD5是这个家族里比较早的成员上世纪90年代初由一位密码学者设计输出128位。设计者最初的目标是提供一种快速的摘要算法。后来MD4被发现存在严重缺陷MD5也由于碰撞攻击被逐步淘汰但它的结构框架被保留下来。SHA-0和SHA-1是在MD4框架基础上调整出来的输出160位处理逻辑相似。SHA-1在很长一段时间里是安全领域的主力但后来也产生了碰撞问题。SHA-2家族则是对SHA-1的深度改造输出扩展到256位和512位轮运算更复杂常量表更大。虽然还是M-D结构但安全余量明显提高。这三代算法的关系就像同一套房子的三次装修承重墙没动还是填充、分块、迭代、输出但内部管线、门窗细节都换了。所以从原理图上看它们的主流程几乎一模一样区别主要在压缩函数内部。4.2 SHA-3另起炉灶的海绵路线到SHA-2时代加密哈希的结构已经高度统一都是M-D结构。官方密码标准组织在征集新一代哈希时偏好的不是继续在M-D上修修补补而是完全不同的路线。最终胜出的算法采用了海绵结构也就是前面讲过的吸收和挤出两阶段设计。SHA-3不是对SHA-2的增强而是提供了一个全新的备份方案。如果哪天SHA-2被发现重大问题整个行业可以迁移到SHA-3。它的内部状态达到1600位远大于SHA-256的256位结构上天然抵抗某些针对M-D链式结构的攻击。从图上区分两种算法很简单看到链式循环框的是M-D家族看到海绵状吸收挤出结构的是SHA-3家族。4.3 SM3与BLAKE2两种值得关注的特殊选手SM3是国密标准里的哈希算法输出256位整体结构非常接近SHA-256同样采用M-D骨架消息块同样是512位内部也是64轮。区别主要体现在消息扩展方式和压缩函数的具体运算上。由于结构相近你完全可以用同一张主流程去理解它只需注意轮函数实现不同。BLAKE2走的是另一条路线它基于ChaCha的置换思想设计目标是速度和安全性兼得。它的输出长度可以灵活配置在性能敏感的场景里表现更好。原理图上依然是填充、分块、迭代、输出的框架只是内部置换运算换成了一套更轻量的规则。4.4 常用算法参数速查表算法输出长度位内部结构消息块大小位当前状态常见用途MD5128M-D链式512碰撞已被构造不推荐安全用途旧系统兼容、非对抗场景SHA-1160M-D链式512碰撞已被构造正在淘汰版本管理指纹等SHA-256256M-D链式512当前认为安全文件校验、签名、区块链SHA-512512M-D链式1024当前认为安全数据完整性校验SHA-3可变海绵结构可变当前认为安全新系统可选用的备份方案SM3256M-D链式512当前认为安全国密合规场景BLAKE2可变类ChaCha置换可变当前认为安全性能敏感场景这张表里最需要记住的是输出长度背后的安全含义。对抗碰撞攻击时安全强度大约只有输出长度的一半。也就是说128位的MD5抗碰撞强度只有约2的64次方这在当前算力下已经不够看了。这也是为什么MD5和SHA-1在安全场景里必须退场。5. 原理图画不出来的三种攻击以及它们的现实版本原理图画的是算法怎么算但不会告诉你算法会被怎么打。这部分的现实版本同样重要尤其是当你打算在实际系统里选用哈希算法时。5.1 生日攻击为什么128位摘要也不够用如果不做任何攻击哈希看起来无懈可击输入一变输出就变想猜中某个摘要对应的输入平均要试2的256次方次对于SHA-256来说是个天文数字。但攻击者往往不针对特定摘要下手而是找任意碰撞——任何两个不同输入只要摘要相同就行。这里有个著名的生日悖论在一个房间里只要有23个人就有超过一半的概率出现两个生日相同的人。应用到哈希上对于n位的摘要找任意碰撞大约只需要试2的n/2次方次而不是2的n次方次。所以128位的MD5抗碰撞强度只剩2的64次方。在这个量级下大规模算力是可以尝试的现实中确实已经有针对MD5和SHA-1的碰撞攻击出现。这条结论直接对应原理图上的输出长度输出越短抗碰撞越弱。选型时不能只看摘要长度顺眼而要问一句我需要抵抗碰撞攻击吗。5.2 长度扩展攻击M-D结构的结构性问题M-D结构有一个容易被忽视的弱点。攻击者如果知道某条消息m的摘要H(m)并且知道m的长度那么即使完全不知道m的内容也能构造出一条更长的消息m使得H(m)可以被算出来而不需要知道m。这就是长度扩展攻击。原因是M-D结构把消息一块接一块地处理最终的状态值就是前面所有块处理完的结果。攻击者不需要知道前面的内容只需要把这个最终状态当作起点继续往后面添加新的消息块就行。这就像一个流水线攻击者中途接手继续往传送带上放零件照样能推算出最终成品。这个攻击对实际应用有什么影响影响最大的是把密钥拼在消息前面再哈希的认证方案。如果你用H(key message)来当校验码攻击者可能不需要知道key就能构造出合法的校验值。正确的做法是使用HMAC或者改用SHA-3这类不受长度扩展影响的结构。原理图上这一点看不出来但真出问题的时候它比碰撞攻击更隐蔽。5.3 用三个安全属性快速判断算法能不能用判断一个哈希算法在某个场景里能不能用不用背论文盯住三个属性就行。安全属性含义被攻破的影响抗碰撞找不到两条不同消息产生相同摘要恶意文件可以伪装成正常文件抗原像知道摘要也无法还原原始消息隐私信息可能被反推抗第二原像已知一条消息找不到另一条消息摘要相同正常消息可以被替换对于文件校验和数字签名抗碰撞最重要。对于密码存储抗原像和抗穷举更重要。对于消息认证还要防长度扩展攻击所以通常直接选用HMAC。把这四个问题过一遍选型基本不会跑偏。6. 看懂图谱之后的选型建议与常见误用了解了原理最后落到实际选择上。不同场景对哈希的要求不太一样没有一种算法通吃所有地方。6.1 按场景选哈希的决策参考使用场景推荐方案理由和注意事项文件下载完整性校验SHA-256广泛支持安全强度足够不容易出错接口签名、防篡改HMAC-SHA256HMAC能防长度扩展攻击密钥管理要单独处理密码存储加盐的慢哈希算法如bcrypt、argon2等普通哈希太快暴力猜密码更容易成功防篡改日志、区块链场景SHA-256或SHA-3链式累积摘要抗碰撞要求高内部数据去重、非对抗场景视性能需求选择如果无安全要求非加密哈希更快但不要用于签名特别注意密码存储这条。很多人以为把密码做一个SHA-256存入数据库就够了这是最经典的误用。哈希速度太快攻击者拿到数据库后可以每秒试上亿次密码配合彩虹表更是雪上加霜。正确的做法是加随机盐再选用特意设计得慢的密码哈希算法。这一点原理图中看不出来但实际部署时影响巨大。6.2 三个最常见的误用以及踩过的坑第一直接用单次哈希做签名。我早年间维护过一个内部系统最初用MD5对参数拼接做签名后来意识到字段顺序如果固定不变碰撞风险就是实打实的隐患于是把所有签名都改成HMAC-SHA256。这个改动不复杂但心里踏实很多。第二自己把标准算法的输出截断来用。有些人觉得SHA-512输出太长截一半当SHA-256用。理论上这不是不行但标准里截断方式有严格定义自己随意截容易造成不同系统之间摘要对不上也失去标准实现的安全性保证。能用标准库的就用标准库。第三自己设计增强版哈希。在标准哈希输出上再套一层哈希或者自己改轮函数都属于给自己挖坑。哈希算法的安全性经过了无数密码分析者的检验个人发明基本无法达到同等保障。记住一句话不要自己发明密码学。6.3 一个随时可做的验证实验如果读完上面这些还是有点晕我建议你亲自动手做一次验证。随便打开一个终端对同一段文字分别用MD5、SHA-1、SHA-256计算摘要观察输出长度。再改一个字母重新算观察输出的变化幅度。用Python只需要几行代码就能验证import hashlib text bhello world print(hashlib.md5(text).hexdigest()) # 32位十六进制 print(hashlib.sha1(text).hexdigest()) # 40位十六进制 print(hashlib.sha256(text).hexdigest()) # 64位十六进制命令行也可以用sha256sum 文件名。看看输出是不是64个十六进制字符然后改文件名内容的一点点再看输出是不是变得面目全非。这个实验做完前面讲的所有特性就都变成亲眼所见的东西了。我个人的习惯是看哈希原理图时只看主流程确认数据从哪里进、从哪里出只有在排查安全细节时才去翻轮函数。当你能够把填充、分块、迭代、输出这个链条随口说出来再遇到MD5、SHA-256还是SM3都只是同一张图的不同变体罢了。哈希没有想象中那么玄它就是把一盆水反复搅拌直到你认不出原来的样子。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑