魔法哈希 - PHP哈希"碰撞"
使用密码1注册,然后使用密码2登录。如果成功登录,说明存储使用了指定算法来哈希密码,而PHP使用==
来比较它们(适用于MD5、SHA-1和明文)。
MD5、SHA-1、SHA-224、SHA-256等
对于MD5、SHA-1和SHA-2系列,它利用了一个众所周知的技巧(实际上是一个已记录的特性,参见PHP类型比较表和浮点数),即在PHP中'0e1' == '00e2' == '0'
,只是将其用于实际目的。列表中的任何密码都匹配其他任何密码。这与整数字符串溢出为浮点数的技巧不同,请注意这两行之间的区别。
以下是所有具有魔法哈希的算法:
- CRC32
- CRC32b
- FNV-1a/32
- FNV-1a/64
- FNV-1/32
- FNV-1/64
- HAVAL-128,3
- HAVAL-128,4
- HAVAL-128,5
- HAVAL-160,3
- HAVAL-160,4
- HAVAL-160,5
- JOAAT
- MD2
- MD4
- MD5
- MurmurHash3_x86_32/Murmur3a
- MurmurHash3_x86_128/Murmur3c
- MurmurHash3_x64_128/Murmur3f
- PHOTON-80/20/16
- PHOTON-128/16/16
- PHOTON-160/36/36
- Quark u-Quark-136
- RIPEMD-128
- RIPEMD-160
- SHA-1
- SHA-224
- SHA-256
- SPONGENT-88/80/8
- SPONGENT-88/176/88
- SPONGENT-128/128/8
- SPONGENT-128/256/128
- Tiger/128,3
- Tiger/128,4
- Tiger/160,3
- Tiger/160,4
- Tiger/192,3
- xxHash-XXH32
- xxHash-XXH64
- xxHash-XXH3_64bits
- xxHash-XXH3_128bits
引用@0xb0bb的话,"魔法哈希除了密码比较之外还有其他应用(如缓存层或源自哈希函数输出的数据),在这些应用中更容易找到这些已知不安全、鲜为人知和伪哈希算法。"
明文
对于明文,它使用各种转换技巧。第一个密码将只匹配第二个密码。技巧按允许使用它们的PHP版本分组。
bcrypt
bcrypt 将密码截断为最大长度72个字符。如果两个密码的前72个字符相匹配,则这两个密码被视为匹配。
descrypt
descrypt(传统UNIX DES加密)将密码截断为最大长度8个字符。如果两个密码的前8个字符相匹配,这两个密码也被视为匹配,详见"通用交叉检查"部分。
PBKDF2-HMAC-SHA1, PBKDF2-HMAC-SHA224, PBKDF2-HMAC-SHA256
如果使用长度超过64字节的密码并用PBKDF2-HMAC-SHA1进行哈希处理,它会首先用SHA1进行预哈希,因此PBKDF2-HMAC-SHA1(password1) === PBKDF2-HMAC-SHA1(password2)
,因为sha1(password1) === bin2hex(password2)
。类似的预哈希处理也适用于PBKDF2-HMAC-SHA224和PBKDF2-HMAC-SHA256。
Tiger/192,3
目前每个类别中只有一个魔法哈希值,这要感谢Norbert Tihanyi的贡献,希望未来能添加更多。
结论
在PHP中比较任何东西*时使用===
,而不是==
。对于PHP中的密码哈希,请使用password_hash()
和password_verify()
,不要使用MD5或SHA-1。*比较哈希值时使用hash_equals()
。
历史
这一切始于2014年2月的一条推文,我生成了QNKCDZO
和240610708
,此后它在互联网上广为流传。只需在谷歌上搜索一下就能看到。
- MD5: 推文,代码,贡献者包括 roycewilliams、Norbert Tihanyi、ethernetlord、0xb0bb、myst404
- SHA-1: 推文,代码,贡献者包括 roycewilliams、0xb0bb、matlink、myst404、Maxim Masiutin
- 明文: 推文,代码
- bcrypt: 代码
- PBKDF2-HMAC-SHA1 由 Christian "CodesInChaos" Winnerlein 提供,Mathias Bynens 解释,代码
- PBKDF2-HMAC-SHA224 由 Norbert Tihanyi 提供,代码
- PBKDF2-HMAC-SHA256 由 Jens 'atom' Steube 提供,代码
- Tiger/192,3 由 Norbert Tihanyi 提供
- SHA-224 由 Norbert Tihanyi、hops、0xb0bb、myst404、Maxim Masiutin 提供
- SHA-256 由 Norbert Tihanyi、Chick3nman、roycewilliams、matlink 提供
- CRC32、CRC32b、FNV-1a/32、FNV-1a/64、FNV-1/32、FNV-1/64、HAVAL-128,3、HAVAL-128,4、HAVAL-128,5、HAVAL-160,3、HAVAL-160,4、HAVAL-160,5、JOAAT、MD2、MD4、RIPEMD-128、RIPEMD-160、Tiger/128,3、Tiger/128,4、Tiger/160,3、Tiger/160,4 由 0xb0bb 提供
- descrypt 由 James M. Hall 和 hops 提供
- PHOTON-80/20/16、PHOTON-128/16/16、PHOTON-160/36/36 由 Norbert Tihanyi 和 Bertalan Borsos 提供
- u-Quark-136 由 Norbert Tihanyi 和 Bertalan Borsos 提供
- SPONGENT-88/80/8、SPONGENT-88/176/88、SPONGENT-128/128/8、SPONGENT-128/256/128 由 Norbert Tihanyi 和 Bertalan Borsos 提供
- xxHash 由我提供(#27)
- MurmurHash3 由我提供(#28)
如何计算您自己的哈希
2014年时,我使用了我的笔记本电脑、几个 for
(或 foreach
?)循环、大量的 CPU 周期和一个外置风扇,但如今您可以/应该使用 GPU 和修改过的 hashcat。请参阅 Carl Löndahl 和 0xb0bb 的这篇文章。
Chick3nman & co. 也正在开发他们自己版本的 hashcat,敬请关注。
真实碰撞
如果你需要一个真正的字母数字碰撞,这里有一个由 Marc Stevens 提供的 72 字节字母数字 MD5 碰撞,只有 1 字节差异,甚至只有 1 比特差异:
md5("TEXTCOLLBYfGiJUETHQ4hAcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak")
=
md5("TEXTCOLLBYfGiJUETHQ4hEcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak")
请注意,如果你用第一个密码注册,然后用第二个密码登录,这可能仍然意味着该网站使用的是 bcrypt(md5($password))
,而不仅仅是 md5($password)
。这种哈希包装有时在升级密码哈希时使用,但应该只是临时使用。
如果你对这些真实碰撞感兴趣,或者想要创建自己的碰撞,可以查看 Marc 的 Project HashClash。