paper-notes: Add modified IPA (from Halo)
arnaucube root@arnaucube.com
Mon, 18 Jul 2022 21:20:31 +0200
6 files changed,
122 insertions(+),
15 deletions(-)
M
ipa.sage
→
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 @@
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
M
paper-notes.bib
→
paper-notes.bib
@@ -31,3 +31,11 @@ year = {2010},
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} +}
M
paper-notes.tex
→
paper-notes.tex
@@ -12,6 +12,7 @@ filecolor=black,
linkcolor=black, urlcolor=blue } +\usepackage{xcolor} % prevent warnings of underfull \hbox: \usepackage{etoolbox}@@ -224,15 +225,113 @@ Identical to verification of a normal signature as long as we use the same corresponding aggregated public key:
$$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}
M
ring-signatures.sage
→
ring-signatures.sage
@@ -24,7 +24,7 @@ for i in range(len(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
M
sigma.sage
→
sigma.sage
@@ -14,9 +14,9 @@ ###
# 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 @@
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 @@
### # 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 @@ z = int(a) + c * int(self.w)
return A, z -class Verifier(object): +class Verifier: def __init__(self, F, g): self.F = F self.g = g@@ -76,7 +76,7 @@ def verify(self, X, A, z):
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 @@ ###
# 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 @@ # note, here the order of the returned elements is always the same, in
# 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 @@ ###
# 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 @@ # note, here the order of the returned elements is always the same, in
# 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