diff --git a/ipa.sage b/ipa.sage index 56776f9..b6cee17 100644 --- a/ipa.sage +++ b/ipa.sage @@ -6,7 +6,7 @@ # IPA_bulletproofs implements the IPA version from the Bulletproofs paper: https://eprint.iacr.org/2017/1066.pdf # https://doc-internal.dalek.rs/bulletproofs/notes/inner_product_proof/index.html -class IPA_bulletproofs(object): +class IPA_bulletproofs: def __init__(self, F, E, g, d): self.g = g self.F = F @@ -89,7 +89,7 @@ class IPA_bulletproofs(object): return C == D # IPA_halo implements the modified IPA from the Halo paper: https://eprint.iacr.org/2019/1021.pdf -class IPA_halo(object): +class IPA_halo: def __init__(self, F, E, g, d): self.g = g self.F = F diff --git a/paper-notes.bib b/paper-notes.bib index d4f3845..983350e 100644 --- a/paper-notes.bib +++ b/paper-notes.bib @@ -31,3 +31,11 @@ note = {\url{https://eth2book.info/altair/part2/building_blocks/signatures}}, url = {https://eth2book.info/altair/part2/building_blocks/signatures} } +@misc{cryptoeprint:2019/1021, + author = {Sean Bowe and Jack Grigg and Daira Hopwood}, + title = {Recursive Proof Composition without a Trusted Setup}, + howpublished = {Cryptology ePrint Archive, Paper 2019/1021}, + year = {2019}, + note = {\url{https://eprint.iacr.org/2019/1021}}, + url = {https://eprint.iacr.org/2019/1021} +} diff --git a/paper-notes.pdf b/paper-notes.pdf index 14e8df5..6bcc9cd 100644 Binary files a/paper-notes.pdf and b/paper-notes.pdf differ diff --git a/paper-notes.tex b/paper-notes.tex index bc82071..f47a2d7 100644 --- a/paper-notes.tex +++ b/paper-notes.tex @@ -12,6 +12,7 @@ linkcolor=black, urlcolor=blue } +\usepackage{xcolor} % prevent warnings of underfull \hbox: \usepackage{etoolbox} @@ -224,17 +225,115 @@ Identical to verification of a normal signature as long as we use the same corre $$e(g_1, \sigma_{aggr})==e(pk_{aggr}, H(m))$$ Unfold: -$$e(pk_{aggr}, H(m))=e(pk_1 + pk_2 + \ldots + pk_n, H(m))=$$ +$$\fbox{e(pk_{aggr}, H(m))}= e(pk_1 + pk_2 + \ldots + pk_n, H(m)) =$$ $$=e([sk_1] \cdot g_1 + [sk_2] \cdot g_1 + \ldots + [sk_n] \cdot g_1, H(m))=$$ $$=e([sk_1 + sk_2 + \ldots + sk_n] \cdot g_1, H(m))=$$ $$=e(g_1, H(m))^{(sk_1 + sk_2 + \ldots + sk_n)}=$$ $$=e(g_1, [sk_1 + sk_2 + \ldots + sk_n] \cdot H(m))=$$ $$=e(g_1, [sk_1] \cdot H(m) + [sk_2] \cdot H(m) + \ldots + [sk_n] \cdot H(m))=$$ -$$=e(g_1, \sigma_1 + \sigma_2 + \ldots + \sigma_n)=e(g_1, \sigma_{aggr})$$ +$$=e(g_1, \sigma_1 + \sigma_2 + \ldots + \sigma_n)= \fbox{e(g_1, \sigma_{aggr})}$$ + +\section{modified IPA (from Halo)} +Notes taken while reading about the modified Inner Product Argument (IPA) from the Halo paper \cite{cryptoeprint:2019/1021}. + +\subsection{Notation} +\begin{description} + \item[Scalar mul] $[a]G$, where $a$ is a scalar and $G \in \mathbb{G}$ + \item[Inner product] $<\overrightarrow{a}, \overrightarrow{b}> = a_0 b_0 + a_1 b_1 + \ldots + a_{n-1} b_{n-1}$ + \item[Multiscalar mul] $<\overrightarrow{a}, \overrightarrow{b}> = [a_0] G_0 + [a_1] G_1 + \ldots [a_{n-1}] G_{n-1}$ +\end{description} + + +\subsection{Transparent setup} +$\overrightarrow{G} \in^r \mathbb{G}^d$, $H \in^r \mathbb{G}$ + +Prover wants to commit to $p(x)=a_0$ +\subsection{Protocol} +Prover: +$$P=<\overrightarrow{a}, \overrightarrow{G}> + [r]H$$ +$$v=<\overrightarrow{a}, \{1, x, x^2, \ldots, x^{d-1} \} >$$ + +where $\{1, x, x^2, \ldots, x^{d-1} \} = \overrightarrow{b}$. + +We can see that computing $v$ is the equivalent to evaluating $p(x)$ at $x$ ($p(x)=v$). + +We will prove: +\begin{enumerate}[i.] + \item polynomial $p(X) = \sum a_i X^i$\\ + $p(x) = v$ (that $p(X)$ evaluates $x$ to $v$). + \item $deg(p(X)) \leq d-1$ +\end{enumerate} + + +Both parties know $P$, point $x$ and claimed evaluation $v$. For $U \in^r \mathbb{G}$, + +$$P' = P + [v] U = <\overrightarrow{a}, G> + [r]H + [v] U$$ + +Now, for $k$ rounds ($d=2^k$, from $j=k$ to $j=1$): +\begin{itemize} + \item random blinding factors: $l_j, r_j \in \mathbb{F}_p$ + \item + $$L_j = < \overrightarrow{a}_{lo}, \overrightarrow{G}_{hi}> + [l_j] H + [< \overrightarrow{a}_{lo}, \overrightarrow{b}_{hi}>] U$$ + $$L_j = < \overrightarrow{a}_{lo}, \overrightarrow{G}_{hi}> + [l_j] H + [< \overrightarrow{a}_{lo}, \overrightarrow{b}_{hi}>] U$$ + \item Verifier sends random challenge $u_j \in \mathbb{I}$ + \item Prover computes the halved vectors for next round: + $$\overrightarrow{a} \leftarrow \overrightarrow{a}_{hi} \cdot u_j^{-1} + \overrightarrow{a}_{lo} \cdot u_j$$ + $$\overrightarrow{b} \leftarrow \overrightarrow{b}_{lo} \cdot u_j^{-1} + \overrightarrow{b}_{hi} \cdot u_j$$ + $$\overrightarrow{G} \leftarrow \overrightarrow{G}_{lo} \cdot u_j^{-1} + \overrightarrow{G}_{hi} \cdot u_j$$ +\end{itemize} + +After final round, $\overrightarrow{a}, \overrightarrow{b}, \overrightarrow{G}$ are each of length 1. + +Verifier can compute +$$G = \overrightarrow{G}_0 = < \overrightarrow{s}, \overrightarrow{G} >$$ +and $$b = \overrightarrow{b}_0 = < \overrightarrow{s}, \overrightarrow{b} >$$ +where $\overrightarrow{s}$ is the binary counting structure: + +\begin{align*} + &s = (u_1^{-1} ~ u_2^{-1} \cdots ~u_k^{-1},\\ + &~~~~~~u_1 ~~~ u_2^{-1} ~\cdots ~u_k^{-1},\\ + &~~~~~~u_1^{-1} ~~ u_2 ~~\cdots ~u_k^{-1},\\ + &~~~~~~~~~~~~~~\vdots\\ + &~~~~~~u_1 ~~~~ u_2 ~~\cdots ~u_k) +\end{align*} + + +And verifier checks: +$$[a]G + [r'] H + [ab] U == P' + \sum_{j=1}^k ( [u_j^2] L_j + [u_j^{-2}] R_j)$$ + +where the synthetic blinding factor $r'$ is $r' = r + \sum_{j=1}^k (l_j u_j^2 + r_j u_j^{-2})$. + +\vspace{1cm} + +Unfold: + +$$ +\textcolor{brown}{[a]G} + \textcolor{cyan}{[r'] H} + \textcolor{magenta}{[ab] U} +== +\textcolor{blue}{P'} + \sum_{j=1}^k ( \textcolor{violet}{[u_j^2] L_j} + \textcolor{orange}{[u_j^{-2}] R_j}) +$$ + +\begin{align*} +&Right~side = \textcolor{blue}{P'} + \sum_{j=1}^k ( \textcolor{violet}{[u_j^2] L_j} + \textcolor{orange}{[u_j^{-2}] R_j})\\ +&= \textcolor{blue}{< \overrightarrow{a}, \overrightarrow{G}> + [r] H + [v] U}\\ +&+ \sum_{j=1}^k (\\ +&\textcolor{violet}{[u_j^2] \cdot <\overrightarrow{a}_{lo}, \overrightarrow{G}_{hi}> + [l_j] H + [<\overrightarrow{a}_{lo}, \overrightarrow{b}_{hi}>] U}\\ +&\textcolor{orange}{+ [u_j^{-2}] \cdot <\overrightarrow{a}_{hi}, \overrightarrow{G}_{lo}> + [r_j] H + [<\overrightarrow{a}_{hi}, \overrightarrow{b}_{lo}>] U} +) +\end{align*} + +\begin{align*} +&Left~side = \textcolor{brown}{[a]G} + \textcolor{cyan}{[r'] H} + \textcolor{magenta}{[ab] U}\\ +& = \textcolor{brown}{< \overrightarrow{a}, \overrightarrow{G} >}\\ +&+ \textcolor{cyan}{[r + \sum_{j=1}^k (l_j \cdot u_j^2 + r_j u_j^{-2})] \cdot H}\\ +&+ \textcolor{magenta}{< \overrightarrow{a}, \overrightarrow{b} > U} +\end{align*} + + \bibliography{paper-notes.bib} \bibliographystyle{unsrt} diff --git a/ring-signatures.sage b/ring-signatures.sage index 7d8c988..58442b2 100644 --- a/ring-signatures.sage +++ b/ring-signatures.sage @@ -24,7 +24,7 @@ def print_ring(a): print(i, a[i]) print("") -class Prover(object): +class Prover: def __init__(self, F, g): self.F = F # Z_p self.g = g # elliptic curve generator diff --git a/sigma.sage b/sigma.sage index 0a617d8..a2d61c3 100644 --- a/sigma.sage +++ b/sigma.sage @@ -14,9 +14,9 @@ def generic_verify(g, X, A, c, z): # Sigma protocol interactive ### -class Prover_interactive(object): +class Prover_interactive: def __init__(self, F, g): - self.F = F # Z_p + self.F = F # Z_q self.g = g # elliptic curve generator def new_key(self): @@ -32,7 +32,7 @@ class Prover_interactive(object): def gen_proof(self, c): return int(self.a) + int(c) * int(self.w) -class Verifier_interactive(object): +class Verifier_interactive: def __init__(self, F, g): self.F = F self.g = g @@ -49,7 +49,7 @@ class Verifier_interactive(object): ### # Sigma protocol non-interactive ### -class Prover(object): +class Prover: def __init__(self, F, g): self.F = F # Z_p self.g = g # elliptic curve generator @@ -67,7 +67,7 @@ class Prover(object): return A, z -class Verifier(object): +class Verifier: def __init__(self, F, g): self.F = F self.g = g @@ -76,7 +76,7 @@ class Verifier(object): c = hash_two_points(A, X) return self.g * int(z) == X * c + A -class Simulator(object): +class Simulator: def __init__(self, F, g): self.F = F self.g = g @@ -92,7 +92,7 @@ class Simulator(object): # OR proof (with 2 parties) ### -class ORProver_2parties(object): +class ORProver_2parties: def __init__(self, F, g): self.F = F # Z_p self.g = g # elliptic curve generator @@ -126,7 +126,7 @@ class ORProver_2parties(object): # a real-world implementation would be shuffled return [c, self.c_1], [z, self.z_1] -class ORVerifier_2parties(object): +class ORVerifier_2parties: def __init__(self, F, g): self.F = F self.g = g @@ -145,7 +145,7 @@ class ORVerifier_2parties(object): # OR proof (with n parties) ### -class ORProver(object): +class ORProver: def __init__(self, F, g): self.F = F # Z_p self.g = g # elliptic curve generator @@ -190,7 +190,7 @@ class ORProver(object): # a real-world implementation would be shuffled return self.cs, self.zs -class ORVerifier(object): +class ORVerifier: def __init__(self, F, g): self.F = F self.g = g