crypt

crypt

Vadim Pushtaev

Если вам надо хешировать пароли, там вам подойдет функция crypt из glibc, она умеет все, что нужно. Во всех языках для нее есть тупые обертки, захешированый в одном проекте пароль может быть легко проверен в другом.

crypt принимает два аргумента: пароль и соль, а возвращает дайджест:

>>> from crypt import crypt
>>> crypt('password', 'ABCDEFG')
'ABRCL9ijBr2LY'

В соли можно использовать только символы [./0-9A-Za-z], но вообще говоря это зависит от реализации в вашей ОС, поэтому питон и перл даже ошибок не кидают, если использовать другие символы. Генерить соль можно без использования криптографически стойкого раднома, это не так принципиально, важно только, чтобы она была уникальной (или почти уникальной) для всех пользователей. (Может, кстати, это и не так, но я не смог придумать или найти подтверждение иному.)

От соли в действительности используются только два первых символа, и они же приписываются в начало дайджеста (AB в примере выше). Это позволяет использовать дайджест как соль при проверке пароля:

>>> crypt('password', 'ABRCL9ijBr2LY')
'ABRCL9ijBr2LY'

Т. е. стандартная формула выглядит так: crypt(password, digest) == digest для верного пароля.

Зачем соль

Вкратце для тех, кто забыл: если все пароли хешировать одинаково, то когда злоумышленник утащит вашу базу, он один раз построит для вашего алгоритма хеширования огромную таблицу с ответами и хакнет все пароли. Если же использовать разные алгоритмы для всех паролей, то такая огромная таблица сгодится для взлома только одного пароля, что делает атаку на базу значительно более трудоемкой.

Соль — это как раз переменный фрагмент вашего алгоритма хеширования. Она не является секретом и обычно похищается вместе с базой паролей.

2к18

По дефолту у crypt под капотом DES, но в современных версиях glibc этим можно управлять. Вместо того, чтобы в качестве соли передавать два символа, можно передать дополнительные параметры в специальном формате: $id$salt. А дайджест тогда будет иметь вид $id$salt$encrypted, что позволяет сохранить существующее свойство: дайджест может быть использован как соль для проверки пароля.

Как можно было догадаться, id — это тип шифрования. Табличка из доки:

ID  | Method
─────────────────────────────────────────────────────────
1   | MD5
2a  | Blowfish (not in mainline glibc; added in some
    | Linux distributions)
5   | SHA-256 (since glibc 2.7)
6   | SHA-512 (since glibc 2.7)

salt — это соль, символы те же, что и в варианте с DES, но длина уже до 16 символов.

Это формат там еще дополнительные плюшки поддерживает, в доке можно посмотреть подробней.

Итого

В итоге с помощью crypt можно спокойно сгенерить дайджест для пользователя, передать его куда угодно и спокойно его там аутентифицировать:

$ perl -E 'say crypt("MySecurePassword", q($5$SALTSALTSALTSALT))'
$5$SALTSALTSALTSALT$nt4wWv6TEimkgvvcc65WW3ea707CrRPVwEIm0SWiS3B
$ python
>>> from crypt import crypt
>>> digest = '$5$SALTSALTSALTSALT$nt4wWv6TEimkgvvcc65WW3ea707CrRPVwEIm0SWiS3B'
>>> crypt('MySecurePassword', digest) == digest
True
>>> crypt('WrongPassword', digest) == digest
False



Report Page