Из этого туториала вы узнаете, как зашифровать произвольно большие сообщения с помощью асимметричных ключей и PHP-библиотеки phpseclib .
Вступление
Большинство из нас понимают необходимость шифрования конфиденциальных данных перед их передачей. Шифрование — это процесс перевода открытого текста (то есть обычных данных) в шифрованный текст (то есть секретных данных). Во время шифрования текстовая информация преобразуется в зашифрованный текст с использованием ключа и алгоритма . Чтобы прочитать данные, зашифрованный текст необходимо расшифровать (то есть перевести обратно в открытый текст), используя ключ и алгоритм .
Алгоритм шифрования представляет собой серию математических операций, применяемых к числовому значению (ям) ключа и числовым значениям символов в строке открытого текста. Результаты зашифрованы. Чем больше ключ, тем надежнее шифрованный текст.
Основная проблема, которую необходимо решить с помощью любого алгоритма шифрования, — это распределение ключей. Как вы передаете ключи тем, кто в них нуждается, чтобы установить безопасную связь?
Решение проблемы зависит от характера ключей и алгоритмов.
Алгоритмы шифрования и ключи
Существует два основных типа алгоритмов шифрования:
1. Симметричные алгоритмы, которые используют один и тот же ключ для шифрования и дешифрования.
2. Асимметричные алгоритмы, которые используют разные ключи для шифрования и дешифрования.
Если выбран симметричный алгоритм, у отправителя и получателя должен быть один и тот же ключ. Если отправитель и получатель находятся в разных местах, передача самого ключа становится уязвимой.
Если выбран асимметричный алгоритм, существует два ключа: открытый ключ и закрытый ключ. Данные, зашифрованные с помощью открытого ключа, могут быть расшифрованы только с помощью соответствующего закрытого ключа. Получатель сначала передает свой открытый ключ отправителю. Отправитель использует этот открытый ключ для шифрования сообщения, а затем передает сообщение получателю. Получатель расшифровывает сообщение своим закрытым ключом.
С помощью асимметричного алгоритма получатель может передавать открытый ключ тому, кому он пожелает, не опасаясь компромисса, поскольку только владелец личного ключа может расшифровать сообщение.
Асимметричные алгоритмы решают проблему распределения ключей.
Выбор алгоритмов шифрования
Сильные криптографические алгоритмы основаны на продвинутой математике и теории чисел. Как правило, криптографический алгоритм является «сильным», если для данного размера ключа расшифровать сообщение будет неоправданно долго. 1
Из-за сложности криптографических алгоритмов выбор одного из другого может сбить с толку тех, кто не имеет большого опыта в математике. Таким образом, многие коммерческие и государственные организации полагаются на Национальный институт стандартов и технологий (NIST) — нерегулирующее агентство США — для получения рекомендаций по надежной криптографии.
NIST определяет три асимметричных алгоритма: RSA, DSA и ECDSA. ECDSA — относительно новичок, поэтому двумя распространенными асимметричными алгоритмами являются RSA и DSA. RSA часто является предпочтительным коммерческим алгоритмом, поскольку стандарт легко допускает больший размер ключа. 2
В 2001 году NIST выбрал алгоритм Rijndael в качестве предпочтительного симметричного алгоритма вместо устаревшего DES (Стандарт шифрования данных). 3
Проблема с ключами RSA
Хотя асимметричные алгоритмы решают проблему распределения ключей, существует еще одна проблема. Природа алгоритма RSA такова, что он может шифровать только ограниченное количество открытого текста. Например, если ваш размер ключа составляет 2048 бит, то вы ограничены 256 байтами (максимум) незашифрованных данных, которые могут быть зашифрованы. 4
Вот краткое изложение нашей проблемы:
1. Асимметричные ключи легко и безопасно обмениваются, но имеют ограниченный размер сообщения.
2. Симметричные ключи имеют неограниченный размер сообщения, но их трудно безопасно обменять.
Решение
Решение проблемы состоит в том, чтобы зашифровать сообщение симметричным ключом, затем асимметрично зашифровать ключ и прикрепить его к сообщению.
Когда сообщение поступит в приемник, у него будет и симметричный ключ, и сообщение. Получатель извлекает зашифрованный симметричный ключ, асимметрично расшифровывает его, а затем использует его для расшифровки остальной части сообщения.
В следующем разделе описываются процессы шифрования и дешифрования шаг за шагом.
шифрование
- Получатель генерирует пару ключей и передает свой открытый ключ отправителю.
- Отправитель генерирует случайный симметричный ключ и использует его для шифрования большого сообщения.
- Отправитель шифрует сообщение симметричным ключом.
- Отправитель шифрует симметричный ключ открытым ключом получателя.
- Отправитель объединяет зашифрованный симметричный ключ и зашифрованное сообщение.
- Отправитель передает зашифрованное сообщение получателю.
Дешифрирование
После того, как получатель получит сообщение, он обратит процесс:
1. Получатель извлекает зашифрованный симметричный ключ из сообщения.
2. Получатель расшифровывает симметричный ключ, используя свой закрытый ключ.
3. Получатель расшифровывает сообщение с помощью симметричного ключа.
Программирование решения на PHP
Чтобы продемонстрировать эту технику, мы будем использовать PHP Secure Communications Library . Эта библиотека (phpseclib) содержит свободные и открытые реализации на чистом PHP с целыми числами произвольной точности, RSA, DES, 3DES, RC4, Rijndael, AES, SSH-1, SSH-2 и SFTP.
Библиотека спроектирована таким образом, что она использует преимущества более быстрых функций шифрования (таких как open_ssl и mcrypt), если они доступны, для целей производительности. Однако иногда эти библиотеки и функции не доступны программистам PHP (например, в среде общего хостинга). Итак, phpseclib разработан для надежной работы, хотя и медленнее, если доступен только PHP.
Вы можете установить его через Composer .
Документацию по phpseclib можно найти по адресу http://phpseclib.sourceforge.net/documentation/index.html.
Образец кода
Давайте напишем наш демонстрационный код шаг за шагом.
Генерация открытых и закрытых ключей
Класс RSA содержит метод генерации ключей. В приведенном ниже примере вы видите, как мы генерируем и сохраняем пару ключей. В реальной производственной среде закрытый ключ будет храниться в безопасном месте, пока не наступит время расшифровки сообщения. Открытый ключ будет передан отправителю сообщения.
$rsa = new Crypt_RSA();
$keys = $rsa->createKey(2048);
file_put_contents('key.pri',$keys['privatekey']);
file_put_contents('key.pub',$keys['publickey']);
Функция шифрования
Функция encrypt_message принимает три параметра:
1. $plaintext
2. $asym_key
3. $key_length
Это необязательный параметр.
function encrypt_message($plaintext,$asym_key,$key_length=150)
{
$rsa = new Crypt_RSA();
$rij = new Crypt_Rijndael();
// Generate Random Symmetric Key
$sym_key = crypt_random_string($key_length);
// Encrypt Message with new Symmetric Key
$rij->setKey($sym_key);
$ciphertext = $rij->encrypt($plaintext);
$ciphertext = base64_encode($ciphertext);
// Encrypted the Symmetric Key with the Asymmetric Key
$rsa->loadKey($asym_key);
$sym_key = $rsa->encrypt($sym_key);
// Base 64 encode the symmetric key for transport
$sym_key = base64_encode($sym_key);
$len = strlen($sym_key); // Get the length
$len = dechex($len); // The first 3 bytes of the message are the key length
$len = str_pad($len,3,'0',STR_PAD_LEFT); // Zero pad to be sure.
// Concatenate the length, the encrypted symmetric key, and the message
$message = $len.$sym_key.$ciphertext;
return $message;
}
Функция расшифровки
Функция расшифровки принимает два параметра:
1. $message
2. $asym_key
function decrypt_message($message,$asym_key)
{
$rsa = new Crypt_RSA();
$rij = new Crypt_Rijndael();
// Extract the Symmetric Key
$len = substr($message,0,3);
$len = hexdec($len);
$sym_key = substr($message,0,$len);
//Extract the encrypted message
$message = substr($message,3);
$ciphertext = substr($message,$len);
$ciphertext = base64_decode($ciphertext);
// Decrypt the encrypted symmetric key
$rsa->loadKey($asym_key);
$sym_key = base64_decode($sym_key);
$sym_key = $rsa->decrypt($sym_key);
// Decrypt the message
$rij->setKey($sym_key);
$plaintext = $rij->decrypt($ciphertext);
return $plaintext;
}
Вывод
По мере того, как программы и веб-службы становятся все более связанными, безопасный обмен данными между удаленными процессами должен стать рутиной. Поскольку асимметричные ключи могут передаваться безопасно, они являются предпочтительными. Тем не менее, они имеют ограниченный размер сообщения. Гибридный подход, использующий как симметричные, так и асимметричные алгоритмы, может устранить оба эти ограничения.
PHP Secure Communications Library предоставляет удобные, чистые реализации PHP симметричных и асимметричных стандартных отраслевых алгоритмов. Это предоставляет нам средства для создания гибридного решения на PHP.
Исходный код этой статьи находится на github: https://github.com/sitepoint-editors/sitepointcrypto