同一段文字算出不同的 SHA 哈希,先核对输入字节、算法和输出格式。这几处可能同时有差异。下面用不带换行的 test 作对照,再检查中文编码、空文本和文件读取方式。
先给结论
1. 用 test 核对算法和输出格式
下表是文本 test 的计算结果,输入为 4 个 UTF-8 字节,不含引号或换行:
| SHA-256 | 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 | n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg= |
| SHA-384 | 768412320f7b0aa5812fce428dc4706b3cae50e02a64caa16a782249bfe8efc4b7ef1ccb126255d196047dfedf17a0a9 | doQSMg97CqWBL85CjcRwazyuUOAqZMqhangiSb/o78S37xzLEmJV0ZYEff7fF6Cp |
| SHA-512 | ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff | 7iaw3Ur350mqGo7jwQrpkj9hiYB3Lkc/iBml1JQODbJ6wYX4oOHV+E+IvIh/1nsUNzLDBMxfqa2Ob1f1ACio/w== |
三组十六进制输出长度分别是 64、96、128 个字符,对应 256、384、512 位。先把算法和输出格式设成与对方一致,再计算 test。结果相同只能确认这组输入的计算正确;实际业务中的编码、文件读取和参数仍需分别核对。
安装了 Python 3 时,可以用标准库独立复核 SHA-256;此命令不会给输入附加换行:
python -c "import hashlib; print(hashlib.sha256(b'test').hexdigest())"
hexdigest() 返回十六进制字符串,digest() 返回摘要字节,二者不能直接作为同一种文本比较。接口说明见 Python hashlib 文档。
2. 中文和 emoji 按 UTF-8 编码后再哈希
本工具先将文本编码为 UTF-8,再计算摘要。你好 🌍 的字节序列如下:
e4 bd a0 | e5 a5 bd | 20 | f0 9f 8c 8d
你 好 空格 🌍(4 字节)
空文本对应空字节序列,同样有合法摘要。不完整的 Unicode 字符需单独注意:本工具把孤立代理项 \\ud800(一个未配对的 UTF-16 编码单元)替换为 U+FFFD,对应字节 ef bf bd;Python 默认的严格 UTF-8 编码会拒绝这个输入。
对于正常 Unicode 文本,Python 显式使用 UTF-8、Node 使用 UTF-8、本工具使用 UTF-8 时,输入字节可以一致。若一端使用 GBK,或添加了 BOM(文本文件开头的编码标记),就不应预期得到同一哈希。先比较输入的十六进制字节,再查摘要计算。本工具也不自动统一 Unicode 规范化形式:预组合字符 é 与 e 加组合重音可能看起来一样,字节却不同。
3. 空字符串和末尾换行会得到什么结果
空字符串的 SHA-256 十六进制值是 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855。这是合法结果。如果本来应有内容,需检查读取或传参时是否丢失了输入。
从日志或 HTTP 请求体复制文字时,应检查末尾是否有换行。test 是 4 字节,带一个 LF 换行的 test\\n 是 5 字节,后者的 SHA-256 为 f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2。这里的 \\n 表示实际换行,不是反斜杠和字母 n。
排查时依次比较字节长度、换行形式(LF 或 CRLF)和 UTF-8 BOM(ef bb bf)。只有确认某个字符是误带入的,才删除它;原文件中的换行也属于待校验内容。
4. 文件按原始字节哈希,不走文本编码
文件模式不解码文本,直接对字节做摘要。实测字节 00 01 02 ff 的 SHA-256 是 3d1f57c984978ef98a18378c8166c1cb8ede02c03eeb6aee7e2f121dfeee3e56。
同一个 CSV,粘贴文本与选择文件可能得到不同结果:编辑器可能改动换行或移除 BOM,文本模式还会重新编码为 UTF-8。校验下载文件时,应选择原文件,保留所有原始字节。工具在浏览器本地读取文件并计算摘要,不上传文件内容。
当前文件模式会一次性把文件读入内存。较大的文件可能占用较多内存或读取失败,这种情况可用本机支持分块读取的校验工具。
5. 十六进制和 Base64 只是两种写法
同一份摘要字节可以写成两种文本。字节 00 01 0f 10 fe ff 的十六进制是 00010f10feff,Base64 是 AAEPEP7/。本工具使用标准 Base64 字母表,放入 URL 查询参数时应使用 URL 参数编码。
比较前先确认算法和输出格式,例如“SHA-256、十六进制”。十六进制可以统一大小写,本工具输出小写;Base64 区分大小写,不能对它进行大小写转换。若要比较不同表示,应还原成摘要字节,或统一输出格式。尤其不要把十六进制字符串本身再做 Base64 编码,那会得到另一份数据。
6. 在线计算 SHA 哈希
文本和文件都能在浏览器本地算,不经过服务器。你可以在 哈希生成器 里操作:选 SHA-256、SHA-384 或 SHA-512,再选十六进制或 Base64 输出,文本按 UTF-8 编码,空文本也有有效哈希。
7. 常见错误清单
| test 都对不上 | 算法、输出格式或输入有差异 | 确认是 4 个字节,再与第 1 节比较 |
| 中文哈希跨语言不一致 | 文本编码、BOM 或规范化形式有差异 | 比较输入字节的十六进制 |
| 空输入得到 e3b0c44… | 空输入的正常结果 | 若预期有内容,检查读取与传参 |
| 带换行后结果不同 | 输入字节发生变化 | 核对换行是否属于原始内容 |
| 文件和粘贴文本结果不同 | 文本模式经过 UTF-8 编码,文件模式用原始字节 | 校验文件用文件模式,核对文字用文本模式 |
| 十六进制和 Base64 对不上 | 表示方式不同,也可能摘要本身不同 | 统一输出格式;仅十六进制可统一大小写 |
| 当前浏览器无法使用 Web Crypto。 | 非安全上下文、不支持摘要 API,或文件读取等操作失败 | 使用 HTTPS 或 localhost,并检查文件是否能正常读取 |
相同算法下,摘要不同就能确定输入字节不同;摘要相同则不能在数学上排除碰撞,即不同输入得到同一摘要。文件校验还必须从可信发布渠道取得预期哈希。若文件和哈希一起被替换,比对仍会通过;验证发布者身份需要可信签名或可信分发渠道。SHA 算法定义见 NIST FIPS 180-4。
8. 常见问题(FAQ)
- 哈希能还原成原文吗? 没有通用的解码操作,但短口令等可猜测输入能通过枚举候选值逐一比对。哈希不等于保密。
- 空字符串有哈希吗? 有。SHA-256 是 e3b0c44…b855,这是合法输出。
- SHA-256、SHA-384、SHA-512 选哪个? 三者属于 SHA-2 系列,输出长度和内部算法参数不同,不能把 SHA-512 截断当成 SHA-256。已有校验值用什么算法,就选择什么算法。
- 文件会上传吗? 不会。浏览器在本地读取字节并计算,内容不经过服务器。
- 十六进制和 Base64 哪个对? 都对,是同一摘要的两种写法。比较前先统一成一种。
- 可以用这个工具存储登录密码吗? 不应直接用一次 SHA 摘要存储密码。服务端应采用 Argon2id 等专门的密码哈希方案,并配置独立盐值和计算成本,参见 OWASP 密码存储指南。
核验依据
本文于 2026-09-06 核对当前核心实现、页面文件读取及错误映射。Vitest 3.2.7 下,相关测试文件 6 项通过;表中六个摘要另用 Node 原生哈希计算交叉核对,换行示例也已计算验证。仓库内复现命令:
pnpm test src/tools/hash-generator/core.test.ts –reporter verbose


