я ожидал slappasswd
для создания фиксированного хеша, но похоже, что вывод рандомизирован, поскольку я никогда не получаю тот же вывод для одного и того же входного пароля:
$ slappasswd -s secret
{SSHA}mCXsPZkfgQYZr2mKHpy5Iav+2S2XlVU3
$ slappasswd -s secret
{SSHA}62oXsalJBuopYfHhi6hGp6AESuWNIVnd
$ slappasswd -s secret
{SSHA}0Ulc8+ugMi3NbTtWnclOFW1LKCqRdsT8
Во время аутентификации, как шлепок знает, как рандомизировать хэш для предоставленного пароля таким же образом, чтобы он мог соответствовать паролю, определенному в первую очередь?
Здесь вы рискуете, но я предполагаю, что slappasswd использует соленый хеш вместо простого. Это означает, что он добавляет случайный префикс к вашему паролю и сохраняет этот случайный префикс как часть строки, которую вы видите в выводе slappasswd. Когда вы вводите пароль, он добавляет к нему префикс, хеширует результат и сравнивает его со строкой в выводе slappasswd. Если он совпадает, значит вы в системе. Если нет, значит, вы ошиблись паролем :)
SSHA - это соленый SHA-1. По умолчанию последние 4 байта являются солью. Результатом slappasswd будет
'{<Hash Method>}<base64 converted hash and salt>'
Итак, чтобы проверить, равен ли простой текстовый пароль солёному SHA, вам необходимо:
Строка в кодировке base64 содержит хэш в двоичной форме и не может быть распечатана, поэтому мы преобразуем ее в шестнадцатеричный формат с помощью od. Первые 3 шага выполняются следующим кодом:
#!/bin/bash
output=$(slappasswd -h {SSHA} -s password)
hashsalt=$( echo -n $output | sed 's/{SSHA}//' | base64 -d)
salt=${hashsalt:(-1),(-4)}
echo $output
echo $(echo -n $hashsalt | od -A n -t x1)
echo "Salt: $salt"
Результатом может быть:
{SSHA}fDu0PgKDn1Di9W1HMINpPXRqQ9jTYjuH
7c 3b b4 3e 02 83 9f 50 e2 f5 6d 47 30 83 69 3d 74 6a 43 d8 d3 62 3b 87
<------------------------- Hash --------------------------> <-- Salt-->
Salt: ▒b;▒
Итак, теперь мы должны объединить соль с паролем в виде простого текста и хешировать его, на этот раз без соления! Проблема, с которой я столкнулся, заключалась в понимании того, что соль действительно может быть любым символом, включая непечатаемые символы. Чтобы объединить эти непечатаемые символы, мы будем использовать printf и их шестнадцатеричные представления:
slappasswd -h {SHA} -s $(printf 'password\xd3\x62\x3b\x87') | sed 's/{SHA}//' | base64 -d | od -A n -t x1
Результат:
7c 3b b4 3e 02 83 9f 50 e2 f5 6d 47 30 83 69 3d 74 6a 43 d8
Что равно хешу выше. Теперь мы проверили, что «пароль» соответствует солёному SHA.
Спасибо и дальнейшее чтение: http://cpansearch.perl.org/src/GSHANK/Crypt-SaltedHash-0.09/lib/Crypt/SaltedHash.pm