preon: digital signature from zk-SNARK

The preon team

Team

  • Hon Hai Research Institute
    • Yu-Shian Chen & Wei-Bin Lee
  • BTQ
    • Shiuan Fu, Wei-Chih Hong, Jen-Hsuan Hsiang, Sheng-Te Hu, & Po-Chun Kuo
  • Academia Sinica
    • Ming-Shing Chen & Bo-Yin Yang (TBC)
  • Feng-Hao Liu, Washington State University
  • Justin Thaler, Georgetown University
  • Eylon Yogev, Bar-Ilan University
  • Chen-Mou Cheng, Chang Gung University

Outline

  • NIST PQC
  • preon
  • zk-SNARK: an anatomy
    • Commitment
    • I(O)P & ZKP
      • Schnorr's ZKP for DLP
    • Aurora
  • Feb 2016: Announced in PQCRYPTO
    • Need to run on classical, non-quantum computers
    • Wide spectrum: From extremely constrained devices to limited communication bandwidth
  • July 2022: To standardize 4 algorithms






     
  • July 2023: To consider 40 additional signature schemes
CRYSTALS-Kyber Lattice (MLWE) KEM
CRYSTALS-Dilithium Lattice (MLWE) Signature
Falcon Lattice (NSIS) Signature
SPHINCS+ Hash-based Signature

preon:
beyond digital signature

  • Standard digital signature on message \( x \):
    • "I swear that the signer said \( x \)."
  • Beyond digital signature:
    • "The signer said \( \color{red}x\color{black} \), which I'm not going to disclose here, but I swear that \( f(\color{red}x\color{black})=y \)."

Example

  • CA signs Cert: "Batman was born on Jan 1, 1976"
  • \( f(x,\color{red}w\color{black})=1 \) if and only if:
    • \( \color{red}w\color{black} \) is a valid certificate signed by CA
    • \( \color{red}w\color{black} \) says as of today, \( x \) is over 18 years old
  • Beers for Batman if \( f(\text{Batman},\color{red}\text{Cert}\color{black})=1 \)

preon: under the hood

  • preon \( \approx \) Aurora + AES
    • Aurora: post-quantum zk-SNARK (to be detailed)
    • AES as one-way function
      • Public key is the ciphertext of encrypting a random plaintext using private key
  • Optimization: replace prime field with binary field
    • 14240 \( \rightarrow \) 3440 constraints
    • 4x speedup, with additional 2\( \text{--} \)3x via AFFT
    • About 20% smaller signature

preon+: performance

Security Private key Public key Signature Key gen Sign Verify
128-bit (A1) 16 32 44.7K 2us 490ms 7.2ms
128-bit (A2) 16 32 49.7K 2us 326ms 8.5ms
128-bit (B) 16 32 90.1K 2us 343ms 16.8ms
192-bit (A) 24 56 101.6K 2us 497ms 47ms
192-bit (B) 24 56 201.6K 2us 623ms 103ms
256-bit (A) 32 64 186.1K 2us 1399ms 149ms
256-bit (B) 32 64 369K 2us 1773ms 330ms

Where we are & to go

  • preon accepted by NIST as complete & proper
    • Preliminary security analysis shows even Aggressive (A) meets NIST's requirement, with Balanced (B) as backup
    • preon+ incorporates Cantor basis & more efficient encoding/padding
  • Future works
    • More security analysis
    • Further optimized implementations
      • Must have: CPU, GPU, FPGA
      • Nice to have: ASIC

Anatomy of zk-SNARK

Serialization via commitment

(How to play rock-paper-scissors over internet)

  • Cryptographic commitment
    • Commit: \( c=\text{commit}(r,m) \)
    • Verify: \( \text{verify}\Big(r,m,c\Big)? \)
  • Security properties
    • Hiding: difficult to find \( m \) given \( c=\text{commit}\left(r,m\right) \)
    • Binding: difficult to find \( r',m'\neq m \) s.t. \( \text{verify}\Big(r',m',\text{commit}(r,m)\Big) \)

Proving \( x\in X \) via Merkle tree

Proving \( f(x)=y \)

  • Syntax of (polynomial) functional commitment
    • \( c=\text{commit}(r,f) \)
    • \( (y,\pi)=\text{eval}(r,f,x) \)
    • \( \text{verify}\Big(c,x,y,\pi\Big) \) iff \( \exists r\text{ s.t. }c=\text{commit}(r,f) \) and \( f(x)=y \)
  • Example (Merkle tree)
    • Leaves \( y_0,y_1,\ldots,y_{n-1} \) define \( f:\Big\{0,1,\ldots,n-1\Big\}\rightarrow Y \)
    • Authentication path encodes (binary expansion of) \( i\in\Big\{0,1,\ldots,n-1\Big\} \) and thus proves \( f(i)=y_i \)

Why polynomials?

  • \( f_{v+w}=f_v+f_w, f_{v\odot w}=f_vf_w \) for coordinate-wise product \( \odot \) \[ \Big(\because\text{ev}\in k[X]\times k\rightarrow k\cong k[X]\rightarrow k\rightarrow k\Big) \]
  • Lemma [Schwartz-Zippel] \[ \text{Pr}_{r\in k}\Big(f(r)=g(r)\Big)\leq\frac{d}{|k|}\text{ for }f\neq g\text{ with }\deg f,\deg g\leq d \]
    • Zero test: \( f(\omega)=0\ \forall\omega\in\Omega \)
    • Sum check: \( \sum_{\omega\in\Omega}f(\omega)=0 \)
    • Product check: \( \prod_{\omega\in\Omega}f(\omega)=1 \)

Interactive (oracle) proof

  • IP allows Prover P to prove Statement S to (computationally bounded) Verifier V via dialogue
    • Completeness: If S is true, then V should be convinced with probability 1
    • Soundness: If S is false, then V should be convinced with a (very) small probability
  • Example (trivial): NP \( \subset \) IP
  • IOP: dialogue consists of probabilistically checkable proofs, implemented by e.g. functional commitment

Zero-knowledge IP

  • V learns nothing beyond S is true
    • Consider special S: \( y=f(x,\color{red}w\color{black}) \)
    • Can simulate the dialogues without knowing \(\color{red}w\color{black}\)
  • Example: Blind V with two colored balls

Toy example

  • Prover: "I know integers \( \color{red}p\color{black},\color{red}q\color{black} \) s.t. \( n=\color{red}pq\color{black} \)"
  • Prover commits to three polynomial functions: \[ \color{red}r_p\color{black}X+\color{red}p\color{black},\color{red}r_q\color{black}X+\color{red}q\color{black},\text{ and }\color{red}r_pr_q\color{black}X^2+(\color{red}r_pq\color{black}+\color{red}pr_q\color{black})X+n \]
  • Verifier challenges Prover with random \( r \) and checks whether \( (\color{red}r_p\color{black}r+\color{red}p\color{black})(\color{red}r_q\color{black}r+\color{red}q\color{black})\stackrel{?}{=}\color{red}r_pr_q\color{black}r^2+(\color{red}r_pq\color{black}+\color{red}pr_q\color{black})r+n \)
  • Lemma [Schwartz-Zippel] \[ \text{Pr}_{r\in k}\Big(f(r)=g(r)\Big)\leq\frac{d}{|k|}\text{ for }f\neq g\text{ with }\deg f,\deg g\leq d \]

Schnorr's ZKP for DLP

  • S: "I know \( \color{red}x\color{black} \) s.t. \( y=g^{\color{red}x\color{black}} \)"
    • P \( \rightarrow \) V: \( r=g^{\color{red}k\color{black}} \)
    • P \( \leftarrow \) V: \( e \)
    • P \( \rightarrow \) V: \( s=\color{red}k\color{black}-\color{red}x\color{black}e \)
    • V checks: \( r\stackrel{?}{=}g^sy^e\left(=g^{\color{red}k\color{black}-\color{red}x\color{black}e}(g^x)^e\right) \)
  • Fiat-Shamir heuristic turns (most) IP to NIROP (Non-Interactive Random-Oracle Proof)
    • Schnorr's signature: \( \pi=(r,s) \) for \( e=H(r||m) \)
    • zk-NARK (Noninteractive ARgument of Knowledge)

Knowledge extractor

How Sony PS3 got hacked in 2011: \[ \left\{\begin{aligned} s_1 & =\color{red}k\color{black}-\color{red}x\color{black}e_1 \\ s_2 &= \color{red}k\color{black}-\color{red}x\color{black}e_2 \end{aligned}\right. \]

zk-SNARK

  • Consider special zk-NARK:
    • Proof \( \pi \) proves P knows a \( \color{red}w\color{black} \) s.t. \( y=f(x,\color{red}w\color{black}) \)
    • If \( \pi \) is "small" compared with \( f \), e.g., \( |\pi|=O(\log|f|) \), then we say it is succinct, or zk-SNARK
  • Questions
    • What can we do with a zk-SNARK?
    • How to "compress" \( \pi \)?
    • How to encode (interesting) \( f \)?

zk-SNARKing C2PA

  • Coalition for Content Provenance and Authenticity
    • Camera signs all photos taken: \( s=\text{sign}(p) \)
    • Publisher/consumer verifies: \( \text{verify}(p,s)? \)
  • What if \( p'=f(p) \) where \( f \) crops, resizes, rotates, ... \( p \)?
    • \( \pi \): "I know \( \color{red}p\color{black},\color{red}s\color{black} \) s.t. \( \text{verify}(\color{red}p\color{black},\color{red}s\color{black}) \) & \( p'=f(\color{red}p\color{black}) \)"
    • For zk-SNARKs, \( |\pi|\ll |f|=\mathcal O(|p|) \)

EF's semaphore

  • "Users who broadcast a signal will not expose their identity"
    • "Specifically, an adversary will only know they're a user in the group, but not which user"
  • "Users cannot broadcast two different signals on the same topic twice"

How to implement?

  • Identity commitment integrity: \[ \text{id}_\text{comm}=\text{Commit}_{\text{id}_\text{trapdoor}}(\text{id}_\text{pub},\text{id}_\text{nullifier}) \]
  • Merkle path validity: \[ (\text{id\textunderscore path},\text{id\textunderscore path\textunderscore index})\text{ is a valid Merkle path from id}_\text{comm}\text{ to root} \]
  • Nullifiers hash integrity: \[ \text{nullifiers\textunderscore hash}=\text{PRF}_{\text{id}_\text{nullifier}}(\text{external\textunderscore nullifier},\text{id\textunderscore path\textunderscore index}) \]
  • Signal authorization: \[ \text{Verify}(\text{id}_\text{pub},(\text{external\textunderscore nullifier},\text{signal\textunderscore hash}),\text{signature}) \]

Recipe: RS-encoded IOP

  • Think of \( v\in V \) as a function \( H\rightarrow F_q \) for \( |H|=\dim V \)
  • Encode \( v \) as \( f_v \) via Lagrange interpolation
    • \( f_v(X)=r(X)+q(X)\prod_{h\in H}(X-h) \)
    • S.t. \( \forall h\in H,r(h)=v(h) \)
  • V can now query \( f_v(x) \) for some \( x\in L \)
    • Intuition: ZK if \( H\cap L=\varnothing \) and \( \deg q \) is large enough
  • (FRI) low-degree test: Check if \( \deg f_v \) is small enough
  • Encode \( y=f(x,\color{red}w\color{black}) \) into R1CS: \( Az\odot Bz=Cz \), where:
    • \( A,B,C \) are matrices depending on \( f \)
    • \( z=\begin{bmatrix} 1 & u & \color{red}w\color{black} & x & y \end{bmatrix}^T \)
    • \( u \) is auxiliary variables
  • Lincheck RS-encoded IOP: \( y_A=Az, y_B=Bz, y_C=Cz \)
  • Rowcheck RS-encoded IOP: \( y_A\odot y_B=y_C \)

Expressiveness of R1CS

\[ y=x^3: \boxed{\begin{aligned} x\cdot x & =u \\ u\cdot x & =y \end{aligned}} \]

\[ 0\leq x<8: \boxed{\begin{aligned} 1\cdot(x_0+2x_1+4x_2) & =x \\ x_0\cdot x_0 & =x_0 \\ x_1\cdot x_1 & =x_1 \\ x_2\cdot x_2 & =x_2 \end{aligned}} \]

\(r=\) if \(b\) then \(t\) else \(f\): \[ \boxed{\begin{aligned} (t-f)\cdot b & =r-f \\ b\cdot b & =b \end{aligned}} \]

Got DSL? 

Revisiting Merkle tree

In ZoKrates

  • Witness contains array of arrays of hash values along authentication path
  • Well-known trick to include the indices of these hash values at each level
    • Not strictly necessarily but for easy programming
    • Will expand to nested if-then-else in R1CS anyway
    field mut digest = leaf;

    for u32 i in 0..DEPTH {
        assert(path[i][indices[i]] == digest);
        digest = hash(path[i]);
    }
    assert(digest == root);

\(\text{\tt fold}\) to rescue in Keelung

\(\text{\tt foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b}\)

merkleProof :: Int -> Number -> Comp ()
merkleProof depth root = do
  leaf <- inputNum
  path <- inputs2 depth 2
  digest <- foldlM (\digest p -> do
                      assert (digest `existsIn` p)
                      hash p)
                   leaf
                   path
  assert (digest `Eq` root)

Thank you!

Questions or comments?

Made with Slides.com