Crypt: примеры (PHP)

Руководство по функции crypt с примерами на русском
Раздел: Хеширование и шифрование
crypt(string $string, string $salt): string

Функция crypt в PHP

Назначение и использование

Функция crypt выполняет одностороннее хеширование строки. Основное применение — безопасное хранение паролей и проверка аутентификации. Она возвращает хешированную строку, сформированную с использованием стандартных алгоритмов Unix.

Аргументы функции

Функция принимает два аргумента:

  1. string — исходная строка для хеширования. Обычно это пароль.
  2. salt — соль, которая определяет алгоритм хеширования и его параметры. Этот аргумент не обязателен. Если соль не указана или опущена, PHP генерирует случайную соль для каждого вызова, что делает невозможным прямое сравнение хешей.

Длина возвращаемой строки зависит от выбранного алгоритма.

Примеры использования функции crypt

Хеширование с автоматической солью

При каждом вызове без указания соли генерируется новая случайная соль, и результат будет разным.

echo crypt('myPassword');
$1$Tk1b01rK$z6h7L5f1L5b5J1b5N5b5.
Использование разных алгоритмов через соль

Строка соли может указывать алгоритм. Для MD5 используется префикс $1$.

echo crypt('password', '$1$somesalt$');
$1$somesalt$qP7h2V8sQ7h2V8sQ7h2V8.

Использование Blowfish с указанием стоимости.

echo crypt('password', '$2a$07$usesomesillystringforsalt$');
$2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi

Проверка пароля с известным хешем.

$hashed_password = '$1$somesalt$qP7h2V8sQ7h2V8sQ7h2V8.';
if (hash_equals($hashed_password, crypt('password', $hashed_password))) {
    echo 'Пароль верный.';
} else {
    echo 'Пароль неверный.';
}
Пароль верный.

Альтернативные функции в PHP

password_hash и password_verify

Функции password_hash и password_verify предоставляют более простой и безопасный интерфейс для хеширования паролей. Они автоматически выбирают подходящий алгоритм (по умолчанию BCRYPT) и управляют солью.

$hash = password_hash('пароль', PASSWORD_DEFAULT);
echo $hash;
$2y$10$X5z4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C

Функция hash поддерживает широкий набор алгоритмов (SHA-256, SHA-512 и др.), но не предназначена специально для паролей, так как не включает встроенную защиту от перебора.

echo hash('sha256', 'password');
5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

Аналоги функции crypt в других языках

Python (модуль crypt)

Модуль crypt в Python предоставляет аналогичный интерфейс для хеширования паролей.

import crypt
hashed = crypt.crypt('password', crypt.mksalt(crypt.METHOD_SHA512))
print(hashed)
$6$rounds=656000$saltstring$... (хеш)
JavaScript (библиотеки)

В JavaScript нет встроенной функции crypt, но существуют библиотеки, например, bcrypt.js.

const bcrypt = require('bcryptjs');
const salt = bcrypt.genSaltSync(10);
const hash = bcrypt.hashSync('password', salt);
console.log(hash);
$2a$10$N9qo8uLOickgx2ZMRZoMye...
MySQL (функция PASSWORD)

MySQL имеет функцию PASSWORD, но она предназначена для внутреннего использования и не рекомендуется для приложений.

SELECT PASSWORD('mypass');
*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4

Распространенные ошибки

Использование функции без указания соли для проверки

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

$stored_hash = crypt('password', '$1$somesalt$');
$input = 'password';
$new_hash = crypt($input); // соль генерируется случайно
var_dump($stored_hash === $new_hash);
bool(false)
Неправильная обрезка хеша

Хеши crypt имеют фиксированную длину в зависимости от алгоритма. Их усечение приводит к невозможности проверки.

$hash = crypt('password', '$1$salt$');
$trimmed_hash = substr($hash, 0, 10);
$check = crypt('password', $trimmed_hash);
var_dump($hash === $check);
bool(false)

Изменения в последних версиях PHP

PHP 8.0

В PHP 8.0 функция crypt теперь принимает необязательный параметр salt как nullable-аргумент. Это изменение улучшает согласованность с современными стандартами PHP. При передаче null используется поведение по умолчанию с генерацией случайной соли.

echo crypt('password', null);
$1$5C7b5C7b$5C7b5C7b5C7b5C7b5C7b5.

Расширенные примеры применения crypt

Использование с различными алгоритмами

Пример с алгоритмом SHA-512. Соль задается в формате $6$rounds=5000$saltstring$.

Пример php
$salt = '$6$rounds=5000$saltstring$';
echo crypt('password', $salt);
$6$rounds=5000$saltstring$uZsC... (хеш)
Создание соли для алгоритма CRYPT_BLOWFISH

Генерация соли с использованием случайных данных и указанием стоимости.

Пример php
$cost = 10;
$salt = '$2y$' . str_pad($cost, 2, '0', STR_PAD_LEFT) . '$' . substr(str_replace('+', '.', base64_encode(random_bytes(16))), 0, 22) . '$';
echo crypt('password', $salt);
$2y$10$abcdefghijklmnopqrstuu... (хеш)
Сравнение хешей с защитой от атак по времени

Для безопасного сравнения используется функция hash_equals, чтобы избежать атак по времени.

Пример php
$user_input = 'password';
$stored_hash = '$1$somesalt$qP7h2V8sQ7h2V8sQ7h2V8.';
$calculated_hash = crypt($user_input, $stored_hash);
if (hash_equals($stored_hash, $calculated_hash)) {
    echo 'Аутентификация успешна.';
}
Аутентификация успешна.
Хеширование с пользовательской солью на основе данных

Создание соли на основе имени пользователя, но с добавлением случайного компонента для безопасности.

Пример php
$username = 'user123';
$random = bin2hex(random_bytes(4));
$salt = '$1$' . md5($username . $random) . '$';
echo crypt('password', $salt);
$1$d8577ed78$... (хеш)

PHP crypt function comments

En
Crypt One-way string hashing