Шифрование данных
Класс Bitrix\Main\Security\Cipher реализует симметричное шифрование данных в Bitrix Framework. Подходит для защиты конфиденциальной информации: токенов, ключей или пользовательских данных, которые нужно хранить в зашифрованном виде.
Класс использует расширение PHP OpenSSL для выполнения криптографических операций. По умолчанию применяет два алгоритма:
-
aes-256-ctr— для шифрования данных, -
sha256— для контроля целостности данных.
Конструктор класса
Конструктор проверяет доступность OpenSSL и поддерживаемые алгоритмы. При ошибке он выбрасывает исключение SecurityException.
public function __construct($cipherAlgorithm = 'aes-256-ctr', $hashAlgorithm = 'sha256', $calculateHash = true)
-
$cipherAlgorithm— алгоритм шифрования. По умолчанию —'aes-256-ctr'. Получить список доступных алгоритмов можно функциейopenssl_get_cipher_methods(). -
$hashAlgorithm— алгоритм для контроля целостности. По умолчанию —'sha256'. Получить список доступных алгоритмов можно функциейopenssl_get_md_methods(). -
$calculateHash— включить контроль целостности. По умолчанию контроль включенtrue.
Контроль целостности проверяет, что данные не изменились после шифрования. Если отключить контроль $calculateHash = false, метод шифрования не сможет обнаружить ошибку при неверном ключе.
Зашифровать данные
Метод encrypt($data, $key) шифрует строку и возвращает бинарные данные.
-
$data— строка для шифрования. -
$key— ключ шифрования. Используйте надежный ключ — длинную случайную строку. Можно сгенерировать с помощью\Bitrix\Main\Security\Random::getString(32).
$cipher = new \Bitrix\Main\Security\Cipher();
$cryptoKey = \Bitrix\Main\Security\Random::getString(32);
// encrypt() возвращает бинарные данные
$encrypted = $cipher->encrypt('Секретные данные', $cryptoKey);
Ключ шифрования должен храниться отдельно от зашифрованных данных — например, в переменных окружения или защищенном хранилище. Не храните ключ в открытом виде рядом с данными.
В процессе шифрования метод выполняет несколько шагов.
-
Создает случайный вектор инициализации.
-
Вычисляет хеш-код от конкатенации вектора инициализации и ключа.
-
Вычисляет хеш исходных данных и добавляет его перед шифрованием, если включен контроль целостности.
-
Шифрует данные алгоритмом, который установил пользователь.
-
Возвращает вектор инициализации и зашифрованные данные.
Вектор инициализации всегда разный, поэтому одинаковые данные при одном и том же ключе шифруются по-разному.
Расшифровать данные
Метод decrypt($data, $key) расшифровывает данные и возвращает исходную строку.
-
$data— бинарные данные от методаencrypt(). -
$key— ключ шифрования. Указывайте тот же, что при шифровании.
$decrypted = $cipher->decrypt($encrypted, $cryptoKey);
// Результат должен совпадать с исходными данными
echo $decrypted; // Секретные данные
Метод выполняет шаги, обратные шифрованию.
-
Извлекает вектор инициализации из данных.
-
Вычисляет хеш-код от конкатенации вектора инициализации и ключа.
-
Расшифровывает данные.
-
Проверяет хеш данных, если контроль целостности включен.
-
Возвращает исходную строку.
Если хеш не совпадает, метод возвращает исключение SecurityException.
Как хранить зашифрованные данные
Так как метод encrypt() возвращает бинарные данные, перед сохранением в базу данных их нужно преобразовать в текстовый формат. Для этого используйте кодирование в base64.
// Шифруем и кодируем в base64
$encrypted = $cipher->encrypt($data, $cryptoKey);
$encoded = base64_encode($encrypted);
// Декодируем и расшифровываем
$decoded = base64_decode($encoded);
$decrypted = $cipher->decrypt($decoded, $cryptoKey);
Обработка ошибок
Класс Cipher выбрасывает исключение SecurityException:
-
если расширение OpenSSL не доступно,
-
передан неподдерживаемый алгоритм,
-
не удалось создать вектор инициализации,
-
произошла ошибка при шифровании или расшифровке,
-
не совпал хеш данных при включенном контроле целостности.
Обрабатывайте ошибки с помощью try/catch.
try
{
$cipher = new \Bitrix\Main\Security\Cipher();
$originalData = 'Конфиденциальная информация';
$cryptoKey = \Bitrix\Main\Security\Random::getString(32);
// Шифруем данные
$encryptedData = $cipher->encrypt($originalData, $cryptoKey);
// Расшифровываем данные
$decryptedData = $cipher->decrypt($encryptedData, $cryptoKey);
// Результат должен совпадать с исходными данными
echo $decryptedData; // Конфиденциальная информация
}
catch(\Bitrix\Main\Security\SecurityException $e)
{
// Обрабатываем ошибку
echo 'Ошибка шифрования: ' . $e->getMessage();
}