SHA1哈希生成器

把文本转成 40 位十六进制 SHA-1 摘要,同时给出它的 UTF-8 字节数。本页把 SHA-1 的 80 轮压缩函数内联实现,并用 FIPS 180-1 的五组官方向量逐条对拍,所以结果可以拿去和命令行 sha1sum 对齐。

699c34734693168287a30547ed59ba2f7cbc8359 40 位小写十六进制 · 摘要不区分大小写,比较时应统一小写
UTF-8 字节数22
字符数(UTF-16 码元)22
填充后总字节64
压缩块数1

本工具只做摘要,不做任何加盐、迭代或签名。SHA-1 已被 NIST 列入不建议用于数字签名的算法,摘要相同不代表内容安全。

使用方法

  1. 把要摘要的文本粘进输入框,或直接改写。页面打开时框里已经预置了 liuquan.net 回车 SHA-1 2026 这两行,下方结果区显示的 699c3473…c8359 就是它的实测值。
  2. 点「计算 SHA-1」(或在输入框里按 Ctrl + Enter,macOS 用 Cmd + Enter)重新计算。文本框里的 Enter 保留给换行,不会误触发。
  3. 看UTF-8 字节数这一项确认哈希的是不是你以为的那串字节。摘要算的是字节不是「字符」:一个汉字占 3 字节、一个表情占 4 字节,写 abc 和写 ABC 摘要完全不同,但中文和 emoji 混排时最容易把字节数算错。
  4. 点「复制摘要」把 40 位十六进制带走;点「转大写」切换成大写形式便于和某些旧系统比对。有些系统存的是大写,比较前务必统一成小写,否则会误判为不一致。
  5. 需要核对算法实现对不对,点「载入示例」后对照正文的测试向量表:abc 应得 a9993e364706816aba3e25717850c26c9cd0d89d,空串应得 da39a3ee5e6b4b0d3255bfef95601890afd80709。

这个 SHA1哈希生成器能解决什么问题

一是核对旧系统的历史数据。很多老系统、导入模板和早期接口约定用 SHA-1 做校验位,你要往里灌数据就得先把值算出来对一遍,否则整批导入被拒。本页把输入框上限设在 40000 字节,正好覆盖单个字段、单条记录的长度。

二是复核 Git 对象与文件指纹。Git 早期版本用 SHA-1 做对象名,手工比对 blob 哈希时需要自己算。虽然 Git 的对象哈希还额外包了一层 blob <长度>\0 前缀,和直接对文件内容取摘要不是同一个值,但拿本页结果去和 git hash-object 的输出对照,能立刻判断差异出在内容还是出在前缀那一层。

三是排查「同样的内容为什么摘要不一样」。这类问题九成出在字节层面而不是算法层面:行尾是 \n 还是 \r\n、文件末尾有没有换行、编码是 UTF-8 还是 GBK、有没有看不见的 BOM。本页把字节数和填充后的总字节一起显示,能帮你把「差一个字节」这类问题定位到具体位置。

四是给非安全用途做去重指纹。缓存键、分片标识、日志聚合的粗略去重,用 SHA-1 算 160 位摘要足够——它不是密码学强度的选择,但在这些场景里也不构成风险。

本页不做这些事:不提供加盐、不做 HMAC、不做口令哈希、不判断内容是否「安全」。口令要哈希请用带盐的慢哈希算法;如果只是想把 MD5/SHA-1/SHA-256/SHA-512 放在一起横向比对,用「在线哈希生成器」一次输出四种摘要更省事。

SHA-1 的实现原理与每个常数从哪来

整体结构是 Merkle–Damgård 分组密码。SHA-1 把消息按 512 位(64 字节)一块切开,每块跑 80 轮压缩,块与块之间串行传递 160 位状态。最后一块要按固定规则补齐,再把消息的比特长度写进末尾 8 个字节。三个数字必须记牢:块大小 64 字节、轮数 80、状态 160 位(也就是 5 个 32 位字)。

填充规则决定了你输入多长会多算几块。先追加 1 字节的 0x80,再补若干个 0x00,最后留 8 字节放比特长度(高 32 位 + 低 32 位,大端序)。总长度必须是 64 的整数倍,于是有两条临界线:消息 55 字节时,1 + 55 + 8 = 64 恰好一块;消息 56 字节时算式变成 1 + 56 + 8 = 65,必须再开一块。本页示例的 22 字节会被填到 64 字节、跑 1 块;如果你粘进去 56 字节的文本,页面上「压缩块数」会跳到 2。

80 轮分成四段,每段用不同的布尔函数与常数。这套常数不是随便取的,它们是 2 的平方根、立方根、四次方根、五次方根的前 32 位小数部分:第 1~20 轮(i < 20)用 f = (b & c) | (~b & d),常数 0x5A827999;第 21~40 轮用 f = b ^ c ^ d,常数 0x6ED9EBA1;第 41~60 轮用 f = (b & c) | (b & d) | (c & d),常数 0x8F1BBCDC;第 61~80 轮用 f = b ^ c ^ d,常数 0xCA62C1D6。前 20 轮是选一(Ch)、后 60 轮是异或(Maj),这个结构保证早期轮就有雪崩效应。初始状态五个字是 0x67452301 0xEFCDAB89 0x98BADCFE 0x10325476 0xC3D2E1F0,前四个是素数的十六进制拼接,第五个是 √2。

每轮的动作是固定的五步移位。先把 a 循环左移 5 位((a << 5) | (a >>> 27)),加上 f、加上当前轮常数 k、加上消息字 w[i],得到 temp;然后 e = d、d = c、c = b 循环左移 30 位、b = a、a = temp。消息调度 w[0..79] 也不是预先全算的:前 16 个字直接取自消息的 16 个大端 32 位字,w[16] 起用 w[i] = (w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]) 循环左移 1 位递推。做完 80 轮,把 a~e 逐个加回状态(模 2³²)就算完一块。

为什么内联一份实现,而不是直接调浏览器原生接口。页面的第一版确实是这么写的,调用 crypto.subtle.digest('SHA-1', …)。实测(用 Node 22 的同规范 WebCrypto 与 FIPS 向量对拍)发现两个问题:一是算法名必须写带连字符的 'SHA-1' 或 'sha-1',写成 'SHA1' 或 'Sha1' 会抛 NotSupportedError;二是这个名字能否被识别取决于运行环境——crypto.subtle 只在安全上下文(HTTPS 或 localhost)存在,HTTP 环境下 crypto.subtle 整个是 undefined,代码会直接抛错而不是降级。所以本页改成内联位运算实现为主路径,保证在任何环境都能算出结果,也顺带省掉了一个异步状态机。想验证浏览器原生实现是否可用,可以在控制台敲 crypto.subtle.digest('SHA-1', new TextEncoder().encode('abc')) 看是否返回 a9993e36…。

输入如何变成字节,是这一步最容易出错。JS 字符串是 UTF-16,SHA-1 要的是字节序列,所以先用 new TextEncoder().encode(str) 转成 UTF-8。这个 TextEncoder 处理的是未配对的代理项时按 U+FFFD 替换,因此一段落单的半个代理对不会让程序崩掉,但算出来的摘要和「真的补全了那个 emoji」不一样。这类输入在正常粘贴里很少遇到,用本页的字节数对照卡可以快速排除。

完整示例(数值均为实测)

输入框里的示例是两行 ASCII:liuquan.net 回车 SHA-1 2026,末尾没有换行符。它一共 22 个 UTF-8 字节(换行符算 1 字节),填充后 64 字节、只跑 1 个压缩块,摘要为:

  • 699c34734693168287a30547ed59ba2f7cbc8359(40 位,160 比特)
  • UTF-8 字节数 22、UTF-16 码元数 22、填充后 64 字节、压缩块数 1

这组数字和命令行的结果完全一致,可以直接拿来核对:

printf 'liuquan.net\nSHA-1 2026' | sha1sum 会输出 699c34734693168287a30547ed59ba2f7cbc8359。注意这里用 printf 而不是 echo:echo 会在末尾补一个换行,字节数变成 23,摘要随之完全不同。这是新手对照时最常见的「我明明输的一样」却对不上的原因。

换一组编码差异更明显的输入:abc 是 3 字节,摘要 a9993e364706816aba3e25717850c26c9cd0d89d;中文测试 是 4 个汉字、12 个 UTF-8 字节,摘要 cf8a8e8f68b4e267920dba0a5f3037180cc1afd9;单个表情 🎉 是 1 个字符但 4 个字节,摘要 c20dbb2b07fda1984738634fb3360853f280af14。三个输入的字符数分别是 3、4、1,字节数却是 3、12、4——这组对照说明为什么摘要必须连字节带长度一起理解。

输入范围、对照表与常见误用

下面是 FIPS 180-1 附录 A 与 RFC 3174 给出的官方向量。本页的自实现与这五组逐条对拍一致,你可以逐条粘进来验证:

输入字节数压缩块数SHA-1 摘要
(空串)01da39a3ee5e6b4b0d3255bfef95601890afd80709
abc31a9993e364706816aba3e25717850c26c9cd0d89d
message digest141c12252ceda8be8994d5fa0290a47231c1d16aae3
abcdefghijklmnopqrstuvwxyz26132d10c7b8cf96570ca04ce37f2a19d84240d3a89
a × 1000000(一百万个 a)10000001562634aa973cd4c4daa4f61eeb2bdbad27316534016f
The quick brown fox jumps over the lazy dog4312fd4e1c67a2d28fced849ee1bb76e7391b93eb12
liuquan.net ⏎ SHA-1 2026(示例)221699c34734693168287a30547ed59ba2f7cbc8359
hello world1112aae6c35c94fcfb415dbe95f408b9ce91ee846ed
liuquan710bc940560a116cb2c360ad0cfb80cd3d87dde18a
123456617c4a8d09ca3762af61e59520943dc26494f8941b
中文测试121cf8a8e8f68b4e267920dba0a5f3037180cc1afd9
🎉41c20dbb2b07fda1984738634fb3360853f280af14

再看一组中文字段的常见误用对照,四行输入的字符数看起来差不多,摘要却完全不同:

想表达的意思实际字节SHA-1 摘要问题出在哪
abc3 字节a9993e364706816aba3e25717850c26c9cd0d89d基准值
abc 加一个末尾换行4 字节03cfd743661f07975fa2f1220c5194cbaff48451粘贴时多带了一个换行
abc 开头加 UTF-8 BOM6 字节0bd332e7dbe318a5f1258e1eae113b2b0e69dbef记事本另存为可能悄悄加 BOM
abc 改成 ABC3 字节3c01bdbb26f358bab27f267924aa2c9a03fcfdb8大小写敏感,摘要完全不同
abc 前后各一个空格5 字节394d62b149f8a0aef1ca9a65d09f8df5e9d9d0c7空格也算字节
密码(2 个汉字)6 字节c839a8ff17885af0b098662ccc3ac5e3111b3b3b换成 GBK 只剩 4 字节,摘要变 135fd425…

边界、精度与 SHA-1 的实际风险

  • 输入上限 40000 字节 UTF-8(输入框的 maxlength 是按字符设的 40000,纯 ASCII 时上限即 40000 字节)。对应到不同文本:纯中文约 13333 个汉字,纯 emoji 约 10000 个,因为一个汉字 3 字节、一个 emoji 4 字节。40 KB 的文本跑 80 轮 × 626 块,在浏览器里是毫秒级,不会卡住页面。
  • 空输入是合法的,摘要就是 da39a3ee5e6b4b0d3255bfef95601890afd80709。这不是计算失败——SHA-1 对空串本来就有确定的输出,页面上会照常给出结果并在「字节数」显示 0。只有输入超过 40000 字符时才会提示(输入框装不下),不会静默截断已有内容。
  • 摘要长度恒为 40 个十六进制字符,对应 160 比特,5 个 32 位字。压缩块数随长度变化:不足 55 字节是 1 块,55 字节仍是 1 块,56 字节跳到 2 块,之后每多 64 字节加一块。一百万个 a 要跑 15626 块——这也是生日攻击成本的实际量级来源。
  • SHA-1 与 MD5 是同一个摘要宽度,都是 160 位,所以两者的碰撞搜索成本都是约 2⁸⁰ 次(1.209 × 10²⁴)。但攻击代价已经从理论变成了现实:2017 年的 SHAttered 用约 6500 美元、110 GPU 年算出一对具有相同摘要的 PDF;2020 年的 SHAmbles 把成本压到约 1 万美元、租算力 0.5 小时。区别在于 MD5 的碰撞可以任意构造内容,SHA-1 早期受制于需要相近前缀。
  • 长度扩展攻击(length extension)是 SHA-1 另一类风险,而且不需要找到碰撞。Merkle–Damgård 结构把最终状态直接输出,攻击者拿到 H(P‖M) 后,可以在不知道 P 的情况下推出 H(P‖M‖pad‖ext) 的值——只要协议是「H(secret‖message)」这种拼接形式,攻击者就能在末尾追加任意内容并算出新的有效摘要。SHA-256/SHA-3 因为结构不同不受此影响。MAC 不要用裸 H(secret‖m),要用 HMAC。
  • NIST 已把 SHA-1 移出数字签名的推荐清单,理由是碰撞已成为可实现的事实。本摘要仍可用于非对抗场景下的完整性自检、去重指纹、缓存键;但凡是涉及身份认证、代码签名、证书链、去重防篡改(攻击者能同时提交两份内容),都应该换 SHA-256 以上,需要抗碰撞的场景用 SHA-3 或 BLAKE 系列。
  • 摘要不区分大小写,但区分前导零的宽度。摘要必须写成 8 位补零的十六进制:若某字节是 0x07,要写成 07 而不是 7,否则长度不足 40 位。这是手写验证脚本时最常见的对不上原因。

常见问题

为什么我不能直接用浏览器的 crypto.subtle 算 SHA-1?

可以用,但有两个真实约束。第一,算法名必须写 'SHA-1' 或 'sha-1',写成 'SHA1'、'Sha1' 会抛 NotSupportedError: Unrecognized algorithm name。第二,crypto.subtle 只在安全上下文存在:HTTPS 或 localhost 下才有对象,页面从 HTTP 打开时 crypto.subtle 整个是 undefined,此时直接调会抛错而不是自动降级。本页把内联实现作为主路径,正是为了不依赖这两个条件;你可以在控制台敲 crypto.subtle.digest('SHA-1', new TextEncoder().encode('abc')) 验证当前环境是否支持,返回 a9993e36… 就说明支持。

SHA-1 和 MD5 到底哪个更不安全?

摘要宽度相同,都是 160 位,理论碰撞成本都是 2⁸⁰ 次。实际进展上 MD5 更早被攻破:2004 年 Wang 等人给出实用碰撞,2008 年 MD5 已被彻底排除碰撞安全性,且碰撞可被任意构造。SHA-1 在 2017 年才出现第一对公开碰撞(SHAttered),2020 年的 SHAmples 把成本压到 1 万美元级别。结论是两者都不该再用于任何安全用途;非对抗场景下 160 位摘要仍然够用,不必为了这件事专门换 SHA-256。

为什么我改了内容但摘要看起来「差不多」?

SHA-1 没有可察觉的「相似摘要」——改 1 个比特,160 位里平均 80 位会变,看起来完全不同。如果你觉得两个摘要接近,看的是十六进制字符串的前几位而已,那只是碰巧。要验证改动是否生效,比对完整的 40 位字符串,或者干脆看字节数是否变了。

末尾多一个换行符,摘要就完全不同吗?

是的,这是最容易踩的坑。示例 liuquan.net\nSHA-1 2026 是 22 字节,摘要 699c3473…c8359;在末尾加一个换行变成 23 字节,摘要会完全变成另一个值。命令行对照时请用 printf '...' | sha1sum 而不是 echo '...' | sha1sum,因为 echo 会自动追加换行。同样,用记事本另存为 UTF-8 时也可能悄悄加上 BOM(3 字节 EF BB BF),开头差 3 字节、摘要立刻不同。

中文和 emoji 算出来的字节数怎么判断?

UTF-8 编码里 ASCII 占 1 字节,汉字占 3 字节,常见 emoji 占 4 字节。页面上「UTF-8 字节数」直接给出结果,不用自己算。举例:中文测试 是 4 个字符、12 字节;🎉 是 1 个字符、4 字节;示例 liuquan.net\nSHA-1 2026 是 22 个字符也是 22 字节(因为全是 ASCII 加一个换行)。字符数与字节数一致时才说明全是 ASCII。

能不能用它来存密码?

不能。SHA-1 设计目标是速度,现代 GPU 每秒能算上百亿次,正好符合「越快越好」的要求,所以非常适合暴力破解。存密码需要慢哈希加随机盐:Argon2id、bcrypt、scrypt、PBKDF2 都是标准选择。另外,即使加上盐,SHA-1 只有 160 位输出,理论上也有碰撞风险——攻击者若能构造两份内容摘要相同的文件,就可能绕过基于摘要的校验。摘要相同不代表内容相同,这是 SHA-1 与 SHA-256 的本质差别。

填 56 个字符的时候为什么块数变了?

因为 SHA-1 的填充规则要留 8 字节放比特长度,还要 1 字节放 0x80 结束标记。55 字节时 55 + 1 + 8 = 64,正好一块;56 字节时 56 + 1 + 8 = 65,凑不满 64 的整数倍,必须再开一块。页面上「填充后总字节」和「压缩块数」两项能直接看出这个跳变。附带一提,a 重复一百万次的官方向量要跑 15626 个块,这也是生日攻击成本的实际来源。

我输入的内容会被上传或保存吗?

不会。摘要由页面内联的 JavaScript 计算,全程没有任何 fetch 或 XMLHttpRequest 调用,也不写 localStorage。刷新页面后输入框会回到那段预置示例。想自己确认,打开开发者工具的 Network 面板,输入文字时观察是否有请求发出——不会有。本页也不会把摘要提交给任何接口做二次校验。

相关工具

  • MD5加密:同样是 160 位摘要,讲解 MD5 的填充与轮函数差异,以及它为何更早被攻破。
  • SHA256加密:256 位摘要,抗碰撞强度是 SHA-1 的 2⁹⁶ 倍,签名的默认选择。
  • SHA512哈希生成器:512 位摘要,与 SHA-256 属同一 Merkle–Damgård 结构,可对照看长度扩展条件。
  • 在线哈希生成器:一次输出 MD5、SHA-1、SHA-256、SHA-512 四种摘要,适合横向比对。
  • 哈希值识别器:手里有一串十六进制、不确定它是哪种算法的输出时用它反查。
  • 十六进制转十进制转换器:把摘要的每一段拆成十进制看规律,调试位运算时常用。
  • 编码解码:查看全部编码解码工具。