Симметричное шифрование
Симметричное шифрование – это алгоритм шифрования, в котором используется один и тот же криптографический ключ как для шифрования, так и для расшифровки данных. Рассмотрим на PHP шифрование данных симметричным методом на основе алгоритма AES (Advanced Encryption Standard) – симметричного алгоритма блочного шифрования (размер блока 128 бит, ключ 128/192/256 бит). AES является одним из самых распространённых алгоритмов симметричного шифрования..
PHP шифрование данных AES
Как уже говорилось ранее, для шифровки и расшифровки потребуется ключ шифрования. Это может быть любая строка, но мы для его получения воспользуемся функцией, которая генерирует строку псевдослучайных байт длиной 40, и преобразуем полученный результат в шестнадцатеричное представление:
$bytes = openssl_random_pseudo_bytes(40);
$hex = bin2hex($bytes);
var_dump($hex);
На экран будет выведен результат следующего вида:
string(80) "5aa3c281e42ba7101f7227a7519d5e961c7bcf2b10a42914304bffc1afcebb1d2be98f53caa80d05"
Полученное значение мы будем использовать как секретный ключ шифрования и дешифрования данных (он должен храниться в тайне). Запишем его в переменную $key:
$key = "5aa3c281e42ba7101f7227a7519d5e961c7bcf2b10a42914304bffc1afcebb1d2be98f53caa80d05";
Теперь определим, что мы будем кодировать. Для первого примера возьмем обычную строку:
$data = 'Это строка закодирована симметричным алгоритмом шифрованием AES';
Мы будем шифровать данные алгоритмом AES с 192 битным ключом:
$method = "AES-192-CBC";
Все доступные методы шифрования можно посмотреть следующим образом:
var_dump(openssl_get_cipher_methods());
Имея данные для шифрования $data, выбранный метод $method и секретный ключ $key в PHP симметричное шифрование данных мы можем осуществить с помощью функции openssl_encrypt:
$encrypted = openssl_encrypt($data, $method, $key);
Выведем на экран результат с помощью var_dump($encrypted):
string(152) "qNiTUkY5GY63q2IjbZ034myIFAf7hyTX+dRJF4YjJmJCk15YqAccIigpECKlCmLEgft7WNUV3/yZVcSqxLO3aDDOoV/5oglU1hFRiLD9yBF9q6HrM0Ic2e0RCgXxaHFa6ae6dZ2mVzgSkZvZnasTYg=="
Чтобы расшифровать полученное значение, необходимо воспользоваться обратной функцией openssl_decrypt:
$decrypted = openssl_decrypt($encrypted, $method, $key);
Опять воспользуемся var_dump($decrypted):
string(107) "Это строка была закодирована симметричным шифрованием AES"
Конечный листинг примера симметричного шифрования/расшифровки данных на PHP будет следующий:
<?php
// Ключ шифрования
$key = "5aa3c281e42ba7101f7227a7519d5e961c7bcf2b10a42914304bffc1afcebb1d2be98f53caa80d05";
// Шифруемые данные
$data = 'Это строка была закодирована симметричным шифрованием AES';
// Метод шифрования
$method = "AES-192-CBC";
// Шифруем данные
$encrypted = openssl_encrypt($data, $method, $key);
// Смотрим результат
var_dump($encrypted);
// Дешифруем данные
$decrypted = openssl_decrypt($encrypted, $method, $key);
// Смотрим результат
var_dump($decrypted);
?>
PHP шифрование файлов AES
В PHP шифрование файлов от шифрования данных отличается лишь тем, что содержимое файла сначала необходимо прочитать, проделать с ним необходимые операции, а затем – записать.
Создадим обычный текстовый файл в текущей директории:
$ echo 'Этот файл кодирован на PHP с помощью симметричного алгоритма AES' > aes.txt
Ключ и метод шифрования мы возьмем из предыдущего примера, а данные для кодирования получим из файла aes.txt с помощью функции file_get_contents:
$key = "5aa3c281e42ba7101f7227a7519d5e961c7bcf2b10a42914304bffc1afcebb1d2be98f53caa80d05";
$method = "AES-192-CBC";
$file = 'aes.txt';
$contents = file_get_contents($file);
Закодируем содержимое файла и запишем его в новый файл aes-encrypted.txt с помощью функции file_put_contents:
$contetsEncrypted = openssl_encrypt($contents, $method, $key);
$fileEncrypted = 'aes-encrypted.txt';
file_put_contents($fileEncrypted, $contetsEncrypted);
Посмотрим содержимое полученного файла:
$ cat aes-encrypted.txt
u1IdVyyNwECahzAaN0DQdSPx4lDiXHKXWc8/yl6KLne3tcyT/vUD/96Z84wgZHyhWc0daYT7JxiShat9xUjdQEC5V2nLuuMZ1/yUmIsE4HKZcvZEki99e0gAdtP9M0vdo82rEUfFnKe78wT7/zeOs1PBLaQvpXWbM8VcVeEVzTc=
Осталось попробовать расшифровать этот файл и записать его:
$contents = file_get_contents($fileEncrypted);
$contentsDecrypted = openssl_decrypt($contents, $method, $key);
$fileDecrypted = 'aes-decrypted.txt';
file_put_contents($fileDecrypted, $contentsDecrypted);
Проверяем результат:
$ cat aes-decrypted.txt
Этот файл кодирован на PHP с помощью симметричного алгоритма AES
Конечный листинг симметричного шифрования файла на PHP алгоритмом AES:
<?php
// Ключ шифрования
$key = "5aa3c281e42ba7101f7227a7519d5e961c7bcf2b10a42914304bffc1afcebb1d2be98f53caa80d05";
// Метод шифрования
$method = "AES-192-CBC";
// Файл для шифрования
$file = 'aes.txt';
// Читаем содержимое файла
$contents = file_get_contents($file);
// Шифруем содержимое файла
$contetsEncrypted = openssl_encrypt($contents, $method, $key);
// Шифрованный файл
$fileEncrypted = 'aes-encrypted.txt';
// Записываем шифрованные данные в новый файл
file_put_contents($fileEncrypted, $contetsEncrypted);
// Читаем содержимое шифрованного файла
$contents = file_get_contents($fileEncrypted);
// Расшифровываем содержимое шифрованного файла
$contentsDecrypted = openssl_decrypt($contents, $method, $key);
// Расшифрованный файл
$fileDecrypted = 'aes-decrypted.txt';
// Записываем расшифрованные данные в новый файл
file_put_contents($fileDecrypted, $contentsDecrypted);
?>
Асимметричное шифрование
Асимметричное шифрование отличается от симметричного тем, что для шифровки и расшифровки данных используется не один общий ключ, а два разных. Одним из самых распространенных алгоритмов асимметричного шифрования является RSA (аббревиатура от фамилий Rivest, Shamir и Adleman) — криптографический алгоритм с открытым ключом. В этом алгоритме для шифрования данных используется публичный ключ, а для расшифровки – секретный приватный ключ.
PHP шифрование данных RSA
Для работы с данным алгоритмом нам понадобятся публичный public.crt и приватный private.pem ключ. Получить их можно из консоли с помощью openssl. Сгенерируем пару rsa с ключом 2048 бит на 365 дней (“/C=RU/ST=MO/L=MOSCOW/O=POCKETADMIN/TECH=XX/CN=pocketadmin.tech/emailAddress=”example@pocketadmin.tech – информация о субъекте, который выпустил ключ):
$ openssl req -newkey rsa:2048 -nodes -keyout private.pem -out public.crt -x509 -days 365 -subj "/C=RU/ST=MO/L=MOSCOW/O=POCKETADMIN/TECH=XX/CN=pocketadmin.tech/emailAddress="example@pocketadmin.tech
Generating a 2048 bit RSA private key
..................................................................+++
.+++
writing new private key to 'private.pem'
-----
Subject Attribute TECH has no known NID, skipped
Объявим шифруемую строку и ключи:
$data = 'Эта строка была зашифрована на PHP асимметричным алгоритмом RSA';
$filePublicKey = 'public.crt';
$filePrivateKey = 'private.pem';
Ещё раз хочу обратить внимание, что сам приватный ключ необходимо хранить в тайне! Непосредственно для шифрования третьим лицам достаточно передать только публичный ключ.
Получаем содержимое файла с публичным ключом и извлекаем сам ключ:
$contentsPublicKey = file_get_contents($filePublicKey);
$publicKey = openssl_get_publickey($contentsPublicKey);
С помощью функции openssl_public_encrypt шифруем данные $data публичным ключом $publicKey. Результат шифрования будет помещен в переменную $encrypted:
openssl_public_encrypt($data, $encrypted, $publicKey);
В дальнейшем, для расшифровки нам понадобится приватный ключ:
$contentsPrivateKey = file_get_contents($filePrivateKey);
$privateKey = openssl_get_privatekey($contentsPrivateKey);
Чтобы расшифровать данные $encrypted приватным ключом $privateKey воспользуемся функцией openssl_private_decrypt. Результат помещается в переменную $decrypted:
openssl_private_decrypt($encrypted, $decrypted, $privateKey);
Проверим результат с помощью var_dump($decrypted):
string(112) "Эта строка была зашифрована на PHP асимметричным алгоритмом RSA"
Приведем весь код на PHP шифрования данных алгоритмом RSA:
<?php
// Шифруемые данные
$data = 'Эта строка была зашифрована на PHP асимметричным алгоритмом RSA';
// Публичный и приватный ключи шифрования, полученные с помощью openssl
$filePublicKey = 'public.crt';
$filePrivateKey = 'private.pem';
// Извлекаем публичный ключ для шифрования
$contentsPublicKey = file_get_contents($filePublicKey);
$publicKey = openssl_get_publickey($contentsPublicKey);
// Шифруем данные
openssl_public_encrypt($data, $encrypted, $publicKey);
// Извлекаем приватный ключ
$contentsPrivateKey = file_get_contents($filePrivateKey);
$privateKey = openssl_get_privatekey($contentsPrivateKey);
// Расшифровываем данные с помощью приватного ключа
openssl_private_decrypt($encrypted, $decrypted, $privateKey);
// Проверяем результат
var_dump($decrypted);
?>
PHP шифрование файлов RSA
Создадим простой текстовый файл, который мы будем шифровать:
$ echo 'Этот файл был зашифрован на PHP асимметричным алгоритмом RSA' > rsa.txt
Используем публичный и приватный ключ из предыдущего примера. Объявим шифруемый файл, шифрованный и расшифрованный:
$filePublicKey = 'public.crt';
$filePrivateKey = 'private.pem';
$file = 'rsa.txt';
$fileEncrypted = 'rsa-encrypted.txt';
$fileDecrypted = 'rsa-decrypted.txt';
По аналогии с предыдущими примерами: получаем публичный ключ $publicKey и с помощью него шифруем содержание файла $file. Результат записываем в $fileEncrypted:
$contentsPublicKey = file_get_contents($filePublicKey);
$publicKey = openssl_get_publickey($contentsPublicKey);
$contents = file_get_contents($file);
openssl_public_encrypt($contents, $contentsEncrypted, $publicKey);
file_put_contents($fileEncrypted, $contentsEncrypted);
Чтобы расшифровать этот файл: получаем приватный ключ $privateKey, расшифровываем содержимое файла $fileEncrypted. Данные записываем в файл $fileDecrypted:
$contentsPrivateKey = file_get_contents($filePrivateKey);
$privateKey = openssl_get_privatekey($contentsPrivateKey);
$contentsEncrypted = file_get_contents($fileEncrypted);
openssl_private_decrypt($contentsEncrypted, $contentsDecrypted, $privateKey);
file_put_contents($fileDecrypted, $contentsDecrypted);
Проверим созданный файл:
$ cat rsa-decrypted.txt
Этот файл был зашифрован на PHP асимметричным алгоритмом RSA
Соберем весь код:
<?php
// Объявляем файлы с публичным и приватным ключами
$filePublicKey = 'public.crt';
$filePrivateKey = 'private.pem';
// Объявляем файлы: шифруемый, шифрованный и расшифрованный
$file = 'rsa.txt';
$fileEncrypted = 'rsa-encrypted.txt';
$fileDecrypted = 'rsa-decrypted.txt';
// Получаем публичный ключ из файла
$contentsPublicKey = file_get_contents($filePublicKey);
$publicKey = openssl_get_publickey($contentsPublicKey);
// Получаем содержимое файла, шифруем его и записываем в новый файл
$contents = file_get_contents($file);
openssl_public_encrypt($contents, $contentsEncrypted, $publicKey);
file_put_contents($fileEncrypted, $contentsEncrypted);
// Получаем приватный ключ из файла
$contentsPrivateKey = file_get_contents($filePrivateKey);
$privateKey = openssl_get_privatekey($contentsPrivateKey);
// Расшифровываем содержимое шифрованного файла с помощью приватного ключа. Записываем расшифрованный файл
$contentsEncrypted = file_get_contents($fileEncrypted);
openssl_private_decrypt($contentsEncrypted, $contentsDecrypted, $privateKey);
file_put_contents($fileDecrypted, $contentsDecrypted);
?>