哈希是什么,不是什么
哈希函数可以把任意长度的输入(一个词,或几个GB的文件)变成固定长度的值,称为哈希值或摘要。设计良好的密码学哈希函数应具备三个性质: 相同输入总是得到相同输出;从输出反推输入在现实中不可行(抗原像性);找到两个输出相同的不同输入在现实中不可行(抗碰撞性)。 输入只改动一个字符,输出就应当面目全非,这叫雪崩效应。用本工具计算SHA-256,hello与Hello的结果在256位中约有125位不同, 接近好函数应有的“一半左右”(这是实际计算得到的数值)。
哈希不是加密。加密有密钥就能还原,哈希根本没有还原的路径。所谓“哈希解密”并不准确,网上声称能做到的网站, 只是在预先算好的常见字符串对照表里查找而已。
如何选择算法及其安全状况
输出长度以比特计,写成十六进制的位数为比特÷4(下表按此公式计算)。输入同一段文本,就能看到各算法的长度正是这样不同。
| 算法 | 输出比特 | 十六进制位数 | 发布年份 | 本工具 | 状态 |
|---|---|---|---|---|---|
| MD5 | 128 | 32 | 1992 | 不支持 | 存在实用的碰撞攻击,不可用于安全场景(仅作普通校验和尚可) |
| SHA-1 | 160 | 40 | 1995 | 支持 | 2017年公开了真实碰撞(SHAttered),不可用于安全场景 |
| SHA-256 | 256 | 64 | 2001 | 支持 | 广泛使用的标准,未发现实用攻击 |
| SHA-384 | 384 | 96 | 2001 | 支持 | SHA-512的截短版本,未发现实用攻击 |
| SHA-512 | 512 | 128 | 2001 | 支持 | 在64位CPU上常比SHA-256更快,未发现实用攻击 |
MD5与SHA-1:可作校验和,不可用于安全
2004年有研究者公布了构造MD5碰撞的方法,此后攻击不断改进,如今用普通电脑就能在短时间内造出MD5相同的两个不同文件。 据报道,这一弱点在2012年被Flame恶意软件用于伪造证书。SHA-1也在2017年被谷歌和CWI的研究人员公开了真实碰撞(SHAttered), 美国NIST也表示将逐步淘汰SHA-1,到2030年转向SHA-2和SHA-3。凡是攻击者可能介入的场景,如电子签名、证书、分发软件的防篡改,都不应使用。 在没有攻击者的场景里,例如检查传输是否损坏、生成缓存键、查找重复文件,它们仍被广泛使用。版本控制工具Git至今用SHA-1命名对象, 但那不是签名用途,已加入针对已知碰撞攻击的防护,并且正在迁移到SHA-256。新系统请不要选择它们。
SHA-2系列
SHA-256、SHA-384、SHA-512属于SHA-2系列,由美国国家安全局设计,NIST于2001年标准化,广泛用于证书、代码签名、包管理器和区块链, 目前没有已知的实用碰撞攻击。SHA-384是改了初始值并截短输出的SHA-512。大多数情况下用SHA-256即可;在64位环境下追求速度,或想要更大的安全余量,可选SHA-512。 2015年标准化的SHA-3内部结构完全不同,但本页依赖的Web Crypto API既不提供SHA-3也不提供MD5,所以本工具不能计算它们。
带密钥的认证请用HMAC
想证明消息来自持有密钥的一方时,不要简单地把密钥拼在消息前面做哈希。SHA-1、SHA-256、SHA-512在这种构造下容易遭受长度扩展攻击: 不知道密钥,也能算出在消息后追加数据的哈希值。应使用专门为此设计的HMAC。本工具只计算不带密钥的普通哈希。
绝不要用普通哈希存储密码
“密码要用哈希存储”只对了一半。它比明文存储强,但像SHA-256这样的通用哈希单独使用并不适合存密码,也不要用本工具来搭建这样的逻辑。原因有三:
- 太快。通用哈希为速度而设计,一块显卡每秒就能算几十亿次,数据库泄露后,对常见密码的穷举很快就能完成。
- 相同密码得到相同哈希。没有为每个用户随机生成的盐,攻击者可用预计算表批量破解,还能看出哪些用户用了同一个密码。
- 人选的密码空间很小。即使哈希本身安全,
password1这样的常见密码也会很快被字典攻击找到。
正确做法是使用专为密码设计、故意做得很慢且成本可调的Argon2id、scrypt、bcrypt或PBKDF2,它们内置或要求加盐。具体选用哪种、参数如何设置, 请查看OWASP的Password Storage Cheat Sheet等最新建议。如果只是想要一个给自己用的强密码,请用密码生成器,而不是靠哈希。
实际用途
校验下载的文件有没有被篡改
发布方在文件旁公布了SHA-256值时,可以自己计算文件的哈希再比较字符串。本工具只处理文本,不能读取文件。文件请用系统命令: Windows使用certutil -hashfile 文件名 SHA256;macOS和许多Linux系统使用shasum -a 256 文件名(Linux也可用sha256sum 文件名)。 如果校验值和文件出自同一个网页,篡改文件的人也可能同时改了校验值,所以最好从官网HTTPS或带签名的发布说明等另一渠道核对。
发现变更与重复
比较两个很短的哈希比比较两大块数据快得多,常用于判断配置是否变化、内容去重和生成缓存键。这些场景用SHA-256就足够了。
已验算的示例与常见陷阱
示例1。文本abc的SHA-1是a9993e364706816aba3e25717850c26c9cd0d89d,SHA-256是ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad。它们与这些算法公布的标准测试向量一致, 所以可以用abc来确认任何哈希工具是否工作正常。
示例2。hello的SHA-256是2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824, 改成Hello就变成185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969; 在hello后面加一个换行,开头就变成5891b5b5。
示例3。The quick brown fox jumps over the lazy dog的SHA-256以d7a8fbb3开头,句末加一个句点后以ef537f25开头。
- 看不见的字符。末尾的空格、换行,或Windows的CRLF与Unix的LF之别,都会改变哈希。与其他工具对不上时先查这里。
- 编码。本工具把文本按UTF-8字节计算。含中文时,与按GBK等其他编码算出的值不会一致。
- 文本与文件的区别。编辑器保存的文本文件可能带BOM或末尾换行,看起来一样,哈希却可能与粘贴文本的哈希不同。
- 位数混淆。十六进制40位是SHA-1,64位是SHA-256,96位是SHA-384,128位是SHA-512,凭位数大致就能判断算法。
- 大小写。十六进制中的字母不区分大小写,比较时请统一写法,以免出现并不存在的“不一致”。
本工具的局限
仅支持文本,不能读取文件,也不计算MD5、SHA-3、HMAC、加盐哈希,以及bcrypt、Argon2这类密码哈希。计算通过Web Crypto API在浏览器内完成, 输入的内容不会发送到服务器。即便如此,也不要养成把真实密码或机密粘贴到自己无法掌控的网页中的习惯。
常见问题
能从哈希值还原出原始文本吗?
数学上没有反推的办法。但较短或常见的内容可以通过猜测候选并对比哈希(字典攻击、查找表)被找到,所以做了哈希并不等于秘密就安全。
空格或换行会影响结果吗?
会。哈希按字节计算,多一个空格、换行符不同或大小写不同,都会得到完全不同的值。与其他工具结果不一致时,先检查换行和编码。
MD5和SHA-1应该完全弃用吗?
凡是与安全有关的用途,如签名、证书、密码存储、防篡改,都不要用。检查传输是否损坏、查找重复文件等非安全用途仍很常见。新设计请默认采用SHA-256或更强的算法。
把密码用SHA-256哈希后存储够安全吗?
不够。SHA-256计算极快,数据库泄露后容易被穷举,加盐也要自己处理。请通过可靠的库使用Argon2id、bcrypt、scrypt或PBKDF2。
不同的输入会得到相同的哈希值吗?
原理上会,因为输入有无穷多而输出有限。关键在于现实中能否找到这样的一对:MD5和SHA-1已被证明可以找到,SHA-2系列则尚无已知方法。
相关工具
- 密码生成器:生成难以猜测的密码
- 密码强度检测:查看密码有多容易被猜到
- Base64编码/解码:与哈希不同,可以还原的编码
- UUID生成器:生成唯一标识符