Библиотека Шифрования 

Важно

НЕ ИСПОЛЬЗУЙТЕ эту или любую другую библиотеку шифрования для хранения паролей пользователей! Пароли должны быть кешированы и вы должны сделать это через собственное PHP расширение кеширования паролей.

Библиотека шифрования обеспечивает двухстороннее шифрование данных. Делая это криптографически защищенным способом, она использует PHP-расширения, которые к сожалению не всегда доступны во всех системах. Вы должны иметь одну из следующих зависимостей для того, чтобы использовать эту библиотеку:

  • OpenSSL (и PHP 5.3.3)
  • MCryptMCRYPT_DEV_URANDOM наличие)

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

Использование библиотеки шифрования 

Инициализация класса 

Как и большинство классов 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)
    1. Получаем ключ шифрования и HMAC ключ полученный от ваших настроек encryption_key через HKDF используя SHA-512 алгоритм дайджеста.
    2. Генерируется случайный вектор инициализации (ВИ).
    3. Шифрование данных через AES-128 в CBC режиме (или другими предварительно настроенными шифром и режимом) с помощью вышеупомянутого производного ключа шифрования и вектор инициализации.
    4. Подставляем полученный вектор инициализации к получающемуся шифр-тексту.
    5. Кодируем полученную строку в base64, так что он может безопасно храниться или передаваться, не беспокоясь о наборах символов.
    6. Создаем SHA-512 HMAC проверку подлинности сообщения с помощью производной HMAC ключа для обеспечения целостности данных и сохраняем его в строку формата base64.
  • $this->encryption->decrypt($ciphertext)
    1. Получаем ключ шифрования и HMAC ключ полученный от ваших настроек encryption_key через HKDF используя SHA-512 алгоритм дайджеста. Из-за настроек encryption_key , это даст тот же результат, что и encrypt() метод выше - в противном случае вы не сможете расшифровать его.
    2. Проверяем, если строка достаточно длинная, отдельный алгоритм HMAC проверяет ее на корректность (это делается для предотвращения атак против нее). Возвращать FALSE, если любая из проверок не выполняется.
    3. Декодируем строку в base64.
    4. Отделяем ВИ из шифр-текста и расшифровки указанных шифр-текста с помощью ВИ и производного ключа шифрования.

Использование пользовательских параметров 

Допустим, вам приходится взаимодействовать с другой системой, которая находится вне вашего контроля и использует другой метод шифрования данных. Метод, не соответствует описанной выше последовательности и вероятно, не использует все шаги.

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

Примечание

Можно использовать библиотеку без установки 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 байта