Здравствуйте друзья! Вот наконец то и я добрался до Хабра ресурса! Сразу скажу, я далеко не профессионал, и отношу себя скорее к разряду чайников, но если я поставил себе цель, я стараюсь ее реализовывать любым путем, даже если поставленная задача порой пугает меня. К чему это я? К тому что, этот Tutorial скорее для чайников, которые хотят реализовать простейшее асинхронное шифрование данных и посмотреть, как это работает, нежели для профи, которые пишут статьи, которые новичку сложно понять, не говоря уже о повторении и реализации готовой составляющей!
Небольшое отступление. Собственно говоря к чему вообще весь этот пост, спросите вы? Этот пост к тому, что пытаясь понять как работает RSA шифрование, я ни где не смог найти более понятного и короткого кода, для понимания «что вообще происходит». Блуждая по просторам всемирной паутины в поисках разъяснения, по методу "разжевал и положил в рот", я ни где ни смог найти внятного разъяснения, о таком сложном принципе работы как RSA шифрование. Конечно же в поиске знаний я всегда натыкался на Хабр-статьи. Здесь очень много чего написано, но на уровне Профи, на уровне чайника, это выглядело примерно так, как когда я захотел сделать свое RSA шифрование, открыл encrypt.js и с ужасом закрыл его, вспомнив поговорку программиста про велосипед. Я подумал: «Да, не стоит!».
В итоге, поиски не прошли даром и у меня получилось собрать все воедино, написать небольшой код для реализации RSA шифрования, что бы попробовать его в деле и понять, как это все работает.
Скомпилировав свои знания, я как можно проще старался реализовать проект, что бы каждый начинающий веб разработчик смог его повторить.
Итак, начнем друзья!
Совсем недавно, при разработке своего движка, я дошел до этапа безопасности передачи данных.
Может это я такой ненормальный, но меня до паники волнует этот вопрос.mПерерыл все, конечно же не обошел стороной и Хабр.
Задача была следующая, передать зашифрованные данные клиента→сервер, а на стороне сервера расшифровать их. Всe!
В принципе ничего сложного, но кто читал про Алису и Боба в wikipedia знают, что при передачи данных по незащищенному протоколу http, когда Алиса отправляет письмо Бобу, между ними может сидеть Ева, перехватывать это письмо и читать его. Наиболее детально я прочитал про это здесь.
В качестве локального сервера я использовал OpenServer.
Важно!
Настройки сервера:
— Apache 2.4
— PHP-5.5
Зачем и почему, об этом чуть ниже, а пока настроили и поехали дальше! Качаем jQuery. Качаем JSencrupt. Делаем все удобно и красиво, мы же хотим, что было все было «как по полочкам разложено». Создаем папку js в корне сайта, и кидаем туда скаченные jquery-3.2.0.min.js и jsencrypt.js.
Создаем папку system, а в ней файл decode.php, который будет декодировать кодированное сообщение и возвращать нам, показывая что все работает. На деле нам это конечно не нужно, ведь наша задача отправить зашифрованное сообщение на сервер, дешифровать его там и работать уже с дешифрованными данными, но сначала нужен приватный и публичный ключ.
Я заранее сгенерировал пару ключей:
MIIEpAIBAAKCAQEA9vWm5GzW1kUlDuZaQYB8o2zu4cp8YiTJnyQd5Gb4A2wVt3XK
Bu+4qLi1hd/6o9PMu9FB6rM64LrN2z3dWA+hBcXU5V1YRvCq5IBK3nTWI1KkRew3
UIQqOMYVhIrXDQcgpmmIu8GprJKsh5tdPTI8EJe/Bwezw89czaGTmXsNi5C1YEJn
zK3v8mifBuozNTnCMGZ7tHLSyS+SKyhY3EO1iN7WcTM7PcXbncCQWea4cykZvMg+
vx331aAUpS7gauWAjQvMIqQe9+txuUQiErs3gtvVzl3QyiVLuOnaxn5VoYyZse4p
QIW4OV5a4lQrJR0zWYBx4hmuM3VzPiQI1l+3TQIDAQABAoIBAB4flL3kMMhuIrkQ
jA3VWF6u2OydwFJQXm+U/jhv/uyb8IIyUfRKpWGfNjUgPvhgy2ZVfg7c0d+7qYSG
pUsqjN+hY/ieTDhK/u1kYL2FzuD8IaGN0Kl3lZbbQqCqNtUV+3uQ/+a3FrVAJt9b
qiHe0MjNWbXH0LufvZgvj0t3YQ2W2dDgqT+7IBj62YIx2fhutZAu1kYSFIbhelQr
h/Hhbw6AViLSVdJoj/wnfZKdWplbKcy9JgcKFE3FYnzX2I/zQsnzdefF0MpX0p4R
JK07J/sqc4Tmt25GrYHh+dy27m+XD7350d1LuYkImfdN7Ypd6Pm+vFOLGVRDmih/
qWlY1tkCgYEA/hV37itK654AqNHNwvzhG9tG2VO/UV7qrHQJ+tnHE+833fT/n+IR
wq0PEpbl7ZI6UffcqHmZ+kXWtH/t5bBpAWc4XFT208nyenf0DshIE2EU4Qjp81YH
AdE+k9uOG5hnytg63UXaPPRAL0G3eAgpauBnFhdEEev1kdhVZhqojE8CgYEA+NJt
6/GQHLqISlVIoE+jVHNXZ88LbKH9ox3bLVof3BQA36lXIgcFCqJxhBlfzQiWCWvt
WxXL35eL4ZRNbHv7KPbe5+sFFeLz4BLB7c+MBFqS7VzKYiEbzDmJ+u9Eq1HrH0Ly
AUNxCwiWjHiV4i3Qg4EdQ2GOzzfHJwPBYW+eT6MCgYA+CP3UH6vWJSiiDz9+qQFJ
LNt6elEOy+7eFiLNpVhOzKxGO+ghoC+X6WrxrfgLbhVhJ/QvCimHCoAmZ8mst8qb
dhkzqebtxLO4JQtohIvcd2qCmwuLxuhFEFKIBSYIJMjKpMqSddiX40a8gv4Jh2yd
VJa2tQ2AlqzJZBlNqZqXTwKBgQDjUFrbknP1yvN39THEQv0TycuwKpZlSBhPTJdP
d2ZjyGKD8lCH5aHVdVH/PK8owQ9QzCirbd4zBl/kVXfmA94QLni1px+ePxhNPNWu
TE2+LIDOGFdMDrM2f9puROiXGt+ST7aHMPW0/sOK0R8c4n37pZj2VcoBxRNLsUKZ
oT8fwQKBgQDOTq20saBbZzhOi6CCPAEu7dTCpPel2fo62uRwmenLaFvQ639wvXXB
UE9XApN3GQVwDe9qENZdc2FfF4WepexU4XRVdThIo6q/iBQhf/FvEai8WUGr1mhs
1IiCxAJur7Dc1Wk7niiCBgBWrZVART2Rp36atAog1ATdxwEHMyPmkg==
-----END RSA PRIVATE KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9vWm5GzW1kUlDuZaQYB8
o2zu4cp8YiTJnyQd5Gb4A2wVt3XKBu+4qLi1hd/6o9PMu9FB6rM64LrN2z3dWA+h
BcXU5V1YRvCq5IBK3nTWI1KkRew3UIQqOMYVhIrXDQcgpmmIu8GprJKsh5tdPTI8
EJe/Bwezw89czaGTmXsNi5C1YEJnzK3v8mifBuozNTnCMGZ7tHLSyS+SKyhY3EO1
iN7WcTM7PcXbncCQWea4cykZvMg+vx331aAUpS7gauWAjQvMIqQe9+txuUQiErs3
gtvVzl3QyiVLuOnaxn5VoYyZse4pQIW4OV5a4lQrJR0zWYBx4hmuM3VzPiQI1l+3
TQIDAQAB
-----END PUBLIC KEY-----
Но вы конечно же захотите сгенерировать свои:
В OpenServer на флажке, правой кнопкой мышки → Дополнительно → Консоль → Запускаем.
Для 2048 bit-ного ключа создаем приватный ключ, соответственно если нужно более меньший bit-ый ключ, ставим вместо значений 2048, например 512, и так копируем и вставляем в CMD:
openssl genrsa -out rsa_2048_priv.pem 2048
Для просмотра ключа, копируем и вставляем в CMD:
cat rsa_2048_priv.pem
Создаем публичный ключ, копируем и вставляем в CMD:
openssl rsa -pubout -in rsa_2048_priv.pem -out rsa_2048_pub.pem
Смотрим публичный ключ, копируем и вставляем в CMD:
cat rsa_2048_pub.pem
Все созданные ключи у меня появились в корне папки с программой OpenServer, так что если захотите снова посмотреть созданные приватные и публичные ключи, ищите их там.
Все теперь мы научились сами генерировать свои ключи, теперь приступим к кодингу! В созданном ранее файле decode.php пишем следующее:
$pk = '-----BEGIN RSA PRIVATE KEY-----//ключ который никто не должен знать
MIIEpAIBAAKCAQEA9vWm5GzW1kUlDuZaQYB8o2zu4cp8YiTJnyQd5Gb4A2wVt3XK
Bu+4qLi1hd/6o9PMu9FB6rM64LrN2z3dWA+hBcXU5V1YRvCq5IBK3nTWI1KkRew3
UIQqOMYVhIrXDQcgpmmIu8GprJKsh5tdPTI8EJe/Bwezw89czaGTmXsNi5C1YEJn
zK3v8mifBuozNTnCMGZ7tHLSyS+SKyhY3EO1iN7WcTM7PcXbncCQWea4cykZvMg+
vx331aAUpS7gauWAjQvMIqQe9+txuUQiErs3gtvVzl3QyiVLuOnaxn5VoYyZse4p
QIW4OV5a4lQrJR0zWYBx4hmuM3VzPiQI1l+3TQIDAQABAoIBAB4flL3kMMhuIrkQ
jA3VWF6u2OydwFJQXm+U/jhv/uyb8IIyUfRKpWGfNjUgPvhgy2ZVfg7c0d+7qYSG
pUsqjN+hY/ieTDhK/u1kYL2FzuD8IaGN0Kl3lZbbQqCqNtUV+3uQ/+a3FrVAJt9b
qiHe0MjNWbXH0LufvZgvj0t3YQ2W2dDgqT+7IBj62YIx2fhutZAu1kYSFIbhelQr
h/Hhbw6AViLSVdJoj/wnfZKdWplbKcy9JgcKFE3FYnzX2I/zQsnzdefF0MpX0p4R
JK07J/sqc4Tmt25GrYHh+dy27m+XD7350d1LuYkImfdN7Ypd6Pm+vFOLGVRDmih/
qWlY1tkCgYEA/hV37itK654AqNHNwvzhG9tG2VO/UV7qrHQJ+tnHE+833fT/n+IR
wq0PEpbl7ZI6UffcqHmZ+kXWtH/t5bBpAWc4XFT208nyenf0DshIE2EU4Qjp81YH
AdE+k9uOG5hnytg63UXaPPRAL0G3eAgpauBnFhdEEev1kdhVZhqojE8CgYEA+NJt
6/GQHLqISlVIoE+jVHNXZ88LbKH9ox3bLVof3BQA36lXIgcFCqJxhBlfzQiWCWvt
WxXL35eL4ZRNbHv7KPbe5+sFFeLz4BLB7c+MBFqS7VzKYiEbzDmJ+u9Eq1HrH0Ly
AUNxCwiWjHiV4i3Qg4EdQ2GOzzfHJwPBYW+eT6MCgYA+CP3UH6vWJSiiDz9+qQFJ
LNt6elEOy+7eFiLNpVhOzKxGO+ghoC+X6WrxrfgLbhVhJ/QvCimHCoAmZ8mst8qb
dhkzqebtxLO4JQtohIvcd2qCmwuLxuhFEFKIBSYIJMjKpMqSddiX40a8gv4Jh2yd
VJa2tQ2AlqzJZBlNqZqXTwKBgQDjUFrbknP1yvN39THEQv0TycuwKpZlSBhPTJdP
d2ZjyGKD8lCH5aHVdVH/PK8owQ9QzCirbd4zBl/kVXfmA94QLni1px+ePxhNPNWu
TE2+LIDOGFdMDrM2f9puROiXGt+ST7aHMPW0/sOK0R8c4n37pZj2VcoBxRNLsUKZ
oT8fwQKBgQDOTq20saBbZzhOi6CCPAEu7dTCpPel2fo62uRwmenLaFvQ639wvXXB
UE9XApN3GQVwDe9qENZdc2FfF4WepexU4XRVdThIo6q/iBQhf/FvEai8WUGr1mhs
1IiCxAJur7Dc1Wk7niiCBgBWrZVART2Rp36atAog1ATdxwEHMyPmkg==
-----END RSA PRIVATE KEY-----'
$data = $_POST['data'];//получаем шифрованный текст
$ogp = openssl_get_privatekey($pk);
if(@openssl_private_decrypt(base64_decode($data), $out, $ogp))echo $out;//если все прошло успешно выводим дешифрованные данные
Далее создадим в папке /js, файл script.js в котором напишем обработчик кнопки:
$(document).ready(function(){ //дожидаемся загрузки документа
$('#btn').click(function(){ //кликаем по кнопке
var pub = '-----BEGIN PUBLIC KEY----- //присваиваем переменной публичный ключ
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9vWm5GzW1kUlDuZaQYB8
o2zu4cp8YiTJnyQd5Gb4A2wVt3XKBu+4qLi1hd/6o9PMu9FB6rM64LrN2z3dWA+h
BcXU5V1YRvCq5IBK3nTWI1KkRew3UIQqOMYVhIrXDQcgpmmIu8GprJKsh5tdPTI8
EJe/Bwezw89czaGTmXsNi5C1YEJnzK3v8mifBuozNTnCMGZ7tHLSyS+SKyhY3EO1
iN7WcTM7PcXbncCQWea4cykZvMg+vx331aAUpS7gauWAjQvMIqQe9+txuUQiErs3
gtvVzl3QyiVLuOnaxn5VoYyZse4pQIW4OV5a4lQrJR0zWYBx4hmuM3VzPiQI1l+3
TQIDAQAB-----END PUBLIC KEY-----',//переносы строк отделяем обратным слешем
crypt = new JSEncrypt();//создаем объект JSEncrypt
crypt.setPublicKey(pub);//устанавливаем публичный ключ
var data = $('#data').val(),//считываем введенные данные с #data
data = crypt.encrypt(data);//шифруем данные
$.ajax({передаем данные методом Ajax
url: '/system/decode.php',
type: 'post',
dataType: 'text',
data: {data: data},
success: function(a){
if(a){//если данные пришли вписываем их в поля #encrypted и #reply
$('#encrypted').val(data);//шифрованные данные на сервер
$('#reply').val(a);//дешифрованные данные с сервера
}
}
});
});
});
Создаем файл в корне сайта index.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<script type="text/javascript" src="js/jquery-3.2.0.min"></script>
<script type="text/javascript" src="js/jsencrypt.js"></script>
<script type="text/javascript" src="js/script.js"></script>
</head>
<body>
<input id="data" style="width: 120px; height: 30px; margin-bottom:5px; font-size: 21px;" placeholder="Данные:"/>
<input id="encrypted" style="width: 100%; height: 30px; margin-bottom:5px; background-color: white; border: 1px solid gray; font-size: 21px;" placeholder="Данные на сервер:"/>
<input id="reply" style="width: 100%; height: 30px; margin-bottom:5px; background-color: white; border: 1px solid gray; font-size: 21px;" placeholder="Ответ Сервера:"/>
<div id="btn" style="width: 120px; height: 30px; border: 1px solid gray; margin-bottom:5px; cursor: pointer; background-color: gray; color: white; font-size: 21px; text-align: center; border-radius: 3px;">Отправить</div>
</body>
</html>
С какими трудностями пришлось столкнуться?
Как я писал выше, важно правильно настроить OpenServer. Из за того, что у меня стояли настройки сервера:
— Apache 2.2
— PHP-5.3
Apache рушился с ошибкой:
Имя события проблемы: APPCRASH
Имя приложения: httpd.exe
Версия приложения: 2.2.31.0
Отметка времени приложения: 55a77942
Имя модуля с ошибкой: LIBEAY32.dll
Версия модуля с ошибкой: 1.0.1.16
Отметка времени модуля с ошибкой: 55a2477e
Код исключения: c0000005
Смещение исключения: 000409ab
Версия ОС: 6.1.7601.2.1.0.256.1
Код языка: 1049
Дополнительные сведения 1: 0a9e
Дополнительные сведения 2: 0a9e372d3b4ad19135b953a78882e789
Дополнительные сведения 3: 0a9e
Дополнительные сведения 4: 0a9e372d3b4ad19135b953a78882e789
Если закомментировать функцию openssl_private_decrypt(), то Apache не рушился, наверно из за нее, не зря эта функция не задокументирована, как пишут в справочниках по php «вы ее используете на свой страх и риск»!
Еще важно знать! Как я прочитал тут на Хабре, что при ключе 512-bit, мы можем зашифровать 53 байта, как я понимаю это можно использовать 53 символа, например если вы в поля для ввода пароля задали максимальную длину 60 и пользователь ввел все 60 символов, то произойдет ошибка. Если я не прав, поправьте меня в комментариях пожалуйста.
На этом все друзья, конечно статья не раскрыла все секреты RSA шифрования, но надеюсь она помогла тем, кто не мог понять принцип ее работы и тем кто хотел реализовать несложную, безопасную передачу данных.
Всем защиты и безопасной передачи данных, уважаемые Хабровчане!
Автор: djasonx