哈希算法里SHA256是绕不开的,比特币用它造地址,HTTPS证书签名用它,文件完整性校验用它,Git的提交ID也是它的变体。但真问起来256位输出怎么来的、为什么不能逆推、抗碰撞什么意思,能答全的不多。其实SHA256的原理拆开看就是位运算反复搅动,懂了之后你才知道它为什么安全、为什么改一个字节结果就面目全非。
哈希到底是什么
哈希函数是把任意长度输入映射成固定长度输出的函数,特点是单向、定长、雪崩。单向是指从输出反推输入计算上不可行,你拿到哈希值没法倒推出原文。定长是无论输入1字节还是1GB,SHA256输出都是256位也就是32字节。雪崩是输入改一个比特,输出变化巨大,理论上约一半比特翻转。
哈希不是加密。加密是可逆的,有密钥能解。哈希不可逆,没有解密这回事。所谓MD5解密网站,其实是用彩虹表反查常见输入,不是数学上的逆运算。对于足够随机足够长的输入,哈希无法反推。
SHA256的结构
SHA256属于SHA-2家族,输出256位。它的核心是Merkle-Damgard结构,把输入切成512位一个块,逐块处理。先对输入做填充,补1和若干0让总长度模512等于448,最后64位存原始长度。然后初始化8个32位的哈希值,作为初始状态。
每个512位块进入压缩函数,块再切成16个32位字,扩展成64个32位字。然后跑64轮运算,每轮包含消息调度、轮函数、常量加、状态更新。轮函数里用到位运算:与、或、非、异或、循环右移、循环右旋。64轮后把结果加到当前哈希状态上,进入下一块。所有块处理完,8个32位状态拼起来就是256位输出。
这套设计的核心是每一步都把输入比特充分扩散。经过64轮位运算搅动,输入的每个比特都影响输出的每个比特,所以改一个字节,输出几乎完全变化,这就是雪崩效应的来源。
为什么不可逆
SHA256的每一步都是信息损失的。轮函数里的与或非操作不可逆,比如A与B等于1,你没法倒推出A和B各是啥。循环移位可逆但配合压缩就不可逆了。每轮把512位输入映射成256位状态,信息量减少一半,数学上不可逆。所以从输出反推输入,只能穷举所有可能输入去试,对于长输入计算上不可行。
对于短输入,比如6位密码,可以暴力枚举。这就是为什么哈希存密码要加盐,盐是随机串,让攻击者不能拿预计算的彩虹表批量反查。盐加上后即使两人同密码,哈希也不同。
抗碰撞是什么
哈希的安全性体现在三个性质。抗原像,给输出找输入,计算上不可行。抗第二原像,给一个输入找另一个同输出的输入,不可行。抗碰撞,找任意两个同输出的输入,不可行。SHA256这三个性质在当前算力下都成立。
抗碰撞和生日攻击有关。生日攻击是说,输出n位,找碰撞大约需要2的n除2次方次运算,不是2的n次方。对SHA256,n是256,n除2是128,所以找碰撞需要约2的128次方次,现实不可行。这就是为什么SHA256被认为安全。SHA1的n是160,n除2是80,2的80次方在大型算力下接近可行,所以SHA1被淘汰,Google的SHAttered攻击就实战碰撞了SHA1。
SHA256的安全边界
目前没有实用攻击能破SHA256。理论上的区分攻击把安全性削弱一点,但实际影响微乎其微。量子计算机的Grover算法能把搜索复杂度从2的n次方降到2的n除2次方,对SHA256抗原像相当于128位安全,仍然够用。所以后量子时代SHA256仍被认为安全,不像RSA那样要换。
实际泄露不在算法而在用法。常见坑:用SHA256存明文密码不加盐,彩虹表秒破。用SHA256做消息认证不加密钥,可被伪造。把SHA256当加密用,它根本不能解密。正确用法是密码加盐哈希、消息认证用HMAC、完整性校验对比哈希值。
常见问题
【SHA256能解密吗?】不能。哈希不可逆,没有解密这回事。网上所谓的解密是彩虹表反查常见输入,对随机或加盐输入无效。要保密数据用AES,不是SHA256。
【SHA256和MD5什么区别?】MD5输出128位,SHA256输出256位。MD5已被攻破能实战碰撞,不能用于安全场景。SHA256目前安全,是主流选择。文件校验、数字签名都用SHA256或更高。
【为什么Git用SHA1不安全?】Git的对象ID是SHA1,理论上有碰撞风险。Git团队已迁移到SHA256,新仓库可选SHA256模式。对历史仓库,Git通过强制碰撞内容约束缓解,但长期建议迁移。
【量子计算机会破SHA256吗?】不会破。Grover算法把抗原像安全性降到128位,仍足够安全。后量子加密标准主要换公钥算法如RSA和ECC,对称算法和哈希多数保持不变。