Реализация RSA класса на PHP

По ходу работы, я часто сталкиваюсь с интересными и неординарными задачами, в очередной раз такая задача была направленна на применение криптоалгоритма RSA (буквенная аббревиатура от фамилий Rivest, Shamir и Adleman). Описание RSA было опубликовано в августе 1977 года в журнале Scientific American.

Криптографические системы с открытым ключом используют однонаправленные функции, они обладают следующим свойством:
Если X известно, то функцию от X вычислить относительно просто
Если известно, что Y = функция от X, то для X нет простого пути вычисления
Под однонаправленностью понимается не теоретическая однонаправленость, а практическая невозможность вычислить обратное значение, применяя современные средства, за обозримый интервал времени.
В основу криптографической системы RSA положена задача умножения и разложения простых чисел на множители, которая является вычислительно однонаправленной задачей.
В криптографической системе с открытым ключом каждый располагает как открытым ключом (public key), так и секретным\приватным ключом (secret\private key). Каждый ключ — это часть информации. В криптографической системе RSA каждый ключ состоит из пары целых чисел. Каждый участник создаёт свой открытый и секретный ключ самостоятельно. Секретный ключ каждый из них держит в секрете, а открытые ключи можно сообщать кому угодно или даже публиковать их. Открытый и секретный ключи каждого участника обмена сообщениями образуют «согласованную пару» в том смысле, что они являются взаимно обратными.

На 2009 год система шифрования на основе RSA считается надёжной, начиная с размера N в 1024 бита.

Зная разложение модуля на произведение двух простых чисел, противник может легко найти секретную экспоненту d и тем самым взломать RSA. Однако на сегодняшний день самый быстрый алгоритм факторизации — решето обобщённого числового поля (General Number Field Sieve), скорость которого для k-битного целого числа не позволяет разложить большое целое за приемлемое время.

И теперь перейдем от теории к практике. Я не стал изобретать велосипед и взял уже готовый класс от Khaled Al-Sham’aa. Какие у него плюсы? Плюс один и очень большой – его класс легко читаем, и прост для изучения. В добавок прилагается пример и краткое описание принципа открытых ключей и теория RSA.

качаем тут -> Khaled Al-Sham’aa RSA Class PHP

Расмотрим пример:

тут мы подключаем класс и создаем его экземпляр

include('rsa.class.php');
$RSA = new RSA();


далее мы создаем пару ключей из исходных простых чисел (как их генерировать на лету я расскажу позже)

$keys = $RSA->generate_keys ('9990454949', '9990450271', 1);

тут мы видим пример шифрования и дешифрования фразы

$message="هذا نص عربي بتنسيق مجموعة المحارف العالمية";
$encoded = $RSA->encrypt ($message, $keys[1], $keys[0], 5);
$decoded = $RSA->decrypt ($encoded, $keys[2], $keys[0]);


также чуть ниже мы видим вывод сигнатуры закриптованного сообщения (с его помощью мы можем проверить правильно ли все работает)

$signature = $RSA->sign($message, $keys[1], $keys[0]);

собственно вот тут мы и проверяем подлинность (предварительно мы опредилили переменную $fake_msg которая отличается от переменной $message, но $signature осталась прежняя)

echo "Success: ".(($RSA->prove($fake_msg, $signature, $keys[2], $keys[0])) ? "True" : "False")."\n";

данный код выведет False

Если смотреть пример далее то мы можем увидеть, что в этом классе существует возможность шифровать и проверять файлы используя функции signFile и proveFile.

В принципе алгоритм рабочий. Однако я сделал небольшое усовершенствование зашифровав оба ключа base64_encode для лучшего восприятия, но это не все.

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

private function prime($n,$s=2) {
for ($i=$s;$i<=$n;$i++) {
$flag=true;
for ($k=2;$k*$k<=$i;$k++) {
if ($i%$k == 0) {
$flag=false;
break;
}
}
if ($flag==true) {
$ret[]=$i;
}
}
return $ret;
}


естественно это находится внутри класса

а при генерации ключей включил вот такой код

public function generate_keys ($show_debug=0){

do {
$sta=rand(1000,9999);
$ret=$this->prime(intval($sta.'22500'),intval($sta.'22000'));
$k=rand(0,count($ret));
$p=$ret[$k];
$k=rand(0,count($ret));
$q=$ret[$k];
} while (($p=='') OR ($q=='') OR ($p==$q));


что дает нам генерацию ключей с псевдослучайной рандомизацией.

Естественно этот класс и данный пример не подходят, когда нам нужно устойчивое шифрование, но ни что не мешает нам оптимизировать его.
Спасибо, что дочиталю до конца =) Был бы рад инвайту.
Tags:
php, RSA, асинхронное шифрование, криптография, открытый ключ

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