Шифрование данных

Класс 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);
        

Ключ шифрования должен храниться отдельно от зашифрованных данных — например, в переменных окружения или защищенном хранилище. Не храните ключ в открытом виде рядом с данными.

В процессе шифрования метод выполняет несколько шагов.

  1. Создает случайный вектор инициализации.

  2. Вычисляет хеш-код от конкатенации вектора инициализации и ключа.

  3. Вычисляет хеш исходных данных и добавляет его перед шифрованием, если включен контроль целостности.

  4. Шифрует данные алгоритмом, который установил пользователь.

  5. Возвращает вектор инициализации и зашифрованные данные.

Вектор инициализации всегда разный, поэтому одинаковые данные при одном и том же ключе шифруются по-разному.

Расшифровать данные

Метод decrypt($data, $key) расшифровывает данные и возвращает исходную строку.

  • $data — бинарные данные от метода encrypt().

  • $key — ключ шифрования. Указывайте тот же, что при шифровании.

$decrypted = $cipher->decrypt($encrypted, $cryptoKey);
        
        // Результат должен совпадать с исходными данными
        echo $decrypted; // Секретные данные
        

Метод выполняет шаги, обратные шифрованию.

  1. Извлекает вектор инициализации из данных.

  2. Вычисляет хеш-код от конкатенации вектора инициализации и ключа.

  3. Расшифровывает данные.

  4. Проверяет хеш данных, если контроль целостности включен.

  5. Возвращает исходную строку.

Если хеш не совпадает, метод возвращает исключение 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();
        }