Drc rsa что это
RSA, а так ли все просто?
Прелюдия
Немного теории
Для того чтобы понять почему крайне не рекомендуется использовать RSA в его наиболее простой форме сперва отметим следующее требование, выдвигаемое к асимметричным криптосистемам.
Требование 1:
Современная асимметричная криптосистема может(но это еще не факт) считаться стойкой, если злоумышленник, имея два открытых текста M1 и M2, а также один шифротекст Cb не может с вероятностью большей, чем 0.5 определить какому из двух открытых текстов соответствует шифротекст Cb.
Посмотрим, удовлетворяет ли RSA данному требованию. Итак, представим, злоумышленник Мэлори прослушивает переписку Алисы и Боба. В один чудесный для себя день он видит, что Боб в открытом виде задал Алисе очень важный вопрос, знание ответа на который обогатит, ну или, по крайней мере, безмерно потешит любопытство Мэлори. Алиса односложно отвечает Бобу на этот вопрос личного характера. Она шифрует свой ответ открытым ключом Боба и отправляет шифротекст. Далее Мэлори перехватывает шифротекст и подозревает, что в нем зашифровано либо «Да», либо «Нет». Всё, что ему теперь нужно сделать для того чтобы узнать ответ Алисы это зашифровать открытым ключом Боба слово «Да» и если полученный криптотекст совпадет с перехваченным, то это означает, что Алиса ответила «Да», в противном же случает злоумышленник поймет, что ответом было «Нет».
Как видно из этого, пускай несколько надуманного, но все же не столь и утопичного примера, RSA не столь надежна как это принято считать. Да конечно, можно сказать, что Алиса сама дура и никто ее не просил отвечать на такой серьезный для нее вопрос односложно. Так что же теперь запретить использование односложных ответов в криптографии? Конечно, нет. Все не так плохо, достаточно чтобы алгоритм добавлял к тексту некоторую случайную информацию, которую бы невозможно было предугадать и коварный Мэлори будет бессилен. Ведь, в самом деле, не сможет же он предсказать, что ответ «Да» после обработки алгоритмом превратится, например, в «Да4FE6DA54», а следовательно и зашифровать это сообщение он не сможет и нечего ему будет сравнивать с перехваченным криптотекстом.
Таким образом, уже сейчас можно сказать, что RSA во всех своих проявлениях будь то PGP или SSL не шифрует только отправленные на вход шифрующей функции данные. Алгоритм сперва добавляет к этим данным блоки содержащие случайный набор бит. И только после этого полученный результат шифруется. Т.е. вместо привычной всем
C=M E (mod N)
получаем более близкую к действительности
C=(M||Rand) E (mod N),
где Rand случайное число.
Такую методику называют схемами дополнения. В настоящее время использование RSA без схем дополнения является не столько плохим тоном, сколько непосредственно нарушением стандартов.
Но это далеко не все. Считается, что даже если криптоситема удовлетворяет сформулированному выше требованию, это еще не доказывает ее пригодность в практических целях. Сформулируем еще одно требование к стойкости асимметричного алгоритма.
Требование 2:
Пусть злоумышленник имеет доступ к расшифровывающему «черному ящику». Т.е. любой криптотекст по просьбе злоумышленника может быть расшифрован. Далее злоумышленник создает два открытых текста M1 и M2. Один из этих текстов шифруется и полученный в результате криптотекст Cb возвращается злоумышленнику. Задача злоумышленника угадать с вероятностью большей чем 0.5 какому из сообщений M1 и M2 соответсвует криптотекст Cb. При этом он может попросить расшифровать любое сообщение, кроме Cb(в противном случае игра не имеет смысла). Говорят что криптосистема стойкая, если злоумышленник, даже в таких прекрасных для себя условиях, не сможет указать какому исходному тексту соответствует Cb с вероятностью большей 0.5.
В свете вышесказанного посмотрим как с этим обстоят дела в RSA.
Итак, злоумышленник имеет два сообщения M1 и M2. А также криптотекст
Cb=M1 E (mod N).
Ему необходимо указать какому конкретно из двух текстов соответствует Cb. Для этого он может предпринять следующее. Зная открытый ключ E, он может создать сообщение
C’=2 E *Cb(mod N).
Далее он просит расшифровывающий «черный ящик» расшифровать сообщение C’. А затем несложная арифметика ему в помощь. Имеем:
M’=C’ D (mod N)=2 ED *M1 ED (mod N)=2*M1(mod N).
Т.е. вычислив M’/2 злоумышленник увидит M1. А это означает, что он поймет что в нашем примере было зашифровано сообщение M1, а следовательно мы еще раз убедились в неприемлемости использования RSA в его наивном виде на практике.
Устранить и эту неприятность помогают схемы дополнения. Только теперь к ним выдвигается требование не только о том, чтобы дополнительная информация была абсолютно случайной и непрогнозируемой. Но так же и том, чтобы дополнительные блоки помогали определить был ли шифротекст получен в результате работы шифрующей функции или он смоделирован злоумышленником. Причем в случае, если будет обнаружено, что шифротекст смоделирован вместо расшифрованных данных атакующему будет выдано сообщение о несоответствие данных реальному криптотексту.
Казалось бы, реализация такой схемы дополнения является труднорешаемой задачей, но ведь в криптографии уже есть готовый инструмент контроля целостности данных. Конечно же, это хеш-функции. Все современные схемы дополнений реализованы на идее применения хеш-функции в качестве проверки расшифрованных данных на подлинность.
В RSA при подписи и при шифровании данных используют две различные схемы дополнений. Схема, реализуемая для подписания документов, называется RSA-PSS(probabilistic signature scheme) или вероятностная схема подписи. Схема, используемая при шифровании – RSA-OAEP(Optimal asymmetric encryption padding) или оптимизированное асимметричное дополнение шифрования, на примере OAEP и рассмотрим как на самом деле происходит шифрование сообщений в RSA.
RSA-OAEP
Заключение
Т.е. RSA это не только возведение в степень по модулю большого числа. Это еще и добавление избыточных данных позволяющих реализовать дополнительную защиту вашей информации. Вы, возможно, спросите: а зачем это все нужно? Неужели в действительности может произойти такая ситуация, когда атакующий получит доступ к расшифровывающему алгоритму? Совсем по другому поводу как-то было сказано: если какая-либо неприятность может произойти, она обязательно произойдет. Только вот с использованием схем дополнений это уже не будет считаться неприятностью.
upd: перенес в блог криптография.
upd2:
Литература и ссылки:
1. Н. Фергюссон, Б. Шнайер «Практическая криптография»
2. Н. Смарт «Криптография»
3. Спецификация RSA-OAEP(pdf)
RSA: от простых чисел до электронной подписи
Выясняем, как и откуда можно получить электронную подпись на примере криптосистемы RSA.
Содержание
Определения и обозначения
Описание криптосистемы RSA
Асимметричные криптографические системы
Шифрование и дешифрование
Получение подписи сообщения по RSA
Электронная подпись документов
Введение
Наверняка вы сталкивались с таким понятием, как «электронная подпись». Если обратиться к федеральному закону, то можно найти следующее её определение:
Задача ЭП ясна, теперь хотелось бы увидеть и прочувствовать, что именно скрывается за этими двумя словами. Копаясь дальше в гугле, можно найти довольно много различных алгоритмов создания цифровой подписи (DSA, ГОСТ Р 34.10-2012, RSA-PSS и т.д.), разбираться в которых неподготовленному пользователю сложно.
Спасти эту ситуацию и помочь разобраться в том, что есть ЭП, может криптосистема RSA, разработанная Ривестом, Шамиром и Адлеманом в 1978 году. Она не загромождена безумным количеством алгоритмов и основывается на относительно простой математике. В связи с этим можно шаг за шагом прийти от модульной арифметики к алгоритму создания электронной подписи, чему я и хочу посвятить данную статью.
Теорминимум
Сформируем небольшой словарик терминов, которые нам пригодятся далее:
Открытый текст – данные, подлежащие шифрованию или полученные в результате расшифрования
Шифртекст – данные, полученные в результате применения шифра к открытому тексту
Шифр – совокупность обратимых преобразований, зависящая от некоторого параметра (ключа)
Ключ – параметр шифра, определяющий выбор одного преобразования из совокупности.
Факторизация – процесс разложения числа на простые множители.
НОД – наибольший общий делитель.
Числа a и b называются взаимно простыми, если НОД этих чисел равен 1.
Функция Эйлера φ(n) – функция, равная количеству натуральных чисел, меньших n и взаимно простых с ним.
Хочу отметить, что на данном этапе подразумевается, что вы знакомы с арифметическими операциями по модулю. Если нет, то здесь можно о них почитать.
Как оно устроено
Прежде, чем окунуться в необъятный мир математики рассмотреть, как именно устроена RSA, обратимся к тому, как работают
Асимметричные криптосистемы
Рассмотрим задачу сохранности содержимого посылки при передаче от отправителя к адресату. Вот картинка с многим полюбившимся Алисой и Бобом:
Алиса хочет передать Бобу посылку. Для начала Боб на своей стороне создает уникальные замок и ключ к нему (открытый и закрытый ключ соответственно). Далее, Боб делится с окружающим миром своим замком, чтобы любой желающий отправить ему посылку смог её закрыть. Поскольку ключ от подобного замка один и находится только у Боба, никто, кроме Боба, просмотреть содержимое после защёлкивания замка не сможет. В конце концов, Алиса с помощью полученного замка закрывает посылку и передаёт Бобу, который открывает её своим ключом. Таким образом устроены асимметричные криптографические системы, которой как раз является RSA.
В схеме передачи посылки все объекты вполне материальны. Однако сообщения, которые мы хотим шифровать, являются ничем иным, как последовательностью бит, которую нельзя «закрыть» на физический замок. Таким образом возникают вопросы: что такое ключ и замок? Как Бобу создать ключи? Каким образом ключи связаны и как с их помощью зашифровать сообщение? Здесь нам поможет математика.
Теперь к математике
Асимметричные криптографические системы основаны на так называемых односторонних функциях с секретом. Под односторонней понимается такая функция я y=f(x), которая легко вычисляется при имеющемся x, но аргумент x при заданном значении функции вычислить сложно. Аналогично, односторонней функцией с секретом называется функция y=f(x, k), которая легко вычисляется при заданном x, причём при заданном секрете k аргумент x по заданному y восстановить просто, а при неизвестном k – сложно.
Подобным свойством обладает операция возведения числа в степень по модулю:
Здесь φ(n) – функция Эйлера числа n. Пока условимся, что это работает, далее это будет доказано более строго. Теперь нужно понять, что из это является ключами Боба, а что сообщением. В нашем распоряжении имеются числа c, m, n, e, d.
Давайте посмотрим на первое выражение. Здесь число c получено в результате возведения в степень по модулю числа m. Назовём это действие шифрованием. Тогда становится очевидно, что m выступает в роли открытого текста, а c – шифртекста. Результат c зависит от степени e, в которую мы возводим m, и от модуля n, по которому мы получаем результат шифрования. Эту пару чисел (e, n) мы будем называть открытым ключом. Им Алиса будет шифровать сообщение.
Смотрим на второе действие. Здесь d является параметром, с помощью которого мы получаем исходный текст m из шифртекста c. Этот параметр мы назовём закрытым ключом и выдадим его Бобу, чтобы он смог расшифровать сообщение Алисы.
Что есть что разобрались, теперь перейдём к конкретике, а именно – генерации ключей Боба. Давайте выберем число n такое, что:
где p и q – некоторые разные простые числа. Для такого n функция Эйлера имеет вид:
Такой выбор n обусловлен следующим. Как вы могли заметить ранее, закрытый ключ d можно получить, зная открытый e. Зная числа p и q, вычислить функцию Эйлера не является вычислительно сложной задачей, ровно как и нахождение обратного элемента по модулю. Однако в открытом ключе указано именно число n. Таким образом, чтобы вычислить значение функции Эйлера от n (а затем получить закрытый ключ), необходимо решить задачу факторизации, которая является вычислительно сложной задачей для больших n (в современных системах, основанных на RSA, n имеет длину 2048 бит).
Возвращаемся к генерации ключей. Выберем целое число e:
Для него вычислим число d:
Для отыскания числа, обратного по модулю, можно воспользоваться алгоритмом Евклида.
Мы завершили с этапом генерации ключей. Теперь Боб публикует свой открытый ключ (e, n), прячет закрытый d, а мы переходим к Алисе.
Шифруем, дешифруем.
Возьмём в качестве сообщения число m (m ∈ [1, n − 1]). Чтобы Алисе зашифровать его, необходимо возвести его в степень e по модулю n. Эти числа идут вместе с открытым ключом Боба:
Здесь за с обозначен шифртекст, который Алиса будет должна передать Бобу. Отметим также, что c ∈ [1, n − 1], как и m. Расшифруем шифртекст, возведя его в степень закрытого ключа Боба d:
Здесь нам понадобится теорема Эйлера:
Также полезной будет китайская теорема об остатках:
Получаем подпись сообщения
Ещё раз напишем две ключевые формулы шифрования и расшифрования соответственно:
Теперь давайте предположим, что Боб хочет отправить Алисе открытку m от своего имени. У Боба в распоряжении уже имеются два ключа (e, n) и d, которые он сгенерировал по алгоритму, описанному ранее. Поскольку d является закрытым ключом, то можно им воспользоваться как уникальным идентификатором Боба. Давайте «зашифруем» m с помощью d:
Результат данной операции и есть подпись сообщения Боба. Заметим, что подпись напрямую зависит от подписываемого сообщения, а не только от того, что его подписывает Боб. Далее, Алиса получает сообщение m, подпись s и открытый ключ (e, n). По аналогии с расшифрованием, проверка подписи осуществляется возведением подписи s в степень открытой экспоненты e:
Если Алиса получила, что m ≡ m′, то подпись считается правильной.
Дочитавших до этого места хочу поздравить с получением первой цифровой подписи «на бумаге»!
Подпись документов
Рассмотренный алгоритм получения подписи изящен и прост в осознании, однако операция возведения в степень несколько «мешается». Наша текущая задача – подписать объёмный документ. Чтобы сэкономить время, мы не будем подписывать содержимое документа, а прибегнем к помощи хэш-функций (если вы не знаете, что такое хэш-функция, рекомендую почитать википедию). Скажу лишь то, что выходная последовательность хэш-функции имеет небольшую (по сравнению с размером ключей) длину, а также по имеющемуся хэшу нельзя однозначно восстановить исходные данные.
На картинках наглядно показано, в какой момент мы используем хэширование. Создание подписи:
В качестве хэш-функции можно использовать SHA-256, как это сделано, например, в PGP. По теме практического создания электронной подписи с использованием PGP на хабре уже написана статья, поэтому на этом месте имеет смысл поставить точку и перейти к заключению.
Заключение
Вот мы и прошли все стадии создания электронной подписи, начиная с простой модульной арифметики и заканчивая, собственно, получением подписи. Обладая этими знаниями, вы можете попробовать перевести их на ваш любимый язык программирования и написать свою защищенную аську, например. В том, как именно их применить, вас ограничит только ваше воображение.
Отмечу, что другие существующие алгоритмы создания ЭП основаны на схожих принципах, поэтому надеюсь, что после прочтения этой статьи вам будет проще разобраться в них. «Следующей по сложности» я обозначу криптосистему Эль-Гамаля, но о ней уже не в этом посте.
Спасибо за внимание!
Источники
Handbook of Applied Cryptography by A. Menezes, P. van Oorschot and S. Vanstone
Криптографические методы защиты информации: учеб. пособие / С. М. Владимиров, Э. М. Габидулин, А. И. Колыбельников, А. С. Кшевецкий; под ред. А. В. Уривского. – М.: МФТИ, 2016
Маховенко Е. Б. Теоретико-числовые методы в криптографии — М.: Гелиос АРВ, 2006.
NIST Special Publication 800-57 Part 3 Revision 1
Реализация алгоритма RSA в архитектуре «клиент-сервер»
Возникновение потребности
Данная статья посвящена одной из проблем, с которой я столкнулся при разработке собственного проекта. Проект имеет клиент-серверную архитектуру, и представляет собой бизнес-приложение. Практически первым вопросом после реализации передачи данных по сети и построения каркаса, возникла необходимость шифрования передаваемых данных. Первым возможным алгоритмом (планирует поддержка нескольких) был выбран алгоритм шифрования RSA.
В статье будут рассмотрены варианты реализации алгоритма RSA на клиент-серверной архитектуре, и пример такой реализации в реальном проекте.
Концепция алгоритма RSA
Данная концепция представлена на рисунке №1, изображенном выше.
Как Вы видите, ключ после генерации синим персонажем передается зеленому персонажу по незащищенному каналу в открытом виде. Его может перехватить кто угодно, но с его помощью можно только зашифровать сообщение.
Поэтому зеленый персонаж легко получает открытый ключ и производит шифрование своего сообщения с помощью данного ключа.
В пределах двух человек схема довольно-таки простая. Однако, если необходимо организовать такую систему на архитектуре клиент-сервер, возникает ряд дополнительных вопросов, которые мы рассмотрим ниже.
Клиент — сервер
Итак, для начала определимся с ключами. Как вы помните, для зашифровки сообщений необходим открытый ключ получателя. Соответственно, серверу необходим открытый ключ клиента, а клиенту – открытый ключ сервера. Следовательно, перед началом передачи данных, необходимо произвести обмен ключами. Как это происходит, рассмотрим на рисунке №2, в котором представлен процесс обмена ключами.
Обмен завершен в три этапа. Теперь как у сервера, так и у клиента имеется открытый ключ собеседника «на том конце линии». Однако тут сразу необходимо выбрать одно из двух решений поводу того, как сервер будет генерировать ключи для своих клиентов:
1. Сервер генерирует один ключ для всех клиентов ;
2. Сервер генерирует новый ключ для каждого отдельного клиента ;
Я думаю, каждый из Вас знает, что чем больше ключ, тем больше его практическая полезность. Однако, в случае алгоритма RSA, генерация ключа – не такая уж и простая задача, поскольку она представляет основную вычислительную сложность. К тому же, алгоритм устроен таким образом, что чем больше ключ, тем больший объем данных необходимо будет передавать.
К примеру, при передаче сообщения длиной 5 байт, и используя ключ длиной 512 бит, зашифрованное сообщение будет «весить» 64кбайт. Это связано с тем, что максимальный объем данных, который можно зашифровать таким ключом, равен 64-11=53 кбайт (11кбайт используется для битовых сдвигов). Если необходимо зашифровать больше – разбиваем на блоки по 53 кбайт. А если взять ключ = 4096 бит, то минимальный блок будет равен 512кбайт, несмотря на то, что мы зашифровываем всего-то 5 байтов.
Следовательно, необходимо решить:
У каждого могут быть свои взгляды на тот счет, какой вариант предпочесть, да и многое тут зависит от разрабатываемого продукта. Однако в данном проекте было решено использовать второй вариант.
Генерация и отправка ключа серверу
В нашем проекте используется трехуровневая архитектура: клиент-сервер-база данных. Сервер написан на Java, клиент — на C#. Ниже я буду описывать реализацию шифрования как на серверной части, так и на клиентской. Начнем именно с пользователя — клиента.
Далее необходимо сохранить открытый ключ в байтовом формате и отправить серверу. Для этого необходимо немного разобраться в том, из чего состоят ключи RSA. Если кратко – то они состоят из так называемых открытых и секретных экспонент и единого для обоих ключей модуля. Соответственно, открытый ключ – это открытая экспонента и модуль, закрытый ключ — закрытая экспонента и модуль. Подробнее можно прочитать здесь в главе «Алгоритм создания открытого и секретного ключей».
Записываем открытую экспоненту в буфер вывода (C#):
В данном случае длина экспоненты нужна нам для того, чтобы знать, где именно заканчивается экспонента и начинается модуль (при считывании данных на сервере). После записи отправляем данные серверу.
После того, как сервер принял пакет с ключом, необходимо забрать ключ из пакета и сохранить его. Смотрим (Java):
Думаю, здесь не нужно особо еще комментировать код, разве что странную строку, названную мною «магией вуду» :), где мы выставляем первый байт модуля равным нулю. А дело вот в чем – по неизвестным мне причинам реализация RSA в Java требует, чтобы модуль ключа всегда начинался с нуля. Возможно, это связано с тем, чтобы иметь модуль > 0, т.к. когда я пытался сам реализовать RSA на Java с использованием больших чисел (BigInteger), при неравенстве первого байта нулю получалось отрицательное число. Данный вопрос оставляю Вам, господа Хабравчане, буду очень рад, если кто-нибудь объяснит эту особенность.
Далее идет генерация ключа сервером. Рассмотрим следующий кусок кода (Java):
Думаю, тут все понятно. Хотя, конечно, если углубляться, то обязательно надо погуглить на тему таких существ, как X509 и PKCS8 (X509EncodedKeySpec и PKCS8EncodedKeySpec).
Следующим этапом является отправка ключей серверу. Производится это практически так же, как и в случае клиента (Java):
И наконец, получаем ключ на стороне клиента, считываем и сохраняем его (C#):
В случае сервера немного посложнее (Java):
Зашифрованное сообщение готово к отправке и расшифровке у получателя с помощью закрытого ключа. Единственное, о чем не стоит забывать — это то, что максимальный размер сообщения, которое может быть зашифровано, равно размерю ключа минус 11 байт. Поэтому при шифровке необходимо делить данные на блоки и шифровать их поочереди. Вот пример на C#:
На Java реализуете сами, там изменений — пара строк 🙂
Конечно, в рамках данной статьи я не смогу охватить весь объем реализации данного функционала, но, я думаю, теперь Вы точно имеете представление о том, как реализовать защищенный канал для своих клиентов с помощью алгоритма RSA.