От автора: не так давно на нашем сайте был опубликован урок о шифровании данных на языке PHP, используя расширение mcrypt. И в комментарии к нему прозвучал вопрос о том, как реализовать шифрование, используя открытый и закрытый ключ. Поэтому в данном уроке мы с Вами поговорим о данном виде шифрования.
Введение
Хотел бы сразу отметить, что шифрование – это довольно сложная наука и конечно за один урок мы с Вами не сможем рассмотреть все досконально. Но, мы рассмотрим – основу, то есть, как реализовать механизм шифрования, используя открытый и закрытый ключ.
Итак, системы шифрования с открытым и закрытым ключом были придуманы еще в 70-х гг. То есть – это были системы, которые обеспечивающие передачу шифрованных сообщений, для расшифровки которых необходимо было использовать ключ, отличный от ключа шифрования. Это было главное отличие новых систем от старых, в которых использовался всего один ключ – для шифрования и расшифровки сообщения.
В системах шифрования с открытым ключом используется скрипт, шифрующий данные при помощи открытого ключа. Открытый ключ — это шифр, который непосредственно выступает инструкцией по шифрованию сообщения. Открытый ключ создается скриптом шифрования, и для каждого пользователя он свой — уникальный.
После того, как сообщение зашифровано, его можно расшифровать только при помощи закрытого ключа.
Обратите внимание на рисунок(выше) – это схема работы системы шифрования с открытым и закрытым ключом.
Итак, к примеру Вам необходимо отправить шифрованное сообщение определенному пользователю. Для начала необходимо получить открытый ключ от этого пользователя. Получив данный ключ, Вы используя скрипт шифрования – шифруете сообщение и отправляете его пользователю. Для дешифрования сообщений пользователь использует свой закрытый ключ. При этом для расшифровки сообщения уже нельзя воспользоваться открытым ключом. Это означает, что только получатель сообщения сможет прочитать сообщение, используя свой закрытый ключ.
Таким образом, закрытый ключ в сочетании со скриптом шифрования используется для дешифрования сообщения, зашифрованного при помощи открытого ключа пользователя. Без знания закрытого ключа дешифровать зашифрованный файл невозможно.
Что потребуется для работы
В сегодняшнем уроке для реализации механизма шифрования мы будем использовать расширение языка PHP – OpenSSL.
Вообще OpenSSL — это система защиты и сертификации данных. SSL переводится, как система безопасных сокетов (secure socket layer). OpenSSL используется практически всеми сетевыми серверами для защиты передаваемой информацией и это достаточно сложная и обширная система. В сегодняшнем уроке мы рассмотрим только те моменты, которые затрагивают шифрование данных.
Итак, первым делом необходимо подключить расширение OpenSSL в Вашем интерпретаторе языка PHP. Для этого необходимо открыть главный конфигурационный файл php.ini и раскомментировать строку (убрать символ ; сначала данной строки):
1 |
extension=php_openssl.dll |
После этого не забудьте перезапустить веб-сервер. Если же Вы используете пакет denwer, в его базовом варианте, то, скорее всего данного расширения у Вас нет. Вам необходимо скачать и установить пакет расширений для Вашей версии denwer (данный пакет можно скачать с официального сайта).
Теперь еще один момент: после установки пакета дополнительных расширений и собственно после раскомментирования строки, что указана выше – расширение openssl может так и не заработать. Для исправления данной проблемы необходимо открыть папку (на вашем локальном диске) usr\local\php5 и найти два файла: libeay32.dll и ssleay32.dll. Данные файлы необходимо скопировать и вставить в папку usr\local\apache\bin. В данной папке уже есть копии этих библиотек, но их версии отличаются, от библиотек которые находятся в интерпретаторе языка PHP (в папке usr\local\php5). После этого перезапускаем denwer и все должно работать. Вообще на реальном сервере – хостинге, данное расширение установлено и корректно настроено.
Генерация ключей
Итак, первым делом, необходимо сгенерировать ключи. Для этого мы создадим файл Enc.class.php и создадим класс, который будет являться логическим ядром нашего скрипта:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<?php class Enc { static public function get_keys() { $config = array( "private_key_type"=>OPENSSL_KEYTYPE_RSA, "private_key_bits"=>512 ); $res = openssl_pkey_new($config); $privKey = ''; openssl_pkey_export($res,$privKey); $fpr = fopen("private.txt","w"); fwrite($fpr,$privKey); fclose($fpr); $arr = array( "countryName" => "UA", "stateOrProvinceName" => "Kievskaya Oblast", "localityName" => "Kiev", "organizationName" => "Organization", "organizationalUnitName" => "Soft", "commonName" => "localhost", "emailAddress" => "ilovessl@php.net" ); $csr = openssl_csr_new($arr,$privKey); $cert = openssl_csr_sign($csr,NULL, $privKey,10); openssl_x509_export($cert,$str_cert); $public_key = openssl_pkey_get_public($str_cert); $public_key_details = openssl_pkey_get_details($public_key); $public_key_string = $public_key_details['key']; $fpr1 = fopen("public.txt","w"); fwrite($fpr1,$public_key_string); fclose($fpr1); return array('private'=>$privKey,'public'=>$public_key_string); } } ?> |
В данном в классе создаем статический метод get_keys(), который мы будем использовать для генерации ключей и сохранении их в текстовых файлах (подразумевается, что данный метод будет вызван всего одни раз – для генерации и записи ключей в текстовые файлы). Первым дело создаем массив, конфигов, то есть задаем настройки при создании закрытого ключа:
1 2 3 4 |
$config = array( "private_key_type"=>OPENSSL_KEYTYPE_RSA, "private_key_bits"=>512 ); |
Указываем тип ключа OPENSSL_KEYTYPE_RSA (закрытый ключ для шифрования открытым и закрытым ключем) и размер в битах будущего ключа (512 бит). Далее генерируем закрытый ключ и возвращаем его дескриптор:
1 |
$res = openssl_pkey_new($config); |
Вытащим значение ключа из его дескритпора:
1 2 |
$privKey = ''; openssl_pkey_export($res,$privKey); |
Функция openssl_pkey_export() – возвращает закрытый ключ в виде строки и данная строка сохраняется в переменной $privKey, которая передается вторым аргументом данной функции. Первый параметр – это дескриптор ключа. Теперь давайте создадим файл index.php и выведем на экран значение переменной $privKey (в методе get_keys() я временно возвращаю значение закрытого ключа):
1 2 3 4 5 6 7 |
<?php include "Enc.class.php"; $keys = Enc::get_keys(); var_dump($keys); ?> |
Вот что мы увидим на экране:
Затем сохраняем полученный ключ в текстовый файл.
1 2 3 |
$fpr = fopen("private.txt","w"); fwrite($fpr,$privKey); fclose($fpr); |
Теперь если еще раз обновить скрипт, то мы увидим что создался текстовый файл в котором сохранен закрытый ключ. Далее необходимо сгенерировать открытый ключ. Для этого создадим запрос для сертификата – CSR (Certificate Signing Request). Который представляет собой зашифрованный текст, содержащий информацию о компании, доменном имени и т.д. Данный запрос необходим для приобретения SSL сертификата, который выдается центрами сертификации. Что бы создать запрос CSR, необходимо создать массив со следующими данными:
1 2 3 4 5 6 7 8 9 |
$arr = array( "countryName" => "UA", "stateOrProvinceName" => "Kievskaya Oblast", "localityName" => "Kiev", "organizationName" => "Organization", "organizationalUnitName" => "Soft", "commonName" => "localhost", "emailAddress" => "ilovessl@php.net" ); |
Где:
«countryName» => «UA» – двузначный код страны;
«stateOrProvinceName» => «Kievskaya Oblast» – регион или область;
«localityName» => «Kiev»- город;
«organizationName» => «Organization» – имя компании;
«organizationalUnitName» => «Soft» – название отдела;
«commonName» => «localhost» – доменное имя;
«emailAddress» => ilovessl@php.net – почтовый адрес.
Далее создаем запрос CSR:
1 |
$csr = openssl_csr_new($arr,$privKey); |
Обратите внимание, что необходимо передать функции openssl_csr_new(), ранее созданный массив и закрытый ключ. Дальше создаем сертификат:
1 2 |
$cert = openssl_csr_sign($csr,NULL, $privKey,10); openssl_x509_export($cert,$str_cert); |
Функция openssl_csr_sign – вернет дескриптор созданного сертификата. Ей необходимо передать следующие параметры: $csr- запрос csr, NULL – обозначает, что полученный сертификат будет самостоятельно сгенерированным сертификатом, $privKey – закрытый ключ, 10 – время актуальности сертификата в днях. Функция openssl_x509_export() – вытащит из дескриптора $cert сертификат и сохранит его в переменной $str_cert. Далее, генерируем открытый ключ:
1 2 3 |
$public_key = openssl_pkey_get_public($str_cert); $public_key_details = openssl_pkey_get_details($public_key); $public_key_string = $public_key_details['key']; |
Функция openssl_pkey_get_public() возвращает дескриптор открытого ключа (на основе полученного ранее сертификата), а функция openssl_pkey_get_details() возвращает массив, в котором в ячейке key, содержится открытый ключ. Давайте посмотрим, как он выглядит:
Далее записываем открытый ключ в файл и возвращаем массив с полученными ключами:
1 2 3 4 5 |
$fpr1 = fopen("public.txt","w"); fwrite($fpr1,$public_key_string); fclose($fpr1); return array('private'=>$privKey,'public'=>$public_key_string); |
Шифрование данных
Для шифрования данный добавим метод my_enc():
1 2 3 4 5 6 7 8 9 10 11 |
public function my_enc($str) { $path = "public.txt"; $fpr = fopen($path,"r"); $pub_key = fread($fpr,1024); fclose($fpr); openssl_public_encrypt($str,$result,$pub_key); return $result; } |
Как Вы видите, здесь мы читаем открытый ключ из текстового файла и вызываем функцию openssl_public_encrypt(), которая шифрует данные открытым ключом. Параметры, который необходимо ей передать: $str – строка для шифрования; $result – переменная в которую будут сохранены результаты и $pub_key – публичный ключ.
Дешифрование данных
Как обычно создаем новый метод:
1 2 3 4 5 6 7 8 9 10 |
public function my_dec($str) { $path = "private.txt"; $fpr = fopen($path,"r"); $pr_key = fread($fpr,1024); fclose($fpr); openssl_private_decrypt($str,$result,$pr_key); return $result; } |
Первым делом получаем закрытый ключ из текстового файла и вызываем функцию openssl_private_decrypt(), которая дешифрует данные закрытым ключом. Параметры, которые необходимо ей передать $str – строка для дешифрования, $result переменная в которую будет сохранен результат, $pr_key – закрытый ключ.
Проверка работы скрипта
Теперь давайте допишем код файла index.php, а именно создадим строку для шифрования и вызовем последовательно методы my_enc(), для шифрования и my_dec() для дешифрования (приведу полный код файла index.php):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php include "Enc.class.php"; //$keys = Enc::get_keys(); //var_dump($keys); $ob = new Enc(); $str = "привет мир"; echo "<h2>".$str."</h2>"; $cipher = $ob->my_enc($str); echo "<p style='font-size:25px'>Шифр: ".base64_encode($cipher)."</p>"; $str_d = $ob->my_dec($cipher); echo "<p style='font-size:25px'>Исходная строка: ".$str_d."</p>"; ?> |
Теперь давайте посмотрим, что у нас получилось:
Как Вы видите все успешно отработало. На этом данный урок завершен. Всего Вам доброго и удачного кодирования!!!
Комментарии (7)