Intereting Posts

Crypt для хэширования паролей. Blowfish производит странный выход

У меня немного немного проблем с пониманием функции криптографии php. Моя версия PHP – 5.4.7.

Я хочу использовать crypt для хранения соленых паролей в базе данных, потому что, насколько мне известно, разработчики, которые используют md5 для хэш-паролей, должны быть скопированы и сожжены на месте.

Я хотел использовать мусорный напиток, чтобы создать хэш. Теперь, согласно документации php, crypt использует blowfish, если вы называете его «$ 2y $» + стоимость (например: «08») + «$» + 22 символа salt (./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 

Загадочный склеп заполняет соль с помощью $, если он недостаточно длинный. Соль меняется, а также хеш. Таким образом, выходные данные в строках 1 и 2 соответствуют ожиданиям.

Однако меня озадачивают последние три хэша: очевидно, что точка отделяет хэш от соли (?), Но если вы на самом деле даете крипту 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-го символа, 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 .