$ rails console
>> require 'digest'
>> def secure_hash(string)
>> Digest::SHA2.hexdigest(string)
>> end
=> nil
>> password = "secret"
=> "secret"
>> encrypted_password = secure_hash(password)
=> "2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b"
>> submitted_password = "secret"
=> "secret"
>> encrypted_password == secure_hash(submitted_password)
=> true
Здесь мы определили функцию secure_hash, которая использует криптографическую хеш-функцию SHA2, часть семейства хеш-функций SHA, который мы включаем в Ruby через библиотеку дайджеста. 7 Не важно точно знать, как работают эти хэш-функции;для наших целей важно, чтобы они были односторонними: нет вычисляемого способа обнаружить, что
2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b - это SHA2 * хэш * 10 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * если что о чем вы не думаете *, если вы думаете, 10 *однако, у нас все еще есть проблема: если злоумышленник когда-нибудь овладеет хешированными паролями, у него все равно будет шанс обнаружить оригиналы.Например, он мог догадаться, что мы использовали SHA2, и поэтому написал программу для сравнения заданного хэша с хешированными значениями потенциальных паролей:
>> hash = "2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b"
>> secure_hash("secede") == hash
=> false
>> secure_hash("second") == hash
=> false
>> secure_hash("secret") == hash
=> true
Таким образом, у нашего злоумышленника есть совпадение - плохие новости для любых пользователей.с паролем "секрет".Этот метод известен как радужная атака.
Чтобы предотвратить потенциальную радужную атаку, мы можем использовать соль, которая является уникальной уникальной строкой для каждого пользователя. Один из распространенных способов (почти) обеспечить уникальность состоит в том, чтобыхешируйте текущее время (в UTC не зависящее от часового пояса) вместе с паролем, чтобы два пользователя имели одинаковую соль, только если они созданы в одно и то же время и имеют одинаковый пароль.Давайте посмотрим, как это работает, используя функцию secure_hash, определенную в приведенной выше консоли:
>> Time.now.utc
=> Fri Jan 29 18:11:27 UTC 2010
>> password = "secret"
=> "secret"
>> salt = secure_hash("#{Time.now.utc}--#{password}")
=> "d1a3eb8c9aab32ec19cfda810d2ab351873b5dca4e16e7f57b3c1932113314c8"
>> encrypted_password = secure_hash("#{salt}--#{password}")
=> "69a98a49b7fd103058639be84fb88c19c998c8ad3639cfc5deb458018561c847"
В последней строке мы хэшировали соль с паролем, получая зашифрованный пароль, который практически невозможенвзломать .(Для ясности аргументы хэш-функций часто разделяются с -.)