Библиотека шифрования
Важно
НЕ используйте эту или любую другую библиотеку шифрования для хранения паролей пользователей! Пароли необходимо хэшировать, используя расширение «Хэширование паролей» PHP (ссылка).
Библиотека шифрования обеспечивает двустороннее шифрование данных. Для обеспечения криптографической безопасности она использует расширения PHP, которые, к сожалению, не всегда доступны на всех системах. Для использования этой библиотеки необходимо выполнить одно из следующих требований:
Если ни одно из вышеперечисленных требований не выполнено, мы не можем предложить вам достаточной реализации, отвечающей высоким стандартам надлежащей криптографии.
- Использование библиотеки шифрования
- Справочник по классу
Использование библиотеки шифрования
Инициализация класса
Как и большинство других классов в CodeIgniter, библиотека шифрования инициализируется в вашем контроллере с помощью метода $this->load->library():
$this->load->library('encryption');
После загрузки объект библиотеки шифрования будет доступен с помощью:
$this->encryption
Поведение по умолчанию
По умолчанию библиотека шифрования будет использовать алгоритм шифрования AES-128 в режиме CBC, используя настроенный ключ шифрования и аутентификацию SHA512 HMAC.
Примечание
AES-128 выбран как надежный алгоритм с широкой доступностью в различных криптографических программных средствах и API языков программирования.
Однако ключ шифрования не используется напрямую.
Если вы знакомы с криптографией, вам должно быть известно, что HMAC также требует секретного ключа, а использование одного и того же ключа для шифрования и аутентификации — плохая практика.
Поэтому из вашего настроенного ключа шифрования выводятся два отдельных ключа: один для шифрования и один для аутентификации. Это делается с помощью техники, называемой функцией вывода ключа на основе HMAC (HKDF).
Установка ключа шифрования
Ключ шифрования — это информация, которая управляет криптографическим процессом и позволяет шифровать и дешифровать строку простого текста. Это секретный «ингредиент», позволяющий вам быть единственным, кто может дешифровать данные, которые вы решили скрыть от глаз общественности. После использования одного ключа для шифрования данных, этот же ключ обеспечивает **единственный** способ дешифровать его, поэтому его необходимо тщательно выбирать, и вы не должны его терять, так как в этом случае вы также потеряете доступ к данным.
Следует отметить, что для обеспечения максимальной безопасности такой ключ должен быть не только максимально сильным, но и часто меняться. Однако такое поведение редко бывает практичным или возможным для реализации, и поэтому CodeIgniter предоставляет вам возможность настроить единственный ключ, который будет использоваться (почти) каждый раз.
Само собой разумеется, что вы должны тщательно охранять свой ключ. Если кто-то получит доступ к вашему ключу, данные будут легко дешифрованы. Если ваш сервер не полностью находится под вашим контролем, невозможно гарантировать безопасность ключа, поэтому вы можете тщательно обдумать использование ключа для чего-либо, требующего высокой безопасности, например, для хранения номеров кредитных карт.
Ключ шифрования **должен** быть такой длины, как это позволяет используемый алгоритм шифрования. Для AES-128 это 128 бит или 16 байт (символов).
Ниже приведена таблица, в которой показаны поддерживаемые длины ключей различных алгоритмов.
Ключ должен быть максимально случайным и **не должен** быть обычной строкой текста, результатом функции хеширования и т. д. Для создания правильного ключа необходимо использовать метод библиотеки шифрования create_key().
// $key will be assigned a 16-byte (128-bit) random key $key = $this->encryption->create_key(16);
Ключ можно хранить в файле application/config/config.php или разработать собственную систему хранения и динамически передавать ключ при шифровании/дешифровании.
Чтобы сохранить ключ в application/config/config.php, откройте файл и установите:
$config['encryption_key'] = 'YOUR KEY';
Вы заметите, что метод create_key() выводит двоичные данные, с которыми трудно работать (например, копирование и вставка может повредить их), поэтому можно использовать bin2hex(), hex2bin() или кодирование Base64 для работы с ключом более удобным способом. Например:
// Get a hex-encoded representation of the key: $key = bin2hex($this->encryption->create_key(16)); // Put the same value in your config with hex2bin(), // so that it is still passed as binary to the library: $config['encryption_key'] = hex2bin(<your hex-encoded key>);
Поддерживаемые алгоритмы шифрования и режимы
Примечание
Термины «алгоритм шифрования» и «шифр» взаимозаменяемы.
Портабельные алгоритмы шифрования
Так как MCrypt и OpenSSL (также называемые драйверами в данном документе) поддерживают различные наборы алгоритмов шифрования и часто реализуют их по-разному, наша библиотека шифрования разработана для использования их в портативном режиме, другими словами — она позволяет вам использовать их взаимозаменяемо, по крайней мере, для алгоритмов шифрования, поддерживаемых обоими драйверами.
Она также реализована так, чтобы соответствовать стандартным реализациям в других языках программирования и библиотеках.
Вот список так называемых «портативных» алгоритмов шифрования, где «название в CodeIgniter» — это строковое значение, которое необходимо передать библиотеке шифрования для использования этого алгоритма:
| Название алгоритма | Название в CodeIgniter | Длина ключа (бит/байт) | Поддерживаемые режимы |
|---|---|---|---|
| AES-128 / Rijndael-128 | aes-128 | 128 / 16 | CBC, CTR, CFB, CFB8, OFB, ECB |
| AES-192 | aes-192 | 192 / 24 | CBC, CTR, CFB, CFB8, OFB, ECB |
| AES-256 | aes-256 | 256 / 32 | CBC, CTR, CFB, CFB8, OFB, ECB |
| DES | des | 56 / 7 | CBC, CFB, CFB8, OFB, ECB |
| TripleDES | tripledes | 56 / 7, 112 / 14, 168 / 21 | CBC, CFB, CFB8, OFB |
| Blowfish | blowfish | 128-448 / 16-56 | CBC, CFB, OFB, ECB |
| CAST5 / CAST-128 | cast5 | 88-128 / 11-16 | CBC, CFB, OFB, ECB |
| RC4 / ARCFour | rc4 | 40-2048 / 5-256 | Потоковый режим |
Важно
Из-за особенностей работы MCrypt, если вы не предоставите ключ соответствующей длины, вы можете использовать другой алгоритм, чем тот, который был настроен, поэтому будьте очень осторожны!
Примечание
Если не ясно из таблицы выше, Blowfish, CAST5 и RC4 поддерживают ключи переменной длины. То есть любое число из указанных диапазонов является допустимым, хотя в битах это происходит только с шагом в 8 бит.
Примечание
Хотя CAST5 поддерживает длины ключей меньше 128 бит (16 байтов), на самом деле они будут дополнены нулями до максимальной длины, как указано в RFC 2144.
Примечание
Blowfish поддерживает длины ключей до 32 бит (4 байта), но наши тесты показали, что только длины 128 бит (16 байт) и более надлежащим образом поддерживаются как MCrypt, так и OpenSSL. Также является плохой практикой использование ключей такой малой длины.
Алгоритмы шифрования, специфичные для драйвера
Как отмечалось выше, MCrypt и OpenSSL поддерживают различные наборы алгоритмов шифрования. Из соображений портативности и потому что мы не провели их надлежащей проверки, мы не рекомендуем использовать алгоритмы, специфичные для драйвера, но, независимо от этого, вот список большинства из них:
| Имя шифра | Драйвер | Длины ключей (биты/байты) | Поддерживаемые режимы |
|---|---|---|---|
| AES-128 | OpenSSL | 128 / 16 | CBC, CTR, CFB, CFB8, OFB, ECB, XTS |
| AES-192 | OpenSSL | 192 / 24 | CBC, CTR, CFB, CFB8, OFB, ECB, XTS |
| AES-256 | OpenSSL | 256 / 32 | CBC, CTR, CFB, CFB8, OFB, ECB, XTS |
| Rijndael-128 | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
| Rijndael-192 | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
| Rijndael-256 | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
| GOST | MCrypt | 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
| Twofish | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
| CAST-128 | MCrypt | 40-128 / 5-16 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
| CAST-256 | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
| Loki97 | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
| SaferPlus | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
| Serpent | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
| XTEA | MCrypt | 128 / 16 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
| RC2 | MCrypt | 8-1024 / 1-128 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
| RC2 | OpenSSL | 8-1024 / 1-128 | CBC, CFB, OFB, ECB |
| Camellia-128 | OpenSSL | 128 / 16 | CBC, CFB, CFB8, OFB, ECB |
| Camellia-192 | OpenSSL | 192 / 24 | CBC, CFB, CFB8, OFB, ECB |
| Camellia-256 | OpenSSL | 256 / 32 | CBC, CFB, CFB8, OFB, ECB |
| Seed | OpenSSL | 128 / 16 | CBC, CFB, OFB, ECB |
Примечание
Если вы хотите использовать один из этих шифров, вам нужно передать его имя в нижнем регистре в библиотеку шифрования.
Примечание
Вы, вероятно, заметили, что все шифры AES (и Rijndael-128) также перечислены в списке портативных шифров. Это связано с тем, что драйверы поддерживают различные режимы для этих шифров. Также важно отметить, что AES-128 и Rijndael-128 фактически являются одним и тем же шифром, но **только** при использовании ключа длиной 128 бит.
Примечание
CAST-128 / CAST-5 также указан как в списке портативных, так и в списке шифров, специфичных для драйвера. Это связано с тем, что, похоже, реализация OpenSSL не работает должным образом с размерами ключей 80 бит и ниже.
Примечание
RC2 указан как поддерживаемый как MCrypt, так и OpenSSL. Однако оба драйвера реализуют его по-разному, и они не портативны. Возможно, стоит отметить, что мы нашли только один неочевидный источник, подтверждающий, что MCrypt не реализует его должным образом.
Режимы шифрования
Разные режимы шифрования обладают разными характеристиками и служат для разных целей. Некоторые из них сильнее других, некоторые быстрее, а некоторые предлагают дополнительные возможности. Мы не будем углубляться в это здесь, мы оставим это экспертам по криптографии. Таблица ниже предназначена для предоставления краткой справочной информации нашим более опытным пользователям. Если вы новичок, просто придерживайтесь режима CBC — он широко признан сильным и безопасным для общих целей.
| Название режима | Имя в CodeIgniter | Поддержка драйвера | Дополнительная информация |
|---|---|---|---|
| CBC | cbc | MCrypt, OpenSSL | Безопасный выбор по умолчанию |
| CTR | ctr | MCrypt, OpenSSL | Считается теоретически лучшим, чем CBC, но не так широко доступен |
| CFB | cfb | MCrypt, OpenSSL | Нет данных |
| CFB8 | cfb8 | MCrypt, OpenSSL | То же самое, что CFB, но работает в 8-битном режиме (не рекомендуется). |
| OFB | ofb | MCrypt, OpenSSL | Нет данных |
| OFB8 | ofb8 | MCrypt | То же самое, что OFB, но работает в 8-битном режиме (не рекомендуется). |
| ECB | ecb | MCrypt, OpenSSL | Игнорирует IV (не рекомендуется). |
| XTS | xts | OpenSSL | Обычно используется для шифрования данных с произвольным доступом, таких как оперативная память или хранилище жесткого диска. |
| Поток | stream | MCrypt, OpenSSL | На самом деле это не режим, это просто говорит, что используется потоковый шифр. Требуется из-за общего процесса инициализации шифра+режима. |
Длина сообщения
Вероятно, важно знать, что зашифрованная строка обычно длиннее исходной, открытого текста (в зависимости от шифра). Это зависит от самого алгоритма шифра, IV, предшествующего шифрованному тексту, и сообщения аутентификации HMAC, которое также предшествует. Кроме того, зашифрованное сообщение также кодируется в Base64, чтобы обеспечить безопасность хранения и передачи независимо от используемой кодировки.
Учитывайте эту информацию при выборе механизма хранения данных. Например, файлы cookie могут хранить только 4 КБ информации.
Настройка библиотеки
Для удобства использования, производительности, а также по историческим причинам, связанным с нашим старым классом Encrypt Class, библиотека шифрования разработана для многократного использования одного и того же драйвера, шифра, режима и ключа.
Как отмечено в разделе «Поведение по умолчанию» выше, это означает использование автоматически обнаруженного драйвера (OpenSSL имеет более высокий приоритет), шифра AES-128 в режиме CBC и вашего значения $config['encryption_key']. Однако, если вы хотите изменить это, вам необходимо использовать метод initialize(). Он принимает ассоциативный массив параметров, все из которых являются необязательными:
| Параметр | Возможные значения |
|---|---|
| driver | ‘mcrypt’, ‘openssl’ |
| cipher | Имя шифра (см. Поддерживаемые шифры и режимы шифрования) |
| mode | Режим шифрования (см. Режимы шифрования) |
| key | Ключ шифрования |
Например, если вы хотите изменить алгоритм и режим шифрования на AES-256 в режиме CTR, вот что вам нужно сделать:
$this->encryption->initialize(
array(
'cipher' => 'aes-256',
'mode' => 'ctr',
'key' => '<a 32-character random string>'
)
);
Обратите внимание, что мы упомянули только о желании изменения шифра и режима, но также включили пример ключа. Как отмечалось ранее, важно выбрать ключ соответствующего размера для используемого алгоритма.
Также есть возможность изменить драйвер, если по какой-то причине у вас есть оба, но вы хотите использовать MCrypt вместо OpenSSL:
// Switch to the MCrypt driver
$this->encryption->initialize(array('driver' => 'mcrypt'));
// Switch back to the OpenSSL driver
$this->encryption->initialize(array('driver' => 'openssl'));
Шифрование и расшифровка данных
Шифрование и расшифровка данных с использованием уже настроенных параметров библиотеки проста. Достаточно просто передать строку в методы encrypt() и/или decrypt().
$plain_text = 'This is a plain-text message!'; $ciphertext = $this->encryption->encrypt($plain_text); // Outputs: This is a plain-text message! echo $this->encryption->decrypt($ciphertext);
И это все! Библиотека шифрования сделает все необходимое для того, чтобы весь процесс был криптографически безопасным «из коробки». Вам не нужно беспокоиться об этом.
Важно
Оба метода вернут FALSE в случае ошибки. В то время как для encrypt() это может означать только неправильную конфигурацию, вы всегда должны проверять возвращаемое значение decrypt() в коде производства.
Как это работает
Если вам нужно знать, как работает процесс, вот что происходит под капотом:
-
$this->encryption->encrypt($plain_text)- Извлечь ключ шифрования и ключ HMAC из вашего настроенного encryption_key с помощью HKDF, используя алгоритм хеширования SHA-512.
- Сгенерировать случайный вектор инициализации (IV).
- Зашифровать данные с помощью AES-128 в режиме CBC (или другого предварительно настроенного шифра и режима), используя полученный ключ шифрования и IV.
- Добавить указанный IV к результирующему шифрованному тексту.
- Кодировать результирующую строку в Base64, чтобы ее можно было безопасно хранить или передавать, не беспокоясь о кодировках.
- Создать сообщение аутентификации HMAC SHA-512, используя полученный ключ HMAC, чтобы обеспечить целостность данных, и добавить его к строке Base64.
-
$this->encryption->decrypt($ciphertext)- Извлечь ключ шифрования и ключ HMAC из вашего настроенного encryption_key с помощью HKDF, используя алгоритм хеширования SHA-512. Так как ваш настроенный encryption_key один и тот же, это даст тот же результат, что и в методе
encrypt()выше — в противном случае вы не сможете его расшифровать. - Проверить, достаточно ли длинной строка, извлечь HMAC и проверить его корректность (это делается таким образом, чтобы предотвратить атаки на время против него). Вернуть FALSE, если одно из проверок не пройдёт.
- Декодировать строку из Base64.
- Извлечь IV из шифрованного текста и расшифровать указанный зашифрованный текст, используя этот IV и извлечённый ключ шифрования.
- Извлечь ключ шифрования и ключ HMAC из вашего настроенного encryption_key с помощью HKDF, используя алгоритм хеширования SHA-512. Так как ваш настроенный encryption_key один и тот же, это даст тот же результат, что и в методе
Использование пользовательских параметров
Предположим, вам нужно взаимодействовать с другой системой, которая находится вне вашего контроля и использует другой метод шифрования данных. Метод, который, безусловно, не будет соответствовать вышеописанной последовательности и, вероятно, не будет использовать все шаги.
Библиотека шифрования позволяет изменить работу процессов шифрования и расшифровки, чтобы вы могли легко адаптировать пользовательское решение для таких ситуаций.
Примечание
Можно использовать библиотеку таким образом, не устанавливая encryption_key в вашем конфигурационном файле.
Все, что вам нужно сделать, это передать ассоциативный массив с несколькими параметрами в метод encrypt() или decrypt(). Вот пример:
// Assume that we have $ciphertext, $key and $hmac_key
// from on outside source
$message = $this->encryption->decrypt(
$ciphertext,
array(
'cipher' => 'blowfish',
'mode' => 'cbc',
'key' => $key,
'hmac_digest' => 'sha256',
'hmac_key' => $hmac_key
)
);
В приведенном выше примере мы расшифровываем сообщение, которое было зашифровано с помощью шифра Blowfish в режиме CBC и аутентифицировано с помощью HMAC SHA-256.
Важно
Обратите внимание, что в этом примере используются как ‘key’, так и ‘hmac_key’. При использовании пользовательских параметров ключи шифрования и HMAC не выводятся, как это происходит по умолчанию в библиотеке.
Ниже приведен список доступных параметров.
END_OF_DOCUMENT_MARKERОднако, если вам это действительно нужно и вы знаете, что делаете, мы рекомендуем не изменять процесс шифрования, так как это может повлиять на безопасность, поэтому делайте это с осторожностью.
| Параметр | Значение по умолчанию | Обязательный/Необязательный | Описание |
|---|---|---|---|
| cipher | N/A | Да | Алгоритм шифрования (см. Поддерживаемые алгоритмы шифрования и режимы). |
| mode | N/A | Да | Режим шифрования (см. Режимы шифрования). |
| key | N/A | Да | Ключ шифрования. |
| hmac | TRUE | Нет | Использовать HMAC. Булево значение. Если установлено в FALSE, то hmac_digest и hmac_key будут проигнорированы. |
| hmac_digest | sha512 | Нет | Алгоритм HMAC-хеширования (см. Поддерживаемые алгоритмы аутентификации HMAC). |
| hmac_key | N/A | Да, если hmac не FALSE | Ключ HMAC. |
| raw_data | FALSE | Нет | Текст шифрования должен быть в сыром виде. Булево значение. Если установлено в TRUE, то кодирование и декодирование Base64 не будут выполняться, и HMAC не будет строкой в шестнадцатеричном формате. |
Важно
encrypt() и decrypt() вернут FALSE, если обязательный параметр не указан или предоставленное значение некорректно. Это включает в себя hmac_key, если hmac не установлено в FALSE.
Поддерживаемые алгоритмы аутентификации HMAC
Для аутентификации сообщений HMAC библиотека шифрования поддерживает использование алгоритмов семейства SHA-2:
| Алгоритм | Длина в сыром виде (байты) | Длина в шестнадцатеричном формате (байты) |
|---|---|---|
| sha512 | 64 | 128 |
| sha384 | 48 | 96 |
| sha256 | 32 | 64 |
| sha224 | 28 | 56 |
Причина, по которой не включены другие популярные алгоритмы, такие как MD5 или SHA1, заключается в том, что они больше не считаются достаточно безопасными, и поэтому мы не хотим поощрять их использование. Если вам абсолютно необходимо их использовать, это легко сделать с помощью встроенной функции PHP hash_hmac().
Более сильные алгоритмы, конечно, будут добавлены в будущем, по мере их появления и широкого распространения.
Справочник по классам
-
class CI_Encryption -
-
initialize($params) -
Параметры: - $params (array) – Параметры конфигурации
Возвращает: Экземпляр CI_Encryption (метод цепочки)
Тип возвращаемого значения: CI_Encryption
Инициализирует (настраивает) библиотеку для использования другого драйвера, алгоритма шифрования, режима или ключа.
Пример:
$this->encryption->initialize( array('mode' => 'ctr') );Обратитесь к разделу Настройка библиотеки за подробной информацией.
-
encrypt($data[, $params = NULL]) -
Параметры: - $data (string) – Данные для шифрования
- $params (array) – Необязательные параметры
Возвращает: Зашифрованные данные или FALSE при ошибке
Тип возвращаемого значения: string
Шифрует входные данные и возвращает зашифрованный текст.
Пример:
$ciphertext = $this->encryption->encrypt('My secret message');Обратитесь к разделу Использование пользовательских параметров за информацией об необязательных параметрах.
-
decrypt($data[, $params = NULL]) -
Параметры: - $data (string) – Данные для дешифрования
- $params (array) – Необязательные параметры
Возвращает: Расшифрованные данные или FALSE при ошибке
Тип возвращаемого значения: string
Дешифрует входные данные и возвращает их в виде простого текста.
Пример:
echo $this->encryption->decrypt($ciphertext);
Обратитесь к разделу Использование пользовательских параметров за информацией об необязательных параметрах.
-
create_key($length) -
Параметры: - $length (int) – Длина вывода
Возвращает: Псевдослучайный криптографический ключ заданной длины или FALSE при ошибке
Тип возвращаемого значения: string
Создает криптографический ключ, извлекая случайные данные из источников операционной системы (например, /dev/urandom).
-
hkdf($key[, $digest = 'sha512'[, $salt = NULL[, $length = NULL[, $info = '']]]]) -
Параметры: - $key (string) – Входной материал ключа
- $digest (string) – Алгоритм хеширования семейства SHA-2
- $salt (string) – Необязательная соль
- $length (int) – Необязательная длина вывода
- $info (string) – Необязательная информация о контексте/приложении
Возвращает: Псевдослучайный ключ или FALSE при ошибке
Тип возвращаемого значения: string
Выводит ключ из другого, предположительно более слабого ключа.
Этот метод используется внутри для вывода ключа шифрования и HMAC из вашего настроенного encryption_key.
Он доступен публично из-за его общего назначения. Он описан в RFC 5869.
Однако, в отличие от описания в RFC 5869, эта реализация не поддерживает SHA1.
Пример:
$hmac_key = $this->encryption->hkdf( $key, 'sha512', NULL, NULL, 'authentication' ); // $hmac_key is a pseudo-random key with a length of 64 bytes
-
© 2014–2020 British Columbia Institute of Technology
Licensed under the MIT License.
https://codeigniter.com/userguide3/libraries/encryption.html