\documentclass[12pt,fleqn,a4paper]{book}
% 
% Packages used:
%
\usepackage[koi8-r]{inputenc}
\usepackage[russian,english]{babel}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsfonts}
\usepackage{amsthm}
\usepackage{fullpage}
%
% Common customization:
%
\pagestyle{headings}
\newtheorem{theorem}{Теорема}[chapter]
\newtheorem*{theorem*}{Теорема}
\newtheorem{lemma}{Лемма}[chapter]
\newtheorem{corollary}{Следствие}[chapter]
\newtheorem{proposition}{Утверждение}[chapter]
\newtheorem{fact}{Факт}[chapter]
\theoremstyle{definition}
\newtheorem{problem}{Задача}[chapter]
\newtheorem{exercise}{Упражнение}[chapter]
\newtheorem{example}{Пример}[chapter]
\newtheorem{definition}{Определение}[chapter]
\newtheorem{remark}{Замечание}[chapter]
\newtheorem{algorithm}{Алгоритм}[chapter]
\def\gap{\medskip\centerline{\fbox{\Huge\bfseries{ПРОБЕЛ В КОНСПЕКТЕ.}}}\medskip}
\advance\headheight by 7pt
\def\headsep{15mm}
\newcommand{\lecture}[2]{%
\def\rightmark{\fbox{\parbox{125mm}{\lecturername: \coursetitle%
\hfil\phantom{.}}}}
\def\leftmark{\fbox{\parbox{125mm}{Лекция {#1}. {#2}%
\hfil\phantom{.}}}}
\renewcommand\chaptername{Лекция}\renewcommand\thechapter{#1}\chapter{{#2}}\thispagestyle{headings}}
%
% Things to customize for the course are here:
%
\newcommand\lecturername{Э. А. Гирш}
\newcommand\coursetitle{``Информатика'' (отд. информатики, 1 курс)}
%
\newcommand{\SAT}{\mathtt{SAT}}
\newcommand{\RP}{\mathbf{RP}}
\newcommand{\sRP}{\widetilde{\mathbf{RP}}}
\newcommand{\NP}{\mathbf{NP}}
\newcommand{\sNP}{\widetilde{\mathbf{NP}}}
\newcommand{\UP}{\widetilde{\mathbf{UP}}}
\newcommand{\coNP}{\widetilde{\mathbf{co-NP}}}
\renewcommand{\P}{\mathbf{P}}
\newcommand{\sP}{\widetilde{\mathbf{P}}}
%
\newcommand{\Retc}{и\;т.\;д.}
\newcommand{\poly}{\mathrm{poly}}
%
\newcommand{\ournote}[1]{\ref{?}\footnote{#1}}
\renewcommand{\le}{\leqslant}
\renewcommand{\ge}{\geqslant}
\newcommand{\step}{\mathop{\longrightarrow}\limits}
%
\renewcommand\mod{\mathrm{mod}\ }
\newcommand\pri{\mathtt{pri}}
\newcommand\pub{\mathtt{pub}}
\newcommand\code{\mathtt{code}}
%
% The document
%
\begin{document}
\selectlanguage{russian}
\lecture{11}{Введение в криптографию с открытым ключом}
%
% The lecture
%
\section{Постановка задачи}

В криптографии существует множество задач, которые имеют широкую
область применения. Это и закрытая передача данных по открытым
каналам, и алгоритмы электронной подписи, и интерактивные
доказательства с нулевым разглашением, и многие другие.
Чтобы составить понятие об этой тематике,
в этой лекции мы поговорим
о так называемых <<протоколах шифрования с открытым ключом>>.
Задача состоит в следующем. Имеется читатель A и писатель B
(таких писателей может быть много). Проблема заключается в том,
чтобы передать данные от B к A в зашифрованном виде,
чтобы никто из тех, кто перехватит данные на
пути из B к A, не смог расшифровать их.  В начале
работы протокола у A и B нет никакой общей конфиденциальной
информации. Канал между A и B все время открыт, то есть читать из
него могут все желающие.

\section{Криптосистема с открытым ключом\protect\footnote{Public Key Encryption Scheme}}
Неформально, идея системы, которая бы позволила нам решить
поставленную задачу, состоит в следующем. Первоначально читатель A
создает пару ключей. Один ключ ($\pub$) публикуется. Он общедоступен
и называется открытым (публичным) ключом. Второй ключ ($\pri$) читатель оставляет
у себя и хранит в секрете. Этот ключ называется закрытым (личным,
секретным, приватным). Алгоритм кодирования устроен так, что любой может
закодировать сообщение, зная открытый ключ. Задача раскодирования
сообщения легко решается, если известен закрытый ключ ($\pri$). Если
противник не знает этого ключа, то раскодировать такое
сообщение ему будет крайне трудно; тем труднее, чем длиннее были
выбраны ключи $\pri$ и $\pub$.

\begin{definition}
С формальной точки зрения, криптосистема для шифрования с открытым ключом
состоит из трех алгоритмов, каждый их которых может использовать случайные
числа и заканчивает свою работу за время, математическое ожидание которого
полиномиально от длины входа. (Вероятность берется по используемым алгоритмом
случайным битам, но \underline{не} по входам алгоритма.)
\begin{description}
\item[Генератор ключей] ---
\[
G:1^k\mapsto (\pub,\pri)
\]
генерирует ключи <<сложности>> $k$ (для простоты можно представлять себе,
что $k$ --- <<длина>> ключа).
\item[Шифровальщик] ---
\[
E:(\pub, m)\mapsto \code.
\]
\item[Дешифровщик] ---
\[
D:(\pri, \code)\mapsto m.
\]
\end{description}
\end{definition}
От шифровальщика и дешифровщика, мы, естественно, должны
дополнительно потребовать, чтобы сообщения корректно расшифровывались,
то есть для любого сообщения $m$
вероятность события $D(E(m,\pub), \pri)\neq m$ не превосходит $1/2$
(естественно, мы можем уменьшить вероятность ошибки по приемлемой величины,
повторив пересылку многократно).
Здесь вероятность вновь берется по случайным битам, используемым
алгоритмами $D$, $E$ и $G$ (заметим, что $\pub$ и $\pri$ представляют
собой случайные переменные, порожденные $G$), но \underline{не} по входам
этих алгоритмов (т.е. \underline{не} по $m$ и \underline{не} по $k$).

\begin{remark}
Заметим, что мы ничего не сказали о \emph{надежности} криптосистемы.
Формальное определение понятия надежности слишком громоздко
и мы отложим его до соответствующих спец. курсов.
Неформально же можно сказать, что никакой полиномиальный по времени
алгоритм не должен уметь со сколько-нибудь существенной вероятностью успеха
расшифровывать сообщения, имея в распоряжении лишь $\pub$ и $\code$;
здесь вероятность уже берется не только по использованным случайным битам,
\underline{но и по зашифрованным сообщениям $m$}.
\end{remark}

\section{Пример: RSA}
В качестве примера
мы опишем самый простой и популярный алгоритм шифрования с открытым ключом, 
который называется RSA (по первым буквам фамилий его авторов:
Rivest, Shamir, Adleman). Эта (наиболее простая) версия алгоритма,
конечно, не является надежной,
но она служит базой для его многочисленных модификаций,
которые на самом деле применяются на практике.

\subsection{Совсем простая версия}
Итак выберем два очень больших (например, состоящих из не более,
чем $k/2$ битов, где $1^k$ --- вход генератора $G$) различных простых числа $p,q$.
Вычислим их произведение $n=pq$.
Выберем число $e$ так, чтобы $\mbox{НОД}(e,\phi(n))=1$
(вспомним, что функция Эйлера $\phi(n)=(p-1)(q-1)$ может быть легко
вычислена \emph{тем, кто знает $p$ и $q$}).
Далее, находим $d\in [1..n-1]$, такое, что $de\equiv1\ (\mod\phi(n))$.
Оно, очевидно, существует и единственно в силу того, что $\mbox{НОД}(e,\phi(n))=1$,
и может быть найдено при помощи алгоритма Евклида.
\begin{problem}
А подходящее $e$ как найти?
\end{problem}

Итак, мы описали генератор ключей $G$,
который выдает
публичный ключ $\pub=(e,n)$ и
приватный ключ $\pri=(d,n)$.
Разобьем сообщение на числа, не превосходящие $n$;
достаточно определить $E$ и $D$ на таких <<коротких>> сообщениях.
Функция кодирования 
$$
E((n,e),m)=m^e\ \mod n.
$$  
Для декодирования мы просто возводим код в степень $d$:
$$
D((n,d),c)=c^d\ \mod n.
$$
При этом 
по теореме Ферма-Эйлера\footnote{На лекции меня <<поймали>> на применении
теоремы Ферма-Эйлера в формулировке
\begin{theorem*}
Если разложение $n$ на простые множители не содержит квадратов,
то $$\forall x\ \forall k\ x^{k\mathop{\cdot}\phi(n)+1}\equiv x\ (\mod n).$$
\end{theorem*}
(Заметим, что здесь нет условия на взаимную простоту $x$ и $n$.)
Я не обнаружил ее в книге И.М.Виноградова;
вероятно, не появлялась она и в курсе теории чисел.
Тем не менее, она верна.
Ее доказательство является упражнением по теории чисел
(она следует из малой теоремы Ферма для простых $n$).}
$$
D((n,d),E((n,e),x)) \equiv
x^{ed}\equiv x^{k\mathop{\cdot}\phi(n)+1}\equiv x\ (\mod n).
$$
Мы видим, что зная $d$, 
мы можем запросто раскодировать сообщение за полиномиальное время;
однако, если $d$ неизвестно, непонятно, как это можно было бы сделать.

\subsection{Чуть более надежная версия}
Сразу видно несколько прорех в приведенной выше <<простой>> версии RSA.
\begin{enumerate}
\item Плохо такой версией шифровать биты:
      при $m=0$ и $m=1$ расшифровать полученный код
      всегда тривиально (он равен $m$).
\item Повторяемость: одинаковые сообщения имеют одинаковые коды;
      чтобы соперник этим не воспользовался,
      придется каждый раз выбирать новый ключ.
\item Мультипликативность: произведение кодов есть код произведения.
      Если мы случайно знаем два закодированных сообщения,
      сможем расшифровать и их произведение
      (либо же надо каждый раз выбирать новый ключ).
\end{enumerate}
Чуть более надежная версия выглядит так: разобьем сообщение на биты,
и для шифрования одного бита $b$
\begin{itemize}
\item выберем случайное число $r$ от $1$ до $n/2-1$;
\item зашифруем $2r+b$.
\end{itemize}
Иначе говоря,
\begin{eqnarray*}
\widetilde{E}((n,e),b) &=& E((n,e),2r+b),\\
\widetilde{D}((n,d),c) &=& D((n,d),c)\ \mod 2.
\end{eqnarray*}
Теперь шансы получить <<простой>> код мало зависят
от самого сообщения --- они зависят лишь от попавшихся нам случайных битов.

\section{Односторонние функции}
Увы, достаточные условия существования криптосистем с открытым ключом
(именно, существование так называемых функций <<с секретом>>)
слишком громоздки и не уместились в этом курсе.
(Более того, эти общие условия не влекут надежности конкретных криптосистем:
например, RSA.)
Однако мы можем сформулировать несколько необходимых условий.

\begin{definition}
\emph{Односторонней функцией} называется функция
\[
f:X\rightarrow Y,
\]
вычислимая за полиномиальное время,
обратная к которой не может быть вычислена\footnote{Более формальные
варианты этого определения см. чуть ниже.} за полиномиальное время.
(Обратная --- любая функция
\[
g:Y\rightarrow X,
\]
такая, что $\forall x\in X\ f(g(f(x)))=f(x)$.)
\end{definition}
\begin{remark}
Можно считать, что $X,Y=\{0,1\}^*$, хотя бывают и односторонние функции,
определенные не на всех строках.
\end{remark}

Вторая компонента ($\pub$) генератора ключей, очевидно, должна быть односторонней
функцией от используемых генератором случайных битов\footnote{Если при одном
и том же $k$ генератор время от времени использует разное количество
случайных битов, строчку случайных битов можно дополнить <<фиктивными>> битами
так, чтобы длина этой строки была лишь [монотонно строго возрастающей] функцией
от $k$; длину ключа $k$ можно вычислить по количеству этих битов.}
(в противном случае можно было
бы вычислить по $\pub$ случайные биты, а по ним --- $\pri$).
Это не единственная односторонняя функция, которую можно извлечь из криптосистемы.
\begin{exercise}
А какие еще?
\end{exercise}

\begin{definition}
Различают \emph{односторонние в наихудшем случае\footnote{worst-case one-way}}
и \emph{сильно односторонние\footnote{strongly one-way}} функции.

Для односторонних в наихудшем случае <<не может быть вычислена за
полиномиальное время>> означает <<не существует
полиномиального по времени алгоритма (не использующего случайные числа),
который по $f(x)$ вычисляет некоторую обратную функцию $g(f(x))$
для \emph{каждого} $x$>>.

Для сильно односторонних <<не может>> означает <<для любого полиномиального
по времени алгоритма $A$ (использующего случайные числа), для любого
полинома $q$, для достаточно больших $k$
\[
\mathbf{P}\{x\;|\;f(A(f(x)))=f(x)\} < \frac{1}{q(|x|)},
\]
где вероятность берется как по случайным битам, использованным алгоритмом $A$,
так и по случайным $x\in X$ длины $k$.>>
\end{definition}

\begin{remark}
Несложно показать, что
$\P\neq\NP$ тогда и только тогда, когда существуют функции,
односторонние в наихудшем случае.
\end{remark}

Имеются следующие следствия (первое из них мы также не будем доказывать,
так как не давали необходимых определений):

\bigskip
\noindent
$\exists$ надежное шифрование с открытым ключом $\Rightarrow$\\
$\exists$ сильно односторонние функции $\Rightarrow$\\
$\exists$ односторонние в наихудшем случае функции $\Leftrightarrow$\\
$\P\neq\NP$.

\bigskip
Имеются ли в первых двух случаях обратные следствия, неизвестно.

\end{document}

