我无法理解PHP的crypt函数的一点点点。 我的PHP版本是5.4.7。
我想用地穴来腌密码存储在数据库中,因为据我所知,谁使用MD5开发商散列密码要放样烧毁现场。
我想用河豚ALG来生成散列。 现在,根据PHP文档,隐窝使用河豚,如果你用“$ 2Y $” +成本调用它(例如:“08”)+“$” + 22个字符盐(./0-9A-Za-z) 。 然而,测试代码这一点点的输出困惑我:
echo "<pre>";
if (CRYPT_BLOWFISH == 1) {
echo 'Blowfish SaltLen = 18: ' . crypt('string that should be hashed', '$2y$08$123456789012345678') . "\n";
echo 'Blowfish SaltLen = 19: ' . crypt('string that should be hashed', '$2y$08$1234567890123456789') . "\n";
echo 'Blowfish SaltLen = 20: ' . crypt('string that should be hashed', '$2y$08$12345678901234567890') . "\n";
echo 'Blowfish SaltLen = 21: ' . crypt('string that should be hashed', '$2y$08$123456789012345678901') . "\n";
echo 'Blowfish SaltLen = 22: ' . crypt('string that should be hashed', '$2y$08$1234567890123456789012') . "\n";
}
echo "</pre>";
输出:
Blowfish SaltLen = 18: $2y$08$123456789012345678$$$.Gq4WBozZb6XYmOJ88OC8gThSTUx8pRO
Blowfish SaltLen = 19: $2y$08$1234567890123456789$$.u8Qm7Q9KVtvo2zwpKkN5ntAxu71k2pO
Blowfish SaltLen = 20: $2y$08$12345678901234567890$.iIlIFEGaqDj6XbnKkK1F14HmMGLV.mu
Blowfish SaltLen = 21: $2y$08$123456789012345678901.iIlIFEGaqDj6XbnKkK1F14HmMGLV.mu
Blowfish SaltLen = 22: $2y$08$123456789012345678901uSFz9yPi/jA6e9aMcUkm7y.TJYhcCoSu
该apparantly隐窝充满盐和$如果它不是足够长的时间。 盐的变化也是如此哈希值。 所以如预期线1和2的输出。
更令人不解的我,却是最后三个哈希值:(?)Apparantly点从盐的方式隔开哈希但如果你真的给地穴22个字符它需要盐,点消失。 此外,从盐中的最后一个字符不会出现在输出中,但相比21字符盐改变了哈希值。
什么是特别令人困惑的是在输出3线和4! 盐显然是不同的,但哈希值是完全一样的。 我看不出在这个任何一致性,将不胜感激帮助。
您所看到的问题的原因是,它实际上并不使用盐的22个字符。 它只使用21.25字符。 第22字符的那么几个位用于盐,其余用于哈希(结果)。
原因是,该盐是不是一个字符串。 这是一个128位的数字。 数序列化为BASE64。 审查64是如何工作的基础上,每3字节块“翻译”成一个4字节块。
[byte1][byte2][byte3]
[new1][new2][new3][new4]
现在,请记住每个原始字节有8位。 因此,每个“新字节”只会有6位(因为我们没有添加信息,我们只是代表不同的看法)。
那么,有什么情况是,你只提供数据的21个字符。 其解码时转换为15.75字节。 但你不能有一个半字节。 所以,最后的解码块被丢弃(由于有信息不足)。 而那些6位,我们完全扔掉了地图21字符。
因此,如果没有从第22字符使用的2位,第21届一定要扔掉(因为部分字节没有意义)。
我们测试了这一点:
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./";
for ($i = 0; $i < strlen($chars); $i++) {
echo crypt('string that should be hashed', '$2y$08$12345678901234567890' . $chars[$i]) . "\n";
}
生产:
$2y$08$123456789012345678900.iIlIFEGaqDj6XbnKkK1F14HmMGLV.mu
$2y$08$123456789012345678901.iIlIFEGaqDj6XbnKkK1F14HmMGLV.mu
$2y$08$123456789012345678902.iIlIFEGaqDj6XbnKkK1F14HmMGLV.mu
.
.
.
$2y$08$12345678901234567890/.iIlIFEGaqDj6XbnKkK1F14HmMGLV.mu
但是,如果我们添加了一个22字节(不管它是什么):
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./";
for ($i = 0; $i < strlen($chars); $i++) {
echo crypt('string that should be hashed', '$2y$08$12345678901234567890' . $chars[$i] . 'a') . "\n";
}
然后,我们得到的随机分布的效果:
$2y$08$123456789012345678900OtUUu.EAOjrOztGKf2m.TZIe7HGzFgF.
$2y$08$123456789012345678901Ou28wcnld1gB2vjW9obdQdz6kLMasqKC
$2y$08$123456789012345678902Oum7Yp/p4TEeEC5JxsmnQsACNnnK0cv2
$2y$08$123456789012345678903OxMer1AD.P.UpAMlykl5SokMmDM1BU0W
$2y$08$123456789012345678904OpoNDsh7DaAoSjiZFJKO7iMy53BqwsjO
$2y$08$123456789012345678905OQRUqlnlEpBzccxrCgyZVtl6a.tQxNz6
$2y$08$123456789012345678906O6QMFdYZ.tvQpSdYaxlFl1Rlsk05/Aym
$2y$08$123456789012345678907OwF1TKI.OYT3xtBxg8tqex4L8mZttUCm
$2y$08$123456789012345678908OtzJXaS8/x0KYQ2epPRgVSjWSy/yAwMK
$2y$08$123456789012345678909O17D/xQeJGLIzpwBZuN2kxdpxi6p3aDq
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890bOD9Z5cUlQgJtvhqSOIK/3BV/1QIEmHby
$2y$08$12345678901234567890cOG5DxIU4B/ftl01V/MhViyi8YymLKEdC
$2y$08$12345678901234567890dOcd0.C8PVpjqW7oGI9AZuTVjNwxZDDpa
$2y$08$12345678901234567890eOLQSg5zmHm2nOCmRMdNeY8LxW1xMKnwm
$2y$08$12345678901234567890fOI.DZa4KuxngvaBT8JFtRWY8oRs9A266
$2y$08$12345678901234567890gOTA9XsdwxujLBdLaypPHehWjj1GyjDRC
$2y$08$12345678901234567890hOkS/cZmSqtdHSWz3zPkImTfZbHvdC8Wm
$2y$08$12345678901234567890iOXDaVzn/h7/oQtUgHyPodyggGkOqxFdW
$2y$08$12345678901234567890jODbaT2pRSwnD2qHm43YdAbHVPBJ8iapi
$2y$08$12345678901234567890kOrUyng3J5OCChkP6tHiM.rz4o4CdPkTO
$2y$08$12345678901234567890lOtscWm7fnlUJXZIXLKhVI7E2Abh7uc3i
$2y$08$12345678901234567890mOCeJM40E/G0WrJ4utkSaJwtZUMCae326
$2y$08$12345678901234567890nO4ac8AzrsXk6HpAtOaGEvGfS8eceFtSC
$2y$08$12345678901234567890oOv3BFJmdPMx9josbfOHHtu/7xgoGUygq
$2y$08$12345678901234567890pOPWQlIGa.WBx8kDEEG05uWhUioyNqWiq
$2y$08$12345678901234567890qOg2ufL5bmYfAoZEFknsRaSOlI4GVBKWy
$2y$08$12345678901234567890rOJZTvmghag6zIY5Ha7iOCgArPZGotche
$2y$08$12345678901234567890sOZjZ2OaVZy.GeXp/BQvjbCpXgNa/GAlK
$2y$08$12345678901234567890tO3bAZAMEXEZm72/mAkbJkefUua9CUFuy
$2y$08$12345678901234567890uOQ.i2vydj6OGyl84Qhg5OXPq7OkRQomu
$2y$08$12345678901234567890vOc9BKZfLu6mcd2mIfLtmT6C6JwDT.Siq
$2y$08$12345678901234567890wO7ow2JgV.7yzEsllHUbhbMrOMKXSihsq
$2y$08$12345678901234567890xOUI89zc5eDCCCHoTljMyXuGXmIz9b0PW
$2y$08$12345678901234567890yORmKbjoeO.1HSpQB7L5EBMSRjJr4lR62
$2y$08$12345678901234567890zOZkhGY/cILtgQRmHLkx//nuzLXSwLqYy
$2y$08$12345678901234567890AOuJWX5/tdzRCTTs5EXYioLP1t7u1Ao7u
$2y$08$12345678901234567890BO2vHWuKdbL2lsbBQwaAkWCXz/YVEaHP2
$2y$08$12345678901234567890COedKIdK.eAjm2zF0CAnuM9XxbO3CakoK
$2y$08$12345678901234567890DOpunwAyx9X4/tJzDmUXARABluQdRV7Ji
$2y$08$12345678901234567890EOB1ONHz9lELb7iUvtzTi.PTSgN2tFv1.
$2y$08$12345678901234567890FOplAZBguPKXbAQDxq9PXqgjH/1ZX6u7C
$2y$08$12345678901234567890GOP/G3kfN/r92DIQlC0eVyGi3jWRUoVXK
$2y$08$12345678901234567890HOmala7V1QCL7PX79yODRg2Y5lTq6i/ii
$2y$08$12345678901234567890IOWbq1AXhTucizWIBn58rgVYFpRxMpm8.
$2y$08$12345678901234567890JOxgmM1XAcDg7AUpzeHzHxn6z75ljNoDy
$2y$08$12345678901234567890KOTnfd7pzmfzf80CrXxWC24sK3y1DAbb6
$2y$08$12345678901234567890LOXxQX37TiNlNMfZUtMLZFrZah8u39q9K
$2y$08$12345678901234567890MOmpvWu3ZKbbilLb4f8QF6OUPPpEbsM42
$2y$08$12345678901234567890NO8VjZ2KNbOVoOzgP/Tjd6IFtwjRG2PJ2
$2y$08$12345678901234567890OOvSnZoahC5g1Ewlm6K7US13i6vJIQSqm
$2y$08$12345678901234567890POVs5m/8eCyLd11zjEPYoYhpaZAz6PYF2
$2y$08$12345678901234567890QOk4MBZhDwzS8dwJl6lm.hdAVBcllSid2
$2y$08$12345678901234567890ROWh4H3TuKSuFfrtx1vqHnU/RrQ0HrbNW
$2y$08$12345678901234567890SOd/USMzVBx6wyPgsuvAszCIVZ6zOA44O
$2y$08$12345678901234567890TO53YobspFDSFshtGX9hH4LTw2OT2T4P.
$2y$08$12345678901234567890UOMLp7HSCxWMMxgJVN6JTN7WRKlRPN17y
$2y$08$12345678901234567890VOmOMGgpLXOV/mft8WXOWXmQjc71SN6g2
$2y$08$12345678901234567890WOiAkYTQmitOHabdScoZivJ4JeKtJ6t7.
$2y$08$12345678901234567890XOUUqRtGjd/nob.UiRrJvFyKSMELAIuZe
$2y$08$12345678901234567890YOukccL1Y2PDV9ErOLHileZOq5m6zIzSy
$2y$08$12345678901234567890ZOMNrfK..n1YjuP3F.S4Taxn0XvIf5gXW
$2y$08$12345678901234567890.OmG2XbJMpLDBrtq44ptVtXkVaGdAT9oO
$2y$08$12345678901234567890/OTN4hG/XcY.FtrT85TGI.Vm0sH0tpQ.a
现在,为了证明我们只使用几个位最后一个字节,让我们改变的那一个,拿着固定的21:
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./";
for ($i = 0; $i < strlen($chars); $i++) {
echo crypt('string that should be hashed', '$2y$08$12345678901234567890a' . $chars[$i]) . "\n";
}
这里是:
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890aeDDHXF42QK8mY.t4/x9I.DNpdmARsDG.
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890auYqXTg7.1WNKn8Yxc4wW2p2ppsJb9rZa
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890aOQs9arCVhxFtQ.Z7yJUOtp8UCDsR1rHa
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
$2y$08$12345678901234567890a.FpXM0OnHV1fSxeBCiU8eEDae5LtBtAO
请注意如何只产生4个独特的哈希? 这是因为我们只使用最后一个字节的第2位(2 ^ 2)。 剩下的实际上是结果哈希的一部分(并因此扔掉)。
合理?
和BTW:这个和其他一些原因,我不会使用建议crypt()
直接,而是使用库。 如密码这是在PHP 5.5的到来,或它的兼容性库(这是我保持) password_compat 。
文章来源: Crypt for password hashing. Blowfish produces weird output