This commit is contained in:
jude 2023-04-24 15:56:34 +01:00
parent f4020aadec
commit 29e7e2c11a
3 changed files with 246 additions and 48 deletions

View File

@ -411,3 +411,17 @@ doi={10.1109/SP.2014.36}}
numpages = {11},
series = {CRYPTO '87}
}
@InProceedings{randomoracle,
author="Pointcheval, David
and Stern, Jacques",
editor="Maurer, Ueli",
title="Security Proofs for Signature Schemes",
booktitle="Advances in Cryptology --- EUROCRYPT '96",
year="1996",
publisher="Springer Berlin Heidelberg",
address="Berlin, Heidelberg",
pages="387--398",
abstract="In this paper, we address the question of providing security proofs for signature schemes in the so-called random oracle model [1]. In particular, we establish the generality of this technique against adaptively chosen message attacks. Our main application achieves such a security proof for a slight variant of the El Gamal signature scheme [4] where committed values are hashed together with the message. This is a rather surprising result since the original El Gamal is, as RSA [11], subject to existential forgery.",
isbn="978-3-540-68339-1"
}

Binary file not shown.

View File

@ -183,7 +183,7 @@ The final point describes a proof as being \textit{computationally zero-knowledg
Some proofs described are \emph{honest-verifier} zero-knowledge proofs. In these circumstances, the verifier is required to act in accordance with the protocol for the simulator distribution to behave as expected. This imposes a significant issue: a malicious verifier may intentionally produce challenges that reveal more information.
One solution to this is to transform a proof into a non-interactive zero-knowledge proof. The Fiat-Shamir transformation \cite{fiatshamir} converts an interactive zero-knowledge proof into a non-interactive zero-knowledge proof. In this process, the ability for a verifier to behave maliciously is lost, as the verifier no longer produces challenges themselves. This relies strongly upon the random-oracle model however. %todo cite
One solution to this is to transform a proof into a non-interactive zero-knowledge proof. The Fiat-Shamir transformation \cite{fiatshamir} converts an interactive zero-knowledge proof into a non-interactive zero-knowledge proof. In this process, the ability for a verifier to behave maliciously is lost, as the verifier no longer produces challenges themselves. This relies strongly upon the random-oracle model however \cite{randomoracle}.
As the random-oracle model is not realistically attainable, it must be approximated, typically by a cryptographic hash function. This introduces greater ability for the prover to cheat if they know a preimage in the hash function used.
\subsubsection{Games as graphs}
@ -275,10 +275,6 @@ The Fiat-Shamir heuristic \cite{fiatshamir} provides another method to reduce co
The downside of using the Fiat-Shamir heuristic in our implementation is that any third party can verify proofs. In some situations, we do not want this to be the case.
\subsubsection{Set membership proofs}
Another approach to the problem is to use set membership, which is a widely considered problem in zero-proof literature. In this case, each region would be associated with a set of units from a public "pool" of units. Then, a player needs to prove the cardinality of a set, and the uniqueness/distinctness of its members. A number of constructs exist for analysing and proving in obscured sets.
\chapter{Implementation}
The implementation provided uses WebSockets as the communication primitive. This is therefore a centralised implementation. However, no verification occurs in the server code, which instead simply "echoes" messages received to all connected clients.
@ -575,9 +571,23 @@ As this protocol must run many times during a game, we consider each operation o
\section{Proof system}
The first proof to discuss is the honest-verifier protocol to prove knowledge that a ciphertext is an encryption of zero \cite[Section~5.2]{damgard2003}.
Players should prove a number of properties of their game state to each other to ensure fair play. These are as follows. \begin{enumerate}
\item The number of reinforcements placed during the first stage of a turn.
The proof system presented is a Schnorr-style interactive proof for a given ciphertext $c$ being an encryption of zero.
\item The number of units on a region neighbouring another player.
\item The number of units available for an attack/defence.
\item The number of units lost during an attack/defence (including total depletion of units and loss of the region).
\item The number of units moved when fortifying.
\end{enumerate}
These points are referenced in the following sections.
\subsection{Proof of zero}
The first proof to discuss is the honest-verifier protocol to prove knowledge that a ciphertext is an encryption of zero \cite[Section~5.2]{damgard2003}.
\begin{center}
\begin{tikzpicture}[every node/.append style={very thick,rounded corners=0.1mm}]
@ -607,33 +617,7 @@ The proof system presented is a Schnorr-style interactive proof for a given ciph
A proof for the following homologous problem can be trivially constructed: given some ciphertext $c = g^mr^n \mod n^2$, prove that the text $cg^{-m} \mod n^2$ is an encryption of 0. The text $cg^{-m}$ is constructed by the verifier. The prover then proceeds with the proof as normal, since $cg^{-m}$ is an encryption of 0 under the same noise as the encryption of $m$ given.
\subsection{Implementation details}
Proofs of zero use messages labelled as \texttt{"PROOF"} to resolve, and resolve between two parties. The proof is initiated by the verifier as part of the game protocol, who sends a request containing the region to prove. Initiating proofs on the verifier side has benefits to synchronisation, and helps to reduce race conditions, as the proof is only requested after the verifier has updated their state.
The prover responds with the fields \texttt{conjecture: int} and \texttt{a: str} (where \texttt{a} is the serialisation of a \texttt{BigInt} representing \texttt{a} and \texttt{conjecture} is the proposed plaintext).
The prover then waits on an event listener to respond to the verifier's challenge in a non-blocking way when received.
The verifier receives the message above, and responds with a random challenge selected by generating a cryptographically secure pseudorandom number of 2048 bits. The verifier then waits on an event listener to receive the prover's proof.
Verifying the proof is a simple application of extended Euclidean algorithm to check coprimality, and a modular exponentiation and reduction to check the final equivalence. The ciphertext on the verifier's instance is then tagged with the proven plaintext (should the proof succeed). This tag is removed in the case that the ciphertext is updated.
\subsection{Application to domain}
Players should prove a number of properties of their game state to each other to ensure fair play. These are as follows. \begin{enumerate}
\item The number of reinforcements placed during the first stage of a turn.
\item The number of units on a region neighbouring another player.
\item The number of units available for an attack/defence.
\item The number of units lost during an attack/defence (including total depletion of units and loss of the region).
\item The number of units moved when fortifying.
\end{enumerate}
(2) and (4) are both covered by the proof above. (3) is okay between two players, as it is a subcase of (2). But in the case of more players, the availability of units should be proven. One way to achieve this is with a range proof. Similarly, (5) requires guarantees that the number of units moved is valid, which can be performed as a range proof.
This is used in point (2), as one player can then convince a neighbour in zero-knowledge of the number of units within their region.
\subsection{Range proof}
@ -643,13 +627,103 @@ Through selection of specific private inputs, a prover can create a proof for a
An alternative approach that is in zero-knowledge with acceptable soundness/completeness is to use a set membership proof for a set of all allowable values. This requires too much processing to be effective in this application however.
\subsection{Cheating with negative values}
The range proof is used in points (3), (4), and (5). In (3), this is to convince other players that the number of units is sufficient for the action. In (4), this is to show that the region is not totally depleted. In (5), this is to ensure the number of units being fortified is less than the strength of the region.
Using just the additive homomorphic property to guarantee (1) opens up the ability for a player to cheat by using negative values. This is a severe issue, as potentially the cheat could be completely unnoticed even in the conclusion of the game. To overcome this, we want a new protocol that is still in zero-knowledge, but proves a different property of a player's move.
\subsection{Proving reinforcement}
One consideration is to use a range proof as above. The full proof would then be the combination of a proof that the sum of all ciphertexts is 1, and the range of each ciphertext is as tight as possible, which is within the range $[0, 3]$. This is acceptable in the specific application, however we can achieve a better proof that is similar in operation to \cite{Boudot2000EfficientPT}.
We now need to consider point (1). One option is to prove that the sum of the committed values is 1 by using the additive homomorphic property. However, this allows a player to cheat by using negative values. To overcome this, we want a new protocol that is still in zero-knowledge, but proves additional properties of a reinforce action.
Instead of proving a value is within a range, the prover will demonstrate that a bijection exists between the elements in the reinforcement set and a challenge set.
\begin{figure}[htp]
\centering
\begin{tikzpicture}
\tikzstyle{style}=[circle,minimum size=15mm,draw=black,fill=white]
\node (im1) {\begin{tikzpicture}
\node[style] (A) at (-1.5, 3) {$n_1$};
\node[style] (B) at (-3, 0) {$n_2$};
\node[style] (C) at (0, 0) {$n_3$};
\node[style] (D) at (1.5, 3) {$n_4$};
\path[draw] (A) -- (C) -- (B) -- (A);
\path[draw] (A) -- (D);
\end{tikzpicture}};
\node (im2) at (0.5\textwidth, 0) {\begin{tikzpicture}
\node[style,label=center:$n_1 + 0$] (A) at (-1.5, 3) {};
\node[style,label=center:$n_2 + 0$] (B) at (-3, 0) {};
\node[style,label=center:$n_3 + 1$] (C) at (0, 0) {};
\node[style,label=center:$n_4 + 0$] (D) at (1.5, 3) {};
\path[draw] (A) -- (C) -- (B) -- (A);
\path[draw] (A) -- (D);
\end{tikzpicture}};
\path[draw,->,very thick] (im1) -- (im2);
\end{tikzpicture}
\caption{Example state change from reinforce action.}
\end{figure}
\begin{figure}[H]
\centering
\begin{tikzpicture}
\tikzstyle{style}=[circle,draw=black,minimum size=10mm,fill=white]
\node[anchor=north,black!40!green] at (-0.5, -0.75) {Valid};
\node[style] (A) at (-1, 2) {$0$};
\node[style] (B) at (-2, 0) {$+1$};
\node[style] (C) at (0, 0) {$0$};
\node[style] (D) at (1, 2) {$0$};
\path[draw] (A) -- (C) -- (B) -- (A);
\path[draw] (A) -- (D);
\end{tikzpicture}
\begin{tikzpicture}
\tikzstyle{style}=[circle,draw=black,minimum size=10mm,fill=white]
\node[anchor=north,black!40!green] at (-0.5, -0.75) {Valid};
\node[style] (A) at (-1, 2) {$0$};
\node[style] (B) at (-2, 0) {$0$};
\node[style] (C) at (0, 0) {$0$};
\node[style] (D) at (1, 2) {$+1$};
\path[draw] (A) -- (C) -- (B) -- (A);
\path[draw] (A) -- (D);
\end{tikzpicture}
\begin{tikzpicture}
\tikzstyle{style}=[circle,draw=black,minimum size=10mm,fill=white]
\node[anchor=north,black!40!red] at (-0.5, -0.75) {Invalid};
\node[style] (A) at (-1, 2) {$+1$};
\node[style] (B) at (-2, 0) {$+1$};
\node[style] (C) at (0, 0) {$0$};
\node[style] (D) at (1, 2) {$0$};
\path[draw] (A) -- (C) -- (B) -- (A);
\path[draw] (A) -- (D);
\end{tikzpicture}
\begin{tikzpicture}
\tikzstyle{style}=[circle,draw=black,minimum size=10mm,fill=white]
\node[anchor=north,black!40!red] at (-0.5, -0.75) {Invalid};
\node[style] (A) at (-1, 2) {$0$};
\node[style] (B) at (-2, 0) {$+2$};
\node[style] (C) at (0, 0) {$-1$};
\node[style] (D) at (1, 2) {$0$};
\path[draw] (A) -- (C) -- (B) -- (A);
\path[draw] (A) -- (D);
\end{tikzpicture}
\caption{Valid and invalid reinforce messages. Notably, the final invalid message would not be caught by the additive homomorphic check.}
\end{figure}
One consideration is to use a range proof. The full proof would then be the combination of a proof that the sum of all ciphertexts is 1, and the range of each ciphertext is as tight as possible. This requires a large amount of rounds though, and still has the issue of soundness/completeness.
Instead of proving a value is within a range, the prover will demonstrate that a bijection exists between the elements in the reinforcement set and a known "good" set.
\begin{protocol}\label{protocol1}
The prover transmits the set \begin{align*}
@ -676,37 +750,147 @@ This protocol has the following properties, given that the proof of zero from be
\item \textbf{Zero-knowledge.} Supposing each $\psi$, $r_i$, and $r_i^*$ are generated in a truly random manner, the verifier gains no additional knowledge of the prover's private state.
\end{itemize}
Additionally, we can consider this protocol perfect zero-knowledge.
Additionally, this protocol is perfectly simulatable.
\begin{proposition}
In the random-oracle and honest-verifier models, \hyperref[protocol1]{Protocol~\ref*{protocol1}} is perfect zero-knowledge.
\hyperref[protocol1]{Protocol~\ref*{protocol1}} is perfectly simulatable in the random-oracle model.
\end{proposition}
\begin{proof}
To prove perfect zero-knowledge, we require a polynomial-time algorithm $T^*$ such that for all verifiers and for all valid sets $S$, the set of transcripts $T(P, V, S) = T^*(S)$, and the distributions are identical.
To prove perfect simulation, we require a polynomial-time algorithm $T^*$ such that for all verifiers and for all valid sets $S$, the set of transcripts $T(P, V, S) = T^*(S)$, and the distributions are identical.
Such a $T^*$ can be defined for any $S$. \begin{enumerate}
\item Choose a random $\psi'$ from the random oracle.
\item Choose random $(r_i^*)'$ from the random oracle.
\item Encrypt under $P$'s public-key.
\item Verifier picks $c$ as before.
\item Perform proofs of zero, which are also perfect zero-knowledge under the honest-verifier assumption \cite[Lemma~3]{damgard2003}.
\item Perform proofs of zero, which are also perfect simulation \cite[Lemma~3]{damgard2003}.
\end{enumerate}
This gives $T^*$ such that $T^*(S) = T(P, V, S)$, and the output distributions are identical. Hence, this proof is perfect zero-knowledge under random oracle model.
This gives $T^*$ such that $T^*(S) = T(P, V, S)$, and the output distributions are identical. Hence, this proof is perfectly simulatable under random oracle model.
\end{proof}
In reality, as we are using Jurik's form of Paillier, the best we can hope for is computational zero-knowledge, as Jurik's form relies upon the computational indistinguishability of the sequence generated by powers of $h$ to random powers.
This is as close to perfect zero-knowledge as we can get due to the honest-verifier condition of the zero proof.
In practice, as we are using Jurik's form of Paillier, the best we can hope for is computational zero-knowledge. This is because Jurik's form relies upon the computational indistinguishability of the sequence generated by powers of $h$ to random powers.
\subsection{Proving fortifications}
Performing a "fortify" action is distinct to the "reinforce" action and requires its own verification.
More work is needed on point (5). The range proof alone only works to prevent negative values from appearing in a fortify action. Fortify actions need to be of form $\{ k, -k, 0, \dots, 0 \}$) and the regions corresponding to $k, -k$ amounts must be adjacent.
Firstly, the set being proven on changes form to $k, -k, 0, \dots, 0$, for a movement of $k$ units from one region to another. The challenges then change form to be proving that either these sum to zero, or that all but two are zero, with the remaining pair summing to zero (this appropriately hides the true value of $k$).
\begin{figure}[htp]
\centering
\begin{tikzpicture}
\tikzstyle{style}=[circle,minimum size=15mm,draw=black,fill=white]
\node (im1) {\begin{tikzpicture}
\node[style] (A) at (-1.5, 3) {$n_1$};
\node[style] (B) at (-3, 0) {$n_2$};
\node[style] (C) at (0, 0) {$n_3$};
\node[style] (D) at (1.5, 3) {$n_4$};
\path[draw] (A) -- (C) -- (B) -- (A);
\path[draw] (A) -- (D);
\end{tikzpicture}};
\node (im2) at (0.5\textwidth, 0) {\begin{tikzpicture}
\node[style,label=center:$n_1 + k$] (A) at (-1.5, 3) {};
\node[style,label=center:$n_2 + 0$] (B) at (-3, 0) {};
\node[style,label=center:$n_3 - k$] (C) at (0, 0) {};
\node[style,label=center:$n_4 + 0$] (D) at (1.5, 3) {};
\path[draw] (A) -- (C) -- (B) -- (A);
\path[draw] (A) -- (D);
\end{tikzpicture}};
\path[draw,->,very thick] (im1) -- (im2);
\end{tikzpicture}
\caption{Example state change from fortify action.}
\end{figure}
\begin{figure}[H]
\centering
\begin{tikzpicture}
\tikzstyle{style}=[circle,draw=black,minimum size=10mm,fill=white]
\node[anchor=north,black!40!green] at (-0.5, -0.75) {Valid};
\node[style] (A) at (-1, 2) {$0$};
\node[style] (B) at (-2, 0) {$+k$};
\node[style] (C) at (0, 0) {$-k$};
\node[style] (D) at (1, 2) {$0$};
\path[draw] (A) -- (C) -- (B) -- (A);
\path[draw] (A) -- (D);
\end{tikzpicture}
\begin{tikzpicture}
\tikzstyle{style}=[circle,draw=black,minimum size=10mm,fill=white]
\node[anchor=north,black!40!green] at (-0.5, -0.75) {Valid};
\node[style] (A) at (-1, 2) {$-k$};
\node[style] (B) at (-2, 0) {$0$};
\node[style] (C) at (0, 0) {$+k$};
\node[style] (D) at (1, 2) {$0$};
\path[draw] (A) -- (C) -- (B) -- (A);
\path[draw] (A) -- (D);
\end{tikzpicture}
\begin{tikzpicture}
\tikzstyle{style}=[circle,draw=black,minimum size=10mm,fill=white]
\node[anchor=north,black!40!red] at (-0.5, -0.75) {Invalid};
\node[style] (A) at (-1, 2) {$0$};
\node[style] (B) at (-2, 0) {$+k$};
\node[style] (C) at (0, 0) {$0$};
\node[style] (D) at (1, 2) {$-k$};
\path[draw] (A) -- (C) -- (B) -- (A);
\path[draw] (A) -- (D);
\end{tikzpicture}
\begin{tikzpicture}
\tikzstyle{style}=[circle,draw=black,minimum size=10mm,fill=white]
\node[anchor=north,black!40!red] at (-0.5, -0.75) {Invalid};
\node at (1, 1) {$k_1 \neq k_2$};
\node[style] (A) at (-1, 2) {$0$};
\node[style,label=center:$+k_1$] (B) at (-2, 0) {};
\node[style,label=center:$-k_2$] (C) at (0, 0) {};
\node[style] (D) at (1, 2) {$0$};
\path[draw] (A) -- (C) -- (B) -- (A);
\path[draw] (A) -- (D);
\end{tikzpicture}
\caption{Valid and invalid fortify messages.}
\end{figure}
We combine some ideas from the graph isomorphism proofs with ideas from before to get the following protocol.
\begin{protocol}\label{protocol3}
The prover transmits the set \begin{align*}
S = \{ (R_1, E(k, r_1)), (R_2, E(-k, r_2)), (R_3, E(0, r_3)) \dots, (R_N, E(0, r_N)) \}
\end{align*} as their fortify message.
Run $t$ times in parallel:
\begin{enumerate}
\item Prover transmits $\{ (\psi(R_i), E(n_i, r_i^*)) \mid 0 < i \leq N \}$ where $\psi$ is a random bijection on the regions.
\item Verifier chooses a random $c \in \{0, 1\}$. \begin{enumerate}
\item If $c = 0$, the verifier requests the definition of $\psi$. They then compute the product of the $E(x, r_i) \cdot E(x, r_i^*)$ and verify proofs that each of these is zero.
\item If $c = 1$, the verifier requests a proof that each $E(n_i, r_i^*)$ is as claimed.
\end{enumerate}
\end{enumerate}
\end{protocol}
\subsection{Optimising}
It is preferred that these proofs can be performed with only a few communications: this issue is particularly prevalent here as this protocol requires multiple rounds to complete. The independence of each round on the next is a beneficial property, as it means the proof can be performed in parallel, so the prover transmits \textit{all} of their $\psi$'s, then the verifier transmits all of their challenges. However, still is the issue of performing proofs of zero.
It is preferred that these proofs can be performed with only a few communications: this issue is particularly prevalent for protocols requiring multiple rounds to complete. The independence of each round on the next means the proof can be performed in parallel, so the prover computes all of their private state, then the verifier computes all of their challenges. However, still is the issue of performing proofs of zero.
We can apply the Fiat-Shamir heuristic to make proofs of zero non-interactive \cite{fiatshamir}. In place of a random oracle, we use a cryptographic hash function. We take the hash of some public parameters to prevent cheating by searching for some values that hash in a preferable manner. In this case, selecting $e = H(g, m, a)$ is a valid choice. To get a hash of desired length, an extendable output function such as SHAKE256 can be used \cite{FIPS202}. The library jsSHA \cite{jssha} provides an implementation of SHAKE256 that works within a browser.