Библиотека Шифрования
Важно
НЕ ИСПОЛЬЗУЙТЕ эту или любую другую библиотеку шифрования для хранения паролей пользователей! Пароли должны быть кешированы и вы должны сделать это через собственное PHP расширение кеширования паролей.
Библиотека шифрования обеспечивает двухстороннее шифрование данных. Делая это криптографически защищенным способом, она использует PHP-расширения, которые к сожалению не всегда доступны во всех системах. Вы должны иметь одну из следующих зависимостей для того, чтобы использовать эту библиотеку:
Если ни одна из представленных выше зависимостей не встретилась, мы не можем предложить достаточно хорошую реализацию для удовлетворения высоких стандартов, необходимых для правильной криптографии.
Использование библиотеки шифрования
Инициализация класса
Как и большинство классов CodeIgniter, библиотека шифрования инициализируется в контроллере с помощью $this->load->library() метода:
$this->load->library('encryption');
После загрузки библиотеки шифрования, объект будет доступен через:
$this->encryption
Поведение по умолчанию
По умолчанию, Библиотека шифрования будет использовать AES-128 шифр в CBC режиме, с помощью настроенного encryption_key и SHA512 HMAC проверки подлинности (аутентификации).
Примечание
AES-128 выбрана, потому что она оказалась сильной из-за своей широкой доступности различного криптографического программного обеспечения и языков программирования’ APIs.
Однако encryption_key не используется "как есть".
Если вы немного знакомы с криптографией, то уже должны знать, что код HMAC также требует секретный ключ, и что использование одного и того же ключа для шифрования и аутентификации является плохой практикой.
Исходя из этого, два отдельных ключа созданы от уже настроенного encryption_key: один для шифрования и один для аутентификации. Это делается с помощью метода, называемого HMAC-функции формирования ключа (HKDF).
Установка encryption_key
Ключ шифрования - это фрагмент информации, который управляет криптографическими процессом и позволяет зашифровать строку с обычным текстом, и потом - расшифровать. Этот секретный “ингредиент”, на протяжении всего процесса позволяет быть единственным, кто способен расшифровать данные, которые вы решили скрыть от глаз общественности. Ключ, который используется для шифрования данных, обеспечивает единственные средства для их расшифровки, поэтому вы должны не только внимательно его выбирать, но и не должны потерять его, что приведет к потере доступа к данным.
Следует отметить, что для обеспечения максимальной безопасности, такой ключ должен быть не только максимально прочными, но и также часто меняться. Такое поведение, конечно редко практикуется или есть возможность его реализовать, и именно поэтому у CodeIgniter дает вам возможность настроить один ключ, который будет использоваться (почти) каждый раз.
Само собой разумеется, что вы должны хранять ключ тщательно. Стоит кому-либо получить доступ к вашему ключу и данные будет легко расшифровать. Если ваш сервер не полностью под вашим контролем, невозможно обезопасить ключ безопасности, так что будьте внимательны перед использованием его для всего, что требует высокого уровня безопасности, например хранение номеров кредитных карт.
Ваш ключ шифрованиядолжен быть длинным, на сколько позволяет это алгоритм шифрования. Для AES-128 это 128 бит или 16 байт (символов) длина. В таблице ниже вы найдете поддерживаемые длины ключей различных шифров.
Ключ должен быть как можно более произвольным и НЕ ДОЛЖЕН быть ни обычной текстовой строкой ни результатом функции кеширования. В целях создания надлежащего ключа, необходимо использовать метод create_key() библиотеки шифрования.
// $key будет назначен 16-байтовым (128-бит) случайным ключом
$key = $this->encryption->create_key(16);
Ключ может храниться в application/config/config.php или вы можете создать свой собственный механизм хранения и передачи ключа динамически при шифровании/расшифровке.
Чтобы сохранить ваш ключ в application/config/config.php откройте файл и установите:
$config['encryption_key'] = 'ВАШ КЛЮЧ';
Вы заметите, что create_key() метод выводит двоичные данные, с которыми трудно иметь дело (т.е. копирование/вставка может привести к его повреждению), поэтому вы можете использовать bin2hex(), hex2bin() или Base64 кодирование для работы с ключом в более дружественной манере. Например:
// Получить hex-закодированное представление ключа:
$key = bin2hex($this->encryption->create_key(16));
// Установить одинаковые значения с конфигурацией и hex2bin(),
// так, что до сих пор данные передаются в библиотеку как двоичные:
$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 | Stream |
Важно
Из-за того как работает 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 | N/A |
CFB8 | cfb8 | MCrypt, OpenSSL | Как и CFB, но работает в 8-битном режиме (не рекомендуется). |
OFB | ofb | MCrypt, OpenSSL | N/A |
OFB8 | ofb8 | MCrypt | Как и OFB, но работает в 8-битном режиме (не рекомендуется). |
ECB | ecb | MCrypt, OpenSSL | Игнорирует IV (не рекомендуется). |
XTS | xts | OpenSSL | Обычно используется для шифрования случайных данных, таких как доступ к оперативной памяти или жесткому диску. |
Stream | stream | MCrypt, OpenSSL | На самом деле не режим, просто говорит, что потоковый шифр используется. Требуется, поскольку инициализирует основной шифр+режим процесс. |
Длина сообщения
Важно знать, что зашифрованная строка, как правило, длинее, чем простая оригинальная текстовая строка (в зависимости от шифра).
Это влияет на сам алгоритм шифрования, IV пресоединяемый шифр-текст и the HMAC проверка подлинности сообщений, которые тоже присоединяются. Кроме того, зашифрованное сообщение тоже в base64 кодировке, так что оно безопасно для хранения и передачи, независимо от используемого набора символов.
Имейте эту информацию в виду при выборе механизма хранения данных. Куки, например, могут содержать только 4К информации.
Настройка библиотеки
Для удобства использования, производительности, а также историческим причинам привязан к нашему старому классу шифрования, библиотека шифрования позволяет использовать многократно одни и те же драйвера, шифрование шифра, режим и ключ.
Как отмечалось в раздел выше “Поведение по умолчанию” означает использование автоопределение драйвера (OpenSSL имеет более высокий приоритет), AES-128 шифра в CBC режиме и $config['encryption_key'] значения.
Если вы хотите изменить это, то должны использовать initialize() метод. Он принимает ассоциативный массив параметров, каждый из которых являются необязательными:
Вариант | Возможные значения |
---|---|
драйвер | ‘mcrypt’, ‘openssl’ |
шифр | Название шифра (см. Поддерживаемые шифры шифрования и режимы) |
режим | Режим шифрования (см. Режимы шифрования) |
ключ | Ключ шифрования |
Например, если вы решили изменить алгоритм шифрования и режим на AES-256 в CTR режиме, вот что вы должны сделать:
$this->encryption->initialize(
array(
'cipher' => 'aes-256',
'mode' => 'ctr',
'key' => '<a 32-character random string>'
)
);
Обратите внимание, мы только предположили, что вы хотите изменить шифр и режим, но мы также добавили ключ в примере. Как отмечалось ранее, важно выбрать ключ с правильным размером для используемого алгоритма.
Есть также возможность менять драйвера, если по какой-то причине они у вас оба, но хотите использовать MCrypt вместо OpenSSL:
// Переключится на MCrypt драйвер
$this->encryption->initialize(array('driver' => 'mcrypt'));
// Переключится обратно на OpenSSL драйвер
$this->encryption->initialize(array('driver' => 'openssl'));
Шифрование и расшифровка данных
Шифрование и расшифровка данных с уже настроенными параметрами библиотеки проста.Достаточно просто передать строку в encrypt() и/или decrypt() методы:
$plain_text = 'This is a plain-text message!';
$ciphertext = $this->encryption->encrypt($plain_text);
// Выводит: простые текстовые сообщения!
echo $this->encryption->decrypt($ciphertext);
И это всё! Библиотека шифрования сделает все необходимое на протяжении всего процесса, чтобы быть криптографически стойкой "из коробки". Вам не нужно беспокоиться об этом.
Важно
Оба метода возвращают FALSE в случае ошибки. В то время как для encrypt() это может означать только неправильные конфигурации, вы должны всегда проверять возвращаемое значение decrypt() в рабочем коде.
Как это работает
Если вы хотите знать как работает этот процесс, то здесь то, что происходит под капотом:
- $this->encryption->encrypt($plain_text)
- Получаем ключ шифрования и HMAC ключ полученный от ваших настроек encryption_key через HKDF используя SHA-512 алгоритм дайджеста.
- Генерируется случайный вектор инициализации (ВИ).
- Шифрование данных через AES-128 в CBC режиме (или другими предварительно настроенными шифром и режимом) с помощью вышеупомянутого производного ключа шифрования и вектор инициализации.
- Подставляем полученный вектор инициализации к получающемуся шифр-тексту.
- Кодируем полученную строку в base64, так что он может безопасно храниться или передаваться, не беспокоясь о наборах символов.
- Создаем SHA-512 HMAC проверку подлинности сообщения с помощью производной HMAC ключа для обеспечения целостности данных и сохраняем его в строку формата base64.
- $this->encryption->decrypt($ciphertext)
- Получаем ключ шифрования и HMAC ключ полученный от ваших настроек encryption_key через HKDF используя SHA-512 алгоритм дайджеста. Из-за настроек encryption_key , это даст тот же результат, что и encrypt() метод выше - в противном случае вы не сможете расшифровать его.
- Проверяем, если строка достаточно длинная, отдельный алгоритм HMAC проверяет ее на корректность (это делается для предотвращения атак против нее). Возвращать FALSE, если любая из проверок не выполняется.
- Декодируем строку в base64.
- Отделяем ВИ из шифр-текста и расшифровки указанных шифр-текста с помощью ВИ и производного ключа шифрования.
Использование пользовательских параметров
Допустим, вам приходится взаимодействовать с другой системой, которая находится вне вашего контроля и использует другой метод шифрования данных. Метод, не соответствует описанной выше последовательности и вероятно, не использует все шаги.
Библиотека шифрования позволяет изменять способ шифрования и расшифровки в процессе работы, так что вы можете легко адаптировать свое собственное решение для таких случаев.
Примечание
Можно использовать библиотеку без установки encryption_key в файле конфигурации.
Все что вам нужно сделать, это передать ассоциативный массив с несколькими параметрами в encrypt() или decrypt() метод. Вот пример:
// Предположим, что мы имеем $ciphertext, $key и $hmac_key
// из внешнего источника
$message = $this->encryption->decrypt(
$ciphertext,
array(
'cipher' => 'blowfish',
'mode' => 'cbc',
'key' => $key,
'hmac_digest' => 'sha256',
'hmac_key' => $hmac_key
)
);
В примере выше, мы расшифровываем сообщение, которое было зашифровано с помощью the Blowfish шифра в CBC режиме, с проверкой подлинности через SHA-256 HMAC.
Важно
Обратите внимание, что оба ‘key’ и ‘hmac_key’ используются в этом примере. При использовании настраиваемых параметров, шифрование и HMAC ключи не являются установленными в библиотеке с поведением по умолчанию.
Ниже приведен список доступных вариантов.
Если вам действительно нужно и вы знаете, что вы делаете, мы советуем не изменять процесс шифрования, поскольку это может негативно сказаться на безопасности, поэтому, делайте это с осторожностью.
Вариант | Значение по умолчанию | Обязательные / Необязательные | Описание |
---|---|---|---|
Шифр | N/A | Да | Алгоритм шифрования (см. поддерживаемые режимы шифрования и шифры). |
режим | N/A | Да | Режим шифрования (см. режимы шифрования). |
ключ | 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:
Алгоритм | Необработанная длина (байты) | Hex-encoded длина (байты) |
---|---|---|
sha512 | 64 | 128 |
sha384 | 48 | 96 |
sha256 | 32 | 64 |
sha224 | 28 | 56 |
Причина не включать в себя другие популярные алгоритмы, такие как MD5 или SHA1 заключается в том, что они больше не считаются достаточно безопасными, мы не хотим поощрять их использование. Если вам очень нужно использовать их, то это легко сделать используя родную PHP hash_hmac() функцию.
Более сильные алгоритмы конечно же будут добавлены в будущем, как только они появятся и станут широко доступными.
Настройки класса
- class CI_Encryption
- initialize($params)
Параметры: - $params (массив) – Параметры конфигурации
Возвращает: CI_Encryption экземпляр (цепочка методов)
Возвращаемый тип: CI_Encryption
Инициализирует (настраивает) библиотеку, для использования другого драйвера, шифра, режима или ключа.
Пример:
$this->encryption->initialize( array('mode' => 'ctr') );
Пожалуйста, обратитесь к разделу настройка библиотеки для детальной информации.
- encrypt($data[, $params = NULL])
Параметры: - $data (строка) – Данные для шифрования
- $params (масси) – Необязательные параметры
Возвращает: Шифрует данные или FALSE в случае неудачи
Возвращаемый тип: строка
Шифрует входные данные и возвращает зашифрованный текст.
Пример:
$ciphertext = $this->encryption->encrypt('My secret message');
Пожалуйста, обратитесь к разделу используем пользовательские параметры для получения информации о необязательных параметрах.
- decrypt($data[, $params = NULL])
Параметры: - $data (строка) – Данные для расшифровки
- $params (массив) – Необязательные параметры
Возвращает: Расшифрованные данные или FALSE в случае неудачи
Возвращаемый тип: строка
Расшифровывает входные данные и возвращает обычный текст.
Пример:
echo $this->encryption->decrypt($ciphertext);
Пожалуйста, обратитесь к разделу используем пользовательские параметры для получения информации о необязательных параметрах.
- create_key($length)
Параметры: - $length (число) – Выходная длина
Возвращает: Случайный криптографический ключ заданной длины или FALSE в случае неудаче
Возвращаемый тип: строка
Создает криптографический ключ путем выборки случайных данных из источников операционной системы (т.е. /dev/urandom).
- hkdf($key[, $digest = 'sha512'[, $salt = NULL[, $length = NULL[, $info = '']]]])
Параметры: - $key (строка) – Ввод ключевого материала
- $digest (строка) – Алгоритм SHA-2 семейства
- $salt (строка) – Соль (опционально)
- $length (число) – Выходня длина (опционально)
- $info (строка) – Информация context/application приложения (опционально)
Возвращает: Случайный ключ или FALSE в случае неудачи
Возвращаемый тип: строка
Получает ключ от другого предположительно слабее ключа.
Этот метод используется внутренне, чтобы получить шифрование и HMAC ключ из настроек вашего encryption_key.
Он публично доступен благодаря своей политики общего назначения. Это описано в RFC 5869.
Однако, в отличие от описания в RFC 5869, эта реализация не поддерживает SHA1.
Пример:
$hmac_key = $this->encryption->hkdf( $key, 'sha512', NULL, NULL, 'authentication' ); // $hmac_key случайный ключ с длиной в 64 байта