From ea3102c95848f7ee86dfe2081d4a711d37add7d3 Mon Sep 17 00:00:00 2001
From: Andrew Guschin <guschin.drew@gmail.com>
Date: Thu, 19 May 2022 16:08:23 +0400
Subject: Add latex report

---
 report/coursework.tex | 498 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 498 insertions(+)
 create mode 100644 report/coursework.tex

(limited to 'report/coursework.tex')

diff --git a/report/coursework.tex b/report/coursework.tex
new file mode 100644
index 0000000..3821166
--- /dev/null
+++ b/report/coursework.tex
@@ -0,0 +1,498 @@
+\documentclass[spec, och, coursework]{SCWorks}
+\usepackage{preamble}
+
+
+\begin{document}
+\include{titlepage.tex}
+\tableofcontents
+
+
+\intro
+Для безопасного ведения корреспонденции в Интернете необходимы способы 
+подтверждения авторства того или иного пользователя для каждого сообщения.
+Методы, используемые для реализации таких систем взаимодействия зачастую
+намного более надёжные, чем системы общения с помощью физических бумажных
+носителей. Такая надёжность достигается с помощью использования современных
+криптографических протоколов, взлом которых является крайне неэффективной
+задачей.
+
+Основной схемой подтверждения авторства какого-либо сообщения является
+\textit{Электронная цифровая подпись}. При подписи сообщения по такой схеме
+используется сразу несколько криптографических протоколов, обеспечивающих
+надёжность подписи.
+
+Для реализации алгоритмов цифровой подписи обычно используется два
+криптографических алгоритма:
+\begin{itemize}
+    \item 
+        Хэш-функции --- односторонние функции, которые однозначно преобразуют
+        сообщение произвольной длины в сообщение фиксированной длины;
+    \item
+        Системы с открытым ключом --- системы ассиметричного шифрования,
+        которые позволяют надёжно защитить электронную подпись от подделки.
+\end{itemize}
+
+Системы, в которых используется какой-либо вид цифровой подписи способны
+распознать любые попытки компрометации сообщений любого своего пользователя.
+
+
+\section{Хэширование}
+В основе алгоритмов цифровой подписи обычно используется какая-либо 
+односторонняя хэш-фунцкция в том или ином виде.
+
+Хэш-функция определена для сообщений любой длины, при этом в результате 
+получается хэш некоторой фиксированной длины. То есть $h = H(M)$, где 
+$H$ -- некоторая хэш-функция, $M$ -- некоторое сообщение, а $h$ -- хэш 
+сообщения, полученный с помощью функции $H$. При этом хэш-функции обладают 
+дополнительными свойствами, которые обеспечивают полезность таких функций 
+в крипографии:
+
+\begin{itemize}
+    \item Для данного $M$ легко вычислить $h$;
+    \item Для данного $h$ сложно вычислить такое $M$, что $H(M) = h$;
+    \item Для данного $M$ сложно найти другое такое $M'$, что $H(M) = H(M')$.
+\end{itemize}
+
+На практике, для реализации односторонних хэш-функций используется идея функции
+сжатия. В результате применения такой функции получается значение длины $n$, 
+меньшее длины $m$ исходного сообщения. В качестве параметров односторонняя
+функция сжатия принимает часть сообщения и хэш-значение всех предыдущих блоков,
+полученных по данному алгоритму. Таким образом хэш текущей части сообщения $M_i$
+вычисляется по формуле \[ h_i = f(M_i, h_{i - 1}) \].
+
+Это значение становится одним из параметров для вычисления хэша для следующего
+блока сообщения. Хэшем всего сообщения является хэш последнего блока. 
+\cite{scheiner-applied}
+
+Наиболее известными алгоритмами хэширования являются MD5 и SHA, разработанные
+в 1991 и 1995 году соответственно. На данный момент оба алгоритма считаются
+небезопасными для определённых целей, но на их примере можно рассмотреть 
+практическую реализацию и применение односторонних хэш-функций.
+
+
+\subsection{MD5}
+Алгоритм MD5 основан является улучшенной версией предшествующего алгоритма MD4.
+Они cхожи по дизайну, хотя MD5 является несколько более сложным. Эти алгоритмы 
+обрабатывают данное сообщение блоким по 512 бит, которые в свою очередь
+разбиты на 16 32-битных подблоков. В результате их исполнения в обоих случаях 
+получается хэш длины 128 бит, который получается конкатенацией четырёх
+32-битных блоков.
+
+Перед применением непосредственно алгоритма хэширования MD5 предварительно 
+обрабатывает сообщение. Суть обработки состоит в том, что сообщение дополняется
+так, что его длина была на 64 бита меньше числа, кратного 512. Дополнение
+состоит из одного единичного бита, за которым следует необходимое количество 
+нулей. После этого в конце добавляется 64-битное представление длины сообщения
+(до дополнения). Таким образом, в резултате получается сообщение, длина которого
+кратна 512 битам.
+
+Следующим шагом будет установка начальных значений четырёх \textit{цепных 
+переменных}. Они получают следующие значения:
+\begin{align*}
+    A &= \texttt{01234567}_{16} \\
+    B &= \texttt{89abcdef}_{16} \\
+    C &= \texttt{fedcba98}_{16} \\
+    D &= \texttt{76542210}_{16}
+\end{align*}
+
+Эти значения копируются в новые временные переменные $a = A$, $b = B$, $c = C$, 
+$d = D$.
+
+Алгоритм обрабатывает изначальное сообщения по циклам, при этом в каждом цикле
+обрабатывается свой 512-битный блок. Каждый цикл разделён на 4 раунда, в каждом
+из который используется своя нелинейная функция
+\begin{align*}
+    F(x, y, z) &= (x \land y) \lor (\neg x \land z) \\
+    G(x, y, z) &= (x \land z) \lor (\neg z \land y) \\
+    H(x, y, z) &= x \oplus y \oplus z \\
+    I(x, y, z) &= y \oplus (x \lor \neg z)
+\end{align*}
+
+Для обработки $j$-го 32-битного подблока $M_j$ вводятся ещё четыре операции для
+каждого из четырёх раундов:
+\begin{align*}
+    FF(a, b, c, d, M_j, s, t_i) &= (a = b + ((a + F(b, c, d) + M_j + t_i) <<< s)) \\
+    GG(a, b, c, d, M_j, s, t_i) &= (a = b + ((a + G(b, c, d) + M_j + t_i) <<< s)) \\
+    HH(a, b, c, d, M_j, s, t_i) &= (a = b + ((a + H(b, c, d) + M_j + t_i) <<< s)) \\
+    II(a, b, c, d, M_j, s, t_i) &= (a = b + ((a + I(b, c, d) + M_j + t_i) <<< s))
+\end{align*}
+
+Каждая итерация состоит из 64 шагов по 16 шагов на раунд. Для шагов 
+$i = \overline{1,64}$ константа $t_i = \left[2^{32} \cdot |\sin(i)|\right]$. 
+После выполнения всех шагов алгоритма, изменённые значения $a$, $b$, $c$, $d$ 
+прибавляются к $A$, $B$, $C$, $D$ и алгоритм повторяется для следующего блока 
+сообщения. Результат получается после выполнения алгоритма на последнем блоке и
+конкатенации $A$, $B$, $C$ и $D$.
+
+Операции каждого раунда MD5 можно посмотреть в приложении $?$.
+\cite{scheiner-applied}
+
+
+\subsection{Secure Hash Algorithm}
+Алгоритм хэширования SHA (или SHA-1) в общих чертах схож с алгоритмом MD4,
+но в нём присутствуют дополнительные изменения, которые делают его более
+криптостойким.
+\begin{enumerate}
+    \item 
+        Более длинная 160-битная длина хэша из-за использования пяти цепных
+        переменных вместо четырёх;
+    \item
+        В SHA используется 4 раунда, как и в MD5, но при этом в четвёртом
+        раунде используется такая же функция, как и во втором;
+    \item Количество шагов алгоритма увеличено с 64 до 80;
+    \item 
+        Количество числовых констант уменьшено до четырёх, каждая из которых
+        является общей для одного из раундов алгоритма, вместо уникальной
+        константы для каждого шага алгоритма;
+    \item Изменён набор нелинейных функций.
+\end{enumerate}
+
+Как и в MD5 первым шагом является установка начальных значений цепных 
+переменных:
+\[ A = \texttt{67452301}_{16} \]
+\[ B = \texttt{efcdab89}_{16} \]
+\[ C = \texttt{98badcfe}_{16} \]
+\[ D = \texttt{10325476}_{16} \]
+\[ E = \texttt{c3d2e1f0}_{16} \]
+
+На каждой итерации алгоритма обрабатывается очередной блок исходного сообщения.
+Значения цепных переменных копируются в новые переменные $a = A$, $b = B$,
+$c = C$, $d = D$, $e = E$.
+
+Набор нелинейных функций у SHA следующий:
+\begin{align*}
+    f_t(x, y, z) &= (x \land y) \lor (\neg x \land z), \, \text{для } t = \overline{0, 19} \\
+    f_t(x, y, z) &= x \oplus y \oplus z, \, \text{для } t = \overline{20, 39} \\
+    f_t(x, y, z) &= (x \land y) \lor (x \land z) \lor (y \land z), \, \text{для } t = \overline{40, 59} \\
+    f_t(x, y, z) &= x \oplus y \oplus z, \, \text{для } t = \overline{60, 79}
+\end{align*}
+
+Обрабатываемый блок сообщения преобразуется из 16 32-битных слов ($M_i, \,
+i = \overline{0, 15}$) в 80 32-битных слов ($W_i, \, i = \overline{0, 79}$)
+по следующему алгоритму:
+\begin{align*}
+    W_t &= M_t, \, \text{для } t = \overline{0, 15} \\
+    W_t &= (W_{t - 3} \oplus W_{t - 8} \oplus W_{t - 14} \oplus W_{t - 16}) <<< 1, \, \text{для } t = \overline{16, 79} 
+\end{align*}
+
+Для четырёх раундов используются следующие числовые константы:
+\begin{align*}
+    K_t &= \left[\frac{\sqrt{2}}{4}  \cdot 2^{32}\right] = \texttt{5a827999}_{16}, \, \text{для } t = \overline{0, 19} \\
+    K_t &= \left[\frac{\sqrt{3}}{4}  \cdot 2^{32}\right] = \texttt{6ed9eba1}_{16}, \, \text{для } t = \overline{20, 39} \\
+    K_t &= \left[\frac{\sqrt{5}}{4}  \cdot 2^{32}\right] = \texttt{8f1bbcdc}_{16}, \, \text{для } t = \overline{40, 59} \\
+    K_t &= \left[\frac{\sqrt{10}}{4} \cdot 2^{32}\right] = \texttt{ca62c1d6}_{16}, \, \text{для } t = \overline{60, 79} \\
+\end{align*}
+
+Основной цикл алгоритма:
+\begin{minted}{basic}
+    for t = 0 to 79
+        tmp = (a <<< 5) + f_t(b, c, d) + e + W_t + K_t
+        e = d
+        d = c
+        c = b <<< 30
+        b = a
+        a = tmp
+\end{minted}
+
+Далее переменные $a$, $b$, $c$, $d$ и $e$ прибавляются к $A$, $B$, $C$, $D$ 
+и $E$ соответственно. Результатом всего алгоритма является конкатенация
+$A$, $B$, $C$, $D$ и $E$ после выполнения его для всех блоков исходного 
+сообщения.
+
+\section{Ассиметричное шифрование}
+В системах шифрования с открытым ключом (ассиметричных системах шифрования)
+каждый из пользователей обладает некоторым ключом $k$, состоящим из
+открытого ключа $k_o$, который определяет правило шифрования $E_k$, 
+и закрытого ключа $k_p$, который определяет правило расшифрования $D_k$. 
+Эти правила связаны соотношением
+\[ E_k(M) = C, \, D_k(C) = M \]
+где $M$ --- любой открытый текст, $C$ --- шифротекст. \cite{alferov}
+
+Для отправки конфиденциального сообщения от пользователя B пользователю A,
+следует использовать следующий алгоритм:
+\begin{enumerate}
+    \item Пользователь B запрашивает у пользователя A копию открытого ключа $k_o$;
+    \item Пользователь B вычисляет шифротекст $C = E_k(M)$ для своего сообщения $M$;
+    \item 
+        Пользователь A получает шифротекст $C$ и расшифровывает его с помощью
+        своего закрытого ключа $k_p$, чтобы получить зашифрованное сообщение
+        $M = D_k(C)$.
+\end{enumerate}
+
+Системы шифрования с открытым ключом осуществляют блочное шифрование, поэтому
+текст исходного сообщения перед началом алгоритма шифрования разбивается на
+блоки необходимого размера, которые затем последовательно преобразуются.
+Ассиметричные системы обычно обеспечивают значительно меньшие скорости 
+шифрования, чем симметричные системы из-за чего из зачастую используют только
+для передачи ключей пользователей, которые затем используются в симметричных
+системах шифрования.
+
+\subsection{RSA}
+Для обеспечения шифрования в алгоритме RSA используется факт того, что
+имея два достаточно больших простых числа можно легко найти их произведение, 
+но имея произведение двух простых чисел нет простого способа найти его 
+разложение на множители \cite{encyclopedia}. Пусть $n = p \cdot q$ --- целое 
+число, представимое в виде произведения
+двух больших простых числел $p$ и $q$. Выберем два числа $e$ и $d$ из условия
+\[ e \cdot d \equiv 1 (\text{mod } \varphi(n)) \]
+где $\varphi(n) = (p - 1) \cdot (q - 1)$ --- значение функции Эйлера от числа
+$n$.
+
+Пусть $k = (n, p, q, e, d)$ --- некоторый выбранный ключ, который состоит из
+открытого ключа $k_o = (n, e)$ и закрытого ключа $k_p = (n, p, q, d)$.
+Тогда правила шифрования и расшифрования для некоторого сообщения $M$ и
+шифротекста $C$ определяются следующими формулами:
+\[ C = E_k(M) = M^e (\text{mod } n), \, D_k(C) = C^d (\text{mod } n) = M\]
+
+Нетрудно продемонстрировать, что сложность нахождения секретного ключа RSA
+определяется сложностью факторизации числа $n$. Поэтому для создания ключа
+следует использовать достаочно длинные простые числа, на которые также
+можно наложить дополнительные требования для усложнения задачи:
+\begin{enumerate}
+    \item 
+        Числа $p$ и $q$ должны не слишком сильно отличаться друг от друга, но
+        и не быть слишком близкими друг к другу;
+    \item
+        Следует подобрать такие два таких числа, что наибольший общий делитель
+        чисел $p - 1$ и $q - 1$ был небольшим (желательно, равным 2);
+    \item
+        $p$ и $q$ должны быть сильно простыми числами, т. е. следующее 
+        число имеет большой простой делитель и предыдущее число тоже имеет
+        такой большой простой делитель $s$, что $s - 1$ также обладает
+        достаточно большим простым делителем.
+\end{enumerate}
+
+\section{Электронная цифровая подпись}
+Цифровая подпись является некоторым числом, которое зависит от исходного 
+сообщения и некоторого закрытого ключа. С помощью цифровой подписи можно
+решить три важных задачи при обмене сообщениями:
+\begin{itemize}
+    \item аутентификация источника сообщения;
+    \item установление целостности сообщения;
+    \item обеспечение невозможности отказа от факта подписи конкретного сообщения.
+\end{itemize}
+
+Надёжность схемы цифровой подписи определяется сложностью выполнения следующих
+задач:
+\begin{itemize}
+    \item 
+        Подделка подписи (нахождение значения подписи под заданным
+        сообщением лицом, не являющимся владельцем секретного ключа);
+    \item 
+        Создание подписанного сообщения (нахождения хотя бы одного сообщения
+        с правильным значением подписи);
+    \item Подмена сообщения (подбор двух различных сообщений с одинаковой подписью).
+\end{itemize}
+
+Для создания цифровой подписи можно использовать алгоритмы шифрования с открытым
+ключом, так как они обеспечивают невозможность подделки сообщения. Предположим, 
+что имеется некоторая пара преобразований $(E_k, D_k)$, где $E_k$
+зависит от открытого ключа $k_o$, а $D_k$ --- от закрытого $k_p$. Цифровую
+подпись $S$ сообщения $M$ можно вычислить с помощью преобразования $D_k(M) = S$.
+Таким образом, полученную подпись любой другой пользователь сможет проверить
+с помощью известного ему преобразования $E_k(S) = M$ и получить исходное
+сообщение.
+
+Проблема такого подхода заключается в том, что для такой системы подписи не
+выполняется требование невозможности создания подписанного сообщения,
+так как для любого $S_1$ любой пользователь может вычислить $M_1 = E_k(S_1)$
+и получить подписанное сообщение. 
+
+Для решения этой проблемы зачастую в систему подписи также включается некоторая
+хэш-функция $h$, которая перед подписью применяется к сообщению. 
+Но так как по хэшу сообщения невозможно восстановить само сообщение, подпись 
+должна отправляться вместе с сообщением. Создание подписи по такой схеме 
+удовлетворяет всем трём требованиям для надёжности цифровой подписи. 
+\cite{alferov}
+
+\subsection{Правовая сторона применения ЭЦП в России}
+В российском Федеральном Законе \textnumero 63 электронные цифровые подписи
+подразделяются на три вида:
+\begin{enumerate}
+    \item 
+        Простая электронная подпись --- подпись, которая с помощью определённых
+        криптографических протоколов позволяет подтвердить факт формирования
+        подписи определённым лицом;
+    \item 
+        Неквалифицированная электронная подпись --- подпись, которая получена
+        в результате криптографического преобразования информации с
+        использованием ключа электронной подписи, позволяет определить лицо,
+        подписавшее электронный документ, позволяет обнаружить факт внесения
+        изменений в документ после его подписи;
+    \item 
+        Квалифицированная электронная подпись --- подпись, которая соответствует
+        всем техническим признакам неквалифицированной электронной подписи, но
+        при этом также имеет ключ проверки электронной подписи в 
+        квалифицированном сертификате, а также создана при помощи средств
+        электронной подписи, получивших подтверждение соответствия требованиям,
+        установленных в \textnumero 63-ФЗ.
+\end{enumerate}
+
+Электронные документы считаются равнозначными документам на бумажном носителе, 
+подписанном собственноручной подписью, если они подписаны квалифицированной 
+электронной подписью и соответствуют остальным требованиям \textnumero 63-ФЗ.
+
+Таким образом, электронные цифровые подписи, применяемые в разнообразных
+веб-приложениях для защиты от компрометации канала связи обычно не имеют 
+правовой силы на территории Российской Федерации.
+
+
+\section{Разработка системы с применением ЭЦП}
+В качестве системы, в которой необходимо применение электронной цифровой подписи
+мною была выбрана система мгновенного обмена сообщениями (чат). Для разработки
+данной системы я выбрал язык программирования Go, в стандартной библиотеке
+которого присутствуют все криптографические функции, необходимые для реализации
+данной системы. Для упрощения работы с чатом также были использованы две
+сторонние библиотеки:
+\begin{itemize}
+    \item 
+        \textbf{fyne.io}, для создания пользовательского интерфейса клиентской
+        части системы;
+    \item Реализация драйвера базы данных \textbf{sqlite3} для языка Go.
+\end{itemize}
+
+\subsection{Используемый алгоритм цифровой подписи}
+В качестве алгоритма шифрования с открытым ключом используется RSA, в качестве
+хэш-функции $h$ --- SHA-256, а также в процессе подписи к сообщению применяется
+алгоритм Base64.
+
+Алгоритм подписи:
+\begin{enumerate}
+    \item Генерируются открытый и закрытый ключи шифрования RSA;
+    \item Сообщение $M$ преобразуется с помощью алгоритма Base64 в $B_M$; 
+    \item Вычисляется хэш $H_M = h(B_M)$;
+    \item Хэш зашифровывется с помощью ключа $k_o$: $C_M = E_k(H_M)$;
+    \item 
+        Полученный шифротекст $C_M$ преобразуется в подпись $S_M$ с помощью
+        алгоритма Base64.
+\end{enumerate}
+
+Для отправки сообщения $M$ на сервер к нему дополнительно приставляется
+его подпись. Данные, отправляемые на сервер состоят из трёх частей,
+конкатенируемых перед отправкой:
+\begin{itemize}
+    \item Преобразованное с помощью алгоритма Base64 сообщение $M$;
+    \item Знак точки;
+    \item Цифровая подпись $S_M$.
+\end{itemize}
+
+При получении сообщения от клиента, сервер проверяет его подпись. Алгоритм
+проверки подписи:
+\begin{enumerate}
+    \item Полученное сообщение разделяется на $B_M$ и $S_M$;
+    \item $S_M$ декодируются с помощью алгоритма Base64 в шифротекст $C_M$;
+    \item Вычисляется хэш $H_M = h(B_M)$;
+    \item Шифротекст $C_M$ расшифровывается с помощью ключа $h_p$ в сообщение $H_S$;
+    \item Подпись считается валидной в случае, если $H_S = H_M$.
+\end{enumerate}
+
+\subsection{Реализация сервера приложения}
+Сервер приложения принимает сетевые запросы по прикладному протоколу $HTTP$.
+В сервере реализованы следующие точки входа:
+\begin{itemize}
+    \item 
+        \texttt{/api/register}: с помощью данной точки пользователь может внести
+        свой ключ проверки подписи в систему;
+    \item 
+        \texttt{/api/sendMessage}: все сообщения, которые сервер должен сохранить
+        в своей базе данных и передать другим пользователям системы отправляются
+        на эту точку входа;
+    \item
+        \texttt{/api/pollMessages}: с помощью данной точки входа пользователь
+        способен запросить все сообщения, которые пришли на сервер после
+        некоторого момента времени (который пользователь указывает в запросе);
+    \item
+        \texttt{/api/getUserKey}: для проверки подписи пришедшего сообщения 
+        на стороне клиента, пользователь может запросить ключ другого 
+        пользователя, сохранённый на сервере;
+    \item
+        \texttt{/api/tryAuth}: данная точка входа не выполняет никаких действий,
+        и реализована для удобства проверки возможности аутентификации 
+        пользователя на сервере (при удачной аутентификации данная точка
+        вернёт ответ со статусом HTTP 200, иначе, при провале аутентификации по
+        каким-либо причинам, статус будет не равен 200 и клиент может вывести
+        предупреждение пользователю).
+\end{itemize}
+
+\subsection{Работа с клиентом приложения}
+Для начала обмена сообщения с другими ползователями, подключенными к системе
+необходимо в неё войти, либо зарегистрироваться. Вход возможен только при
+наличии сгенерированного ключа для подписи, поэтому при первом запуске
+следует нажать на кнопку <<Зарегистрироваться>> (рис. \ref{fig:start}).
+\begin{figure}[H]
+    \centering
+    \includegraphics[width=0.7\textwidth]{screenshots/start.png}
+    \caption{Экран при запуске приложения}
+    \label{fig:start}
+\end{figure}
+
+При регистрации (и входе) необходимо ввести URL сервера, к которому должен
+присоединиться клиент и своё имя (рис. \ref{fig:register}). После этого 
+необходимо нажать на кнопку <<Сгенерировать ключи подписи>>.
+\begin{figure}[H]
+    \centering
+    \includegraphics[width=0.7\textwidth]{screenshots/register.png}
+    \caption{Окно регистрации}
+    \label{fig:register}
+\end{figure}
+
+Далее можно сохранить ключ в любом удобном месте с любым именем (рис. \ref{fig:key}).
+\begin{figure}[H]
+    \centering
+    \includegraphics[width=0.7\textwidth]{screenshots/key.png}
+    \caption{Выбор места для сохранения ключа}
+    \label{fig:key}
+\end{figure}
+
+После выбора места сохранения ключа необходимо нажать на кнопку 
+<<Зарегистрироваться>>, после чего клиент проверит возможность совершить
+это действие с указанными данными. Если клиент не может соединиться с сервером,
+либо на сервере уже зарегистрирован пользователь с таким именем, то клиент
+выведет окно с ошибкой (рис. \ref{fig:error}).
+\begin{figure}[H]
+    \centering
+    \includegraphics[width=0.7\textwidth]{screenshots/error.png}
+    \caption{Ошибка при регистрации}
+    \label{fig:error}
+\end{figure}
+
+Если клиенту удалось соединиться с сервером и успешно пройти все проверки, то
+для пользователя откроется окно чата, в котором можно написать своё сообщение
+в поле снизу. Для отправки сообщения необходимо нажать на кнопку <<Отправить>>
+(рис. \ref{fig:input}).
+\begin{figure}[H]
+    \centering
+    \includegraphics[width=0.7\textwidth]{screenshots/input.png}
+    \caption{Ввод сообщения}
+    \label{fig:input}
+\end{figure}
+
+Все сообщения, которые клиент смог получить от сервера отображаются в этом
+окне чата (рис. \ref{fig:chat}).
+\begin{figure}[H]
+    \centering
+    \includegraphics[width=0.7\textwidth]{screenshots/chat.png}
+    \caption{Окно чата с сообщением}
+    \label{fig:chat}
+\end{figure}
+
+
+\conclusion
+Для реализации систем электронных цифровых подписей обычно используются
+наиболее проверенные криптографически стойкие алгоритмы, которые способны
+обеспечить защищённость от компрометации канала связи между пользователями.
+
+Благодаря таким алгоритмам имеется возможность установления безопасного
+канала связи даже через Интернет, между людьми, которым сложно физически 
+обменяться ключами для проверки подписей.
+
+Но с увеличением мощности вычислительных компьютерных систем и разработкой
+квантовых компьютеров некоторые криптографические протоколы находятся
+под угрозой потери надёжности и безопасности. Поэтому можно ожидать появления
+новых алгоритмов шифрования, хэширования и электронной цифровой подписи,
+учитывающих новые разработки в сфере квантовых вычислений.
+
+
+\printbibliography
+
+\end{document}
-- 
cgit v1.2.3

