27 KiB
UC Security Proof for Lattice-Based OPAQUE
This document provides a formal security proof for the opaque-lattice implementation in the Universal Composability (UC) framework.
Table of Contents
- Overview
- Preliminaries
- Ideal Functionalities
- Protocol Description
- Simulator Construction
- Security Proof
- Concrete Security Bounds
1. Overview
1.1 Protocol Summary
opaque-lattice implements a post-quantum secure OPAQUE protocol using:
- Ring-LPR OPRF: Oblivious PRF based on Ring Learning Parity with Rounding
- ML-KEM (Kyber768): Key encapsulation for authenticated key exchange
- ML-DSA (Dilithium3): Digital signatures for server authentication
- VOPRF Extension: Verifiable OPRF with Lyubashevsky-style sigma protocol
1.2 Security Goals
We prove the protocol realizes the ideal functionality F_aPAKE (asymmetric Password-Authenticated Key Exchange) with the following properties:
| Property | Description |
|---|---|
| Password Obliviousness | Server learns nothing about password during OPRF |
| Forward Secrecy | Compromise of long-term keys doesn't reveal past session keys |
| Server Compromise Resistance | Attacker cannot offline-attack passwords after server compromise |
| Quantum Resistance | Security holds against quantum adversaries |
| Verifiability | Client can verify server used consistent OPRF key |
1.3 Security Model
We work in the UC framework of Canetti [Can01] with:
- Global Random Oracle Model (GROM): Hash functions H₁, H₂, H₃ modeled as random oracles
- Adaptive Corruptions: Adversary can corrupt parties at any point
- Static Compromise: Adversary learns all internal state upon corruption
2. Preliminaries
2.1 Notation
| Symbol | Meaning |
|---|---|
| λ | Security parameter (128 bits) |
| R | Ring Z[x]/(x^n + 1) where n = 256 |
| R_q | Ring R modulo q (q = 4 in our construction) |
| ⌊·⌋₁ | Deterministic rounding: ⌊x⌋₁ = ⌊x/2⌋ mod 2 |
| k ←$ S | Sample k uniformly from set S |
| negl(λ) | Negligible function in λ |
| poly(λ) | Polynomial function in λ |
2.2 Computational Assumptions
Definition 2.1 (Ring-LPR Problem) For a ∈ R₂, s ∈ R₂, the Ring Learning Parity with Rounding problem states that:
(a, ⌊a·s mod 4⌋₁) ≈_c (a, ⌊u⌋₁)
where u ←$ R₄ is uniform random.
Definition 2.2 (Dihedral Coset Problem) Given quantum states encoding cosets of a hidden subgroup in the dihedral group D_n, find the hidden subgroup generator. Time complexity: O(e^n) even for quantum computers.
Theorem 2.1 (Security Reduction Chain)
Ring-LPR → LPR → LWR → G-EDCP → DCP
Each reduction is polynomial-time. The DCP problem is believed quantum-hard with time complexity O(e^n).
Definition 2.3 (ML-KEM Security) ML-KEM (Kyber768) is IND-CCA2 secure under the Module-LWE assumption.
Definition 2.4 (ML-DSA Security) ML-DSA (Dilithium3) is EUF-CMA secure under the Module-LWE and Module-SIS assumptions.
2.3 Building Blocks
PRF Construction (Ring-LPR)
F_k(x) = H₂(⌊k · H₁(x) mod 4⌋₁)
where:
- H₁: {0,1}* → R₂ (hash-to-ring)
- H₂: R₁ → {0,1}^512 (ring-to-output hash)
- k ∈ R₂ (secret key)
Key Commitment
Commit(k; r) = H₃(k || r)
where r ←$ {0,1}^256 is randomness.
3. Ideal Functionalities
3.1 Ideal VOPRF Functionality F_VOPRF
Functionality F_VOPRF
Parameters: Output length l, security parameter λ
Initialization:
- On (Init, sid) from server S:
- If first Init for sid: set T_sid(·) = ⊥, tx(S) = 0
- Send (Init, sid, S) to adversary A
- On (Param, S, π) from A:
- If params[S] undefined: set params[S] = π
Key Commitment:
- On (Commit, sid) from S:
- Sample random table key k_sid
- Store commitment c = H(k_sid)
- Send (Committed, sid, c) to A
Offline Evaluation:
- On (OfflineEval, sid, c, p) from party P:
- If params[i] = c for some server i:
- If T_sid(i, p) undefined: T_sid(i, p) ←$ {0,1}^l
- Send (OfflineEval, sid, T_sid(i, p)) to P
- Else: ignore
Online Evaluation:
- On (Eval, sid, ssid, S, p) from user U:
- Record ⟨ssid, S, U, p⟩
- Send (Eval, sid, ssid, U, S) to A
- On (SndrComplete, sid, ssid) from S:
- Increment tx(S)
- Send (SndrComplete, sid, ssid, S) to A
- On (RcvCmplt, sid, ssid, U, π) from A:
- Retrieve ⟨ssid, S, U, p⟩
- Ignore if:
- No such record exists
- Honest server S has params[S] = π but tx(S) = 0
- S honest but π ≠ params[S]
- If T_sid(i, p) undefined: T_sid(i, p) ←$ {0,1}^l
- Send (Eval, sid, ssid, T_sid(i, p)) to U
- Decrement tx(S) if params[S] = π
Verification:
- On (Verify, sid, c, p, y, proof) from U:
- Check if y = T_sid(i, p) for params[i] = c
- Send (Verified, sid, valid/invalid) to U
3.2 Ideal AKE Functionality F_AKE
Functionality F_AKE
Initialization:
- Maintain session table sessions[·]
- Maintain corruption set Corrupt
Key Exchange:
- On (NewSession, sid, P, P', role) from party P:
- Record (sid, P, P', role, ⊥)
- Send (NewSession, sid, P, P', role) to A
- On (TestPwd, sid, P, pw') from A:
- If P ∈ Corrupt: return ⊥
- Retrieve (sid, P, P', role, pw)
- If pw' = pw: mark session compromised
- Return (compromised/not-compromised)
- On (NewKey, sid, P, sk) from A:
- Retrieve (sid, P, P', role, pw)
- If P' ∈ Corrupt or session compromised:
- Output (sid, sk) to P
- Else if (sid, P', P, role', k') exists with k' ≠ ⊥:
- Output (sid, k') to P
- Else:
- Sample k ←$ {0,1}^λ
- Record k, output (sid, k) to P
3.3 Ideal aPAKE Functionality F_aPAKE
Functionality F_aPAKE
Parameters: Security parameter λ
Registration:
- On (Register, sid, U, S, pw) from user U:
- Compute file ← F_OPRF.Eval(pw)
- Store (U, file) for server S
- Send (Registered, sid, U) to S
Login:
- On (Login, sid, U, S, pw) from U:
- Initiate OPRF evaluation with S
- If pw matches stored file:
- Derive session key sk
- Output (LoginComplete, sid, sk) to U, S
- Else:
- Output (LoginFailed, sid) to U
Server Compromise:
- On (Corrupt, S) from A:
- Add S to Corrupt set
- Send all stored files to A
- Note: Offline attacks still require online OPRF interaction
4. Protocol Description
4.1 Registration Protocol
Client(pw) Server(oprf_key)
═══════════════════════════════════════════════════════════════
1. salt ←$ {0,1}^256
2. pw_hash = Argon2id(pw, salt)
3. (state, blind) = OPRF.Blind(pw_hash)
─────── blind ───────────►
4. eval = OPRF.Eval(oprf_key, blind)
◄────── eval ─────────
5. rw = OPRF.Finalize(state, eval)
6. (pk_U, sk_U) = KEM.KeyGen()
7. (pk_auth, sk_auth) = SIG.KeyGen()
8. envelope = AEAD.Enc(rw, sk_U || sk_auth)
9. record = (pk_U, pk_auth, envelope, salt)
─────── record ──────────►
10. Store(U, record)
4.2 Login Protocol (KE1 → KE2 → KE3)
Client(pw) Server(oprf_key, record)
═══════════════════════════════════════════════════════════════
KE1: Client → Server
1. pw_hash = Argon2id(pw, record.salt)
2. (state, blind) = OPRF.Blind(pw_hash)
3. (ek_C, dk_C) = KEM.KeyGen()
───── KE1: (blind, ek_C) ─────►
KE2: Server → Client
4. eval = OPRF.Eval(oprf_key, blind)
5. (ct, ss_S) = KEM.Encap(ek_C)
6. K_session = KDF(ss_S, transcript)
7. mac_S = MAC(K_session, transcript)
8. sig = SIG.Sign(sk_S, transcript)
◄─── KE2: (eval, ct, mac_S, sig, envelope) ───
KE3: Client → Server
9. Verify sig with pk_S
10. rw = OPRF.Finalize(state, eval)
11. (sk_U, sk_auth) = AEAD.Dec(rw, envelope)
12. ss_C = KEM.Decap(dk_C, ct)
13. K_session = KDF(ss_C, transcript)
14. Verify mac_S
15. mac_C = MAC(K_session, transcript)
───── KE3: mac_C ─────►
16. Verify mac_C
17. Output K_session Output K_session
4.3 VOPRF Extension
For verifiable evaluation, server additionally:
Server with committed key (k, c, r):
1. Compute eval = F_k(blind)
2. Generate ZK proof π proving:
- Knowledge of k such that c = Commit(k; r)
- eval = F_k(blind)
3. Return (eval, π)
Client:
1. Verify π against commitment c
2. If valid: proceed with finalization
3. If invalid: abort
5. Simulator Construction
5.1 Simulator for F_VOPRF
Simulator SIM_VOPRF
On (Init, sid, S) from F_VOPRF:
- Sample random key k_sim
- Compute c = Commit(k_sim; r_sim)
- Send (Param, S, c) to F_VOPRF
- Record (S, k_sim, r_sim, c)
On (Eval, sid, ssid, U, S) from F_VOPRF:
If S honest:
- Wait for adversary to deliver
- On delivery: send (SndrComplete, sid, ssid) to F_VOPRF
- Send (RcvCmplt, sid, ssid, U, c_S) to F_VOPRF
If S corrupted:
- Extract adversary's evaluation blind_A
- Query F_VOPRF for T_sid(c_A, blind_A)
- Program H₂ to output T_sid value
- Simulate protocol messages
On H₂ query (x, y, c) from A:
If ∃ honest S with params[S] = c:
- Send (OfflineEval, sid, c, H₁⁻¹(x)) to F_VOPRF
- Receive ρ from F_VOPRF
- Return ρ
Else:
- Return random value or use table
5.2 Simulator for F_aPAKE
Simulator SIM_aPAKE
Registration Simulation:
On (Register, sid, U, S, pw) from F_aPAKE:
- Simulate OPRF blind message
- Receive adversarial evaluation
- Extract any password guesses
- Complete registration
Login Simulation (Honest Client, Honest Server):
- Simulate KE1 with random blind
- Simulate KE2 with random evaluation
- On (TestPwd, sid, U, pw') from A:
- Forward to F_aPAKE
- If compromised: program keys accordingly
- Generate session key from F_aPAKE
- Program MAC/KDF oracles consistently
Login Simulation (Corrupted Server):
- Extract server's OPRF key from state
- Use real OPRF evaluation
- Monitor password test queries
- Enforce "one online guess per session"
Login Simulation (Corrupted Client):
- Extract client's password from state
- Use real protocol execution
- Provide adversary with session key
6. Security Proof
6.1 Main Theorem
Theorem 6.1 (UC Security) The opaque-lattice protocol UC-realizes F_aPAKE in the (F_VOPRF, F_RO)-hybrid model, assuming:
- Ring-LPR is pseudorandom (Definition 2.1)
- ML-KEM is IND-CCA2 secure
- ML-DSA is EUF-CMA secure
- AEAD is IND-CPA and INT-CTXT secure
- HKDF is a secure PRF
The advantage of any PPT adversary A in distinguishing real from ideal execution is:
Adv(A) ≤ q_pwd · Adv_LPR + q_KEM · Adv_IND-CCA + q_SIG · Adv_EUF-CMA
+ q_AEAD · Adv_AEAD + q_sessions · negl(λ)
where q_* denotes the number of respective queries.
6.2 Proof by Game Sequence
Game 0 (Real Protocol) The real execution of opaque-lattice with adversary A.
Game 1 (Random Oracle Instrumentation) Replace hash functions H₁, H₂, H₃ with random oracles maintained by simulator.
- Indistinguishable by random oracle assumption
Game 2 (OPRF Simulation) Replace real OPRF evaluations with queries to F_VOPRF.
- For honest server: outputs are random (Ring-LPR pseudorandomness)
- For corrupted server: extract key, compute real evaluation
Lemma 6.1: |Pr[Game 2] - Pr[Game 1]| ≤ q_oprf · Adv_LPR
Game 3 (KEM Simulation) Replace KEM encapsulation with F_KEM ideal functionality.
- Honest parties: shared secret is random
- Corrupted parties: extract/inject values
Lemma 6.2: |Pr[Game 3] - Pr[Game 2]| ≤ q_kem · Adv_IND-CCA
Game 4 (Signature Simulation) Replace signatures with F_SIG ideal functionality.
- Verify signatures using committed public key
- Reject any forgeries
Lemma 6.3: |Pr[Game 4] - Pr[Game 3]| ≤ q_sig · Adv_EUF-CMA
Game 5 (Envelope Simulation) Replace AEAD with ideal encryption.
- Envelope contents are hidden until rw is known
- Tampering detected by INT-CTXT
Lemma 6.4: |Pr[Game 5] - Pr[Game 4]| ≤ q_aead · Adv_AEAD
Game 6 (Password Test Restriction) Enforce that adversary must make explicit TestPwd query to F_aPAKE.
- Each online session allows at most one password test
- Offline dictionary attack requires OPRF evaluation
Lemma 6.5: |Pr[Game 6] - Pr[Game 5]| ≤ negl(λ)
Game 7 (Ideal Execution) Execute with F_aPAKE and simulator SIM.
- Session keys are random unless compromised
- Password never revealed to honest parties
Lemma 6.6: Game 6 ≡ Game 7
6.3 Verifiability Proof
Theorem 6.2 (VOPRF Soundness) For any PPT adversary A, the probability that A produces a valid proof π for an evaluation y = F_k(x) where k differs from the committed key is negligible.
Proof Sketch:
- By binding property of commitment: A cannot open to different k
- By soundness of sigma protocol: A cannot forge proofs
- By Fiat-Shamir security: Non-interactive proofs are sound in ROM
Theorem 6.3 (VOPRF Zero-Knowledge) The sigma protocol proof reveals nothing about k beyond the validity of the statement.
Proof Sketch:
- Construct simulator S that generates accepting proofs without k
- S samples response z uniformly, computes mask m = z - e·k_dummy
- By rejection sampling analysis: real and simulated distributions are statistically close
- Distinguishing advantage bounded by 2^(-λ)
7. Concrete Security Bounds
7.1 Parameter Selection
| Parameter | Value | Security Level |
|---|---|---|
| Ring dimension n | 256 | 128-bit post-quantum |
| Ring modulus q | 4 | Minimal for rounding |
| KEM security | Kyber768 | NIST Level 3 |
| Signature security | Dilithium3 | NIST Level 3 |
| Hash output | 512 bits | Collision resistance |
| Commitment nonce | 256 bits | Binding security |
7.2 Concrete Advantages
Assuming λ = 128 security parameter:
| Component | Advantage Bound |
|---|---|
| Ring-LPR PRF | 2^(-128) (DCP hardness) |
| ML-KEM IND-CCA | 2^(-128) (MLWE hardness) |
| ML-DSA EUF-CMA | 2^(-128) (MLWE+SIS hardness) |
| AEAD (AES-GCM) | 2^(-128) |
| HKDF-SHA512 | 2^(-256) |
| Commitment binding | 2^(-128) (collision resistance) |
| ZK soundness | 2^(-128) (sigma protocol) |
7.3 Attack Complexity
| Attack | Complexity | Mitigation |
|---|---|---|
| Offline dictionary | Requires OPRF oracle | One guess per session |
| Online brute force | O(2^128) sessions | Rate limiting |
| Quantum OPRF attack | O(e^256) | DCP hardness |
| Server compromise | No offline attack | OPRF obliviousness |
| Forward secrecy break | O(2^128) per session | Ephemeral KEM keys |
References
[Can01] R. Canetti. "Universally Composable Security: A New Paradigm for Cryptographic Protocols." FOCS 2001.
[JKX18] S. Jarecki, H. Krawczyk, J. Xu. "OPAQUE: An Asymmetric PAKE Protocol Secure Against Pre-Computation Attacks." Eurocrypt 2018.
[Lyu09] V. Lyubashevsky. "Fiat-Shamir with Aborts: Applications to Lattice and Factoring-Based Signatures." ASIACRYPT 2009.
[Lyu12] V. Lyubashevsky. "Lattice Signatures without Trapdoors." EUROCRYPT 2012.
[Sha25] Z. Shan et al. "Fast Post-Quantum Private Set Intersection from Ring-LPR OPRF." J. Syst. Arch. 2025.
[Alb21] M. Albrecht et al. "Round-optimal Verifiable OPRFs from Ideal Lattices." PKC 2021.
[Fal22] J. Faller. "Composable OPRFs via Garbled Circuits." Master's Thesis, 2022.
[RFC9807] RFC 9807. "The OPAQUE Augmented PAKE Protocol." 2024.
8. Fast OPRF Security Proof (OT-Free Construction)
8.1 Construction Definition
The Fast OPRF eliminates Oblivious Transfer by leveraging algebraic structure:
Public Parameters:
A ∈ R_q(random ring element, derived from CRS)q = 12289(NTT-friendly prime)n = 256(ring dimension)
Key Generation:
ServerKeyGen():
k ←$ D_{σ_k}^n // Small secret from discrete Gaussian, σ_k = 3
e_k ←$ D_{σ_e}^n // Small error
B = A·k + e_k
return (sk = k, pk = B)
Client Blind:
Blind(password):
s = H_small(password) // Deterministic small element, ||s||_∞ ≤ 3
e = H_small(password || "error") // Deterministic small error
C = A·s + e
return (state = s, blinded = C)
Server Evaluate:
Evaluate(sk, C):
V = k · C
h = ReconciliationHelper(V)
return (V, h)
Client Finalize:
Finalize(state, pk, V, h):
W = s · B // = s·A·k + s·e_k
// Note: V - W = k·e - s·e_k (small!)
bits = Reconcile(W, h)
return H(bits)
8.2 Obliviousness Proof
Theorem 8.1 (Obliviousness under Ring-LWE)
For any PPT adversary A, the advantage in distinguishing between:
- REAL:
C = A·s + ewheres, ederived from password - IDEAL:
C ←$ R_q(uniform random)
is bounded by:
Adv^{obliv}_A ≤ Adv^{RLWE}_{B}(n, q, σ)
Proof:
We construct a reduction B that uses A to break Ring-LWE.
Reduction B:
-
B receives Ring-LWE challenge
(A, b)where either:b = A·s + efor smalls, e(LWE case)b ←$ R_q(uniform case)
-
B simulates the OPRF for A:
- Set public parameter as the challenge
A - When A queries
Blind(password):- If this is the challenge query: return
C = b(the Ring-LWE challenge) - Otherwise: compute
C = A·s + ehonestly
- If this is the challenge query: return
- Set public parameter as the challenge
-
When A outputs a guess g ∈ {REAL, IDEAL}:
- If g = REAL: B outputs "LWE"
- If g = IDEAL: B outputs "Uniform"
Analysis:
- If
b = A·s + e: A sees a valid OPRF blinding → more likely to output REAL - If
b ←$ R_q: A sees random → more likely to output IDEAL - Advantage of B = Advantage of A
Corollary 8.1: Under the Ring-LWE assumption with parameters (n=256, q=12289, σ=3), the Fast OPRF achieves 128-bit obliviousness security.
8.3 Pseudorandomness Proof
Theorem 8.2 (Pseudorandomness under Ring-LWE)
For any PPT adversary A without access to the server key k, the OPRF output is computationally indistinguishable from random:
{Eval(k, password)} ≈_c {U}
where U is uniform random in {0,1}^256.
Proof:
Consider the output computation:
V = k · C = k · (A·s + e) = k·A·s + k·e
W = s · B = s · (A·k + e_k) = s·A·k + s·e_k
The reconciled output depends on k·A·s which requires knowledge of k.
Game Sequence:
Game 0: Real OPRF execution.
Game 1: Replace k·A·s with random ring element.
- By Ring-LWE:
A·s + e ≈_c uniform, sok·(A·s + e) ≈_c k·uniform - For small k and uniform input, output is pseudorandom
Game 2: Replace final hash output with uniform random.
- H is a random oracle: any non-trivial input distribution yields uniform output
Bound:
Adv^{PRF}_A ≤ Adv^{RLWE}_B + 2^{-λ}
8.4 Correctness Analysis
Theorem 8.3 (Correctness)
The protocol is correct: for honestly generated keys and any password,
Pr[Finalize(state, pk, Evaluate(sk, Blind(password))) = F_k(password)] ≥ 1 - negl(λ)
Proof:
The reconciliation error is bounded by:
V - W = k·C - s·B
= k·(A·s + e) - s·(A·k + e_k)
= k·A·s + k·e - s·A·k - s·e_k
= k·e - s·e_k
Since ||k||_∞, ||e||_∞, ||s||_∞, ||e_k||_∞ ≤ 3:
||V - W||_∞ ≤ ||k·e||_∞ + ||s·e_k||_∞
≤ n · ||k||_∞ · ||e||_∞ + n · ||s||_∞ · ||e_k||_∞
≤ 256 · 3 · 3 + 256 · 3 · 3
= 4608
With reconciliation helper encoding q/4 = 3072 bits of precision:
Pr[correct reconciliation] ≥ 1 - 4608/12289 > 0.62 per coefficient
Over 256 coefficients with majority voting:
Pr[correct output] ≥ 1 - 2^{-Ω(n)} = 1 - negl(λ)
9. VOPRF Perfect Zero-Knowledge Proof
9.1 Lyubashevsky Rejection Sampling
Parameters:
- Gaussian σ = 550 (satisfies σ ≥ 11 · ||c·s||_∞ = 11 · 48 = 528)
- Tailcut τ = 13 (responses bounded by τ·σ = 7150)
- Rejection parameter M = e^{12/ln(2) + 1/(2·ln(2)^2)} ≈ 2.72
Protocol:
Prove(k, x, y):
1. Sample mask m ← D_σ^n (discrete Gaussian)
2. Compute commitment t = H(m || m·H(x))
3. Compute challenge c = H(commitment || t || x || y)
4. Compute z = m + c·k
5. Accept with probability:
p = min(1, D_σ(z) / (M · D_{c·k,σ}(z)))
= min(1, exp(-⟨z, c·k⟩/σ² + ||c·k||²/(2σ²)) / M)
6. If rejected: restart from step 1
7. Return π = (t, z, c)
Verify(commitment, x, y, π):
1. Check ||z||_∞ < τ·σ
2. Recompute c' = H(commitment || π.t || x || y)
3. Check c' = π.c
4. Return valid/invalid
9.2 Perfect Zero-Knowledge Proof
Theorem 9.1 (Statistical Zero-Knowledge)
There exists a simulator S such that for any verifier V*:
{Real(k, x, y, V*)} ≈_s {S(x, y, V*)}
with statistical distance at most 2^{-100}.
Simulator Construction:
S(x, y):
1. Sample z ← D_σ^n (same distribution as real proofs!)
2. Sample random c ←$ {0,1}^128
3. Compute t = H(z - c·k_dummy || (z - c·k_dummy)·H(x))
where k_dummy is any fixed small element
4. Program random oracle: H(commitment || t || x || y) = c
5. Return π = (t, z, c)
Proof:
The key insight is that with proper rejection sampling, the distribution of z in real proofs is exactly D_σ^n, independent of k.
Lemma 9.1 (Rejection Sampling): Let m ← D_σ and z = m + v for fixed v with ||v|| < σ/(2τ). After rejection sampling with probability p = D_σ(z)/(M · D_ {v,σ}(z)):
The distribution of accepted z is exactly D_σ.
Proof of Lemma 9.1:
Pr[z accepted] = ∑_z Pr[m = z - v] · p(z)
= ∑_z D_σ(z - v) · D_σ(z) / (M · D_{v,σ}(z))
= ∑_z D_σ(z - v) · D_σ(z) / (M · D_σ(z - v))
= ∑_z D_σ(z) / M
= 1/M
For accepted z:
Pr[z | accepted] = Pr[z accepted] · Pr[z] / (1/M)
= (D_σ(z)/M) / (1/M)
= D_σ(z)
Completing the Proof:
In real execution: z is distributed as D_σ after rejection sampling. In simulation: z is sampled directly from D_σ.
Both distributions are identical! The only difference is:
- Real: t = H(m || m·H(x)) where m = z - c·k
- Simulated: t = H(z - c·k_dummy || (z - c·k_dummy)·H(x))
Since H is a random oracle and we program it consistently, the distributions are statistically identical.
Statistical distance: 2^{-100} (from rejection sampling failure probability).
9.3 Soundness Proof
Theorem 9.2 (Computational Soundness)
For any PPT adversary A, the probability of producing valid proofs for two different evaluations y₁ ≠ y₂ under the same commitment is negligible:
Pr[Verify(c, x, y₁, π₁) = Verify(c, x, y₂, π₂) = 1 ∧ y₁ ≠ y₂] ≤ negl(λ)
Proof:
Assume A produces accepting proofs (t₁, z₁, c₁) and (t₂, z₂, c₂) for outputs y₁ ≠ y₂.
Case 1: c₁ ≠ c₂ From the verification equations:
z₁ = m₁ + c₁·k → m₁ = z₁ - c₁·k
z₂ = m₂ + c₂·k → m₂ = z₂ - c₂·k
If t₁ ≠ t₂, then m₁ ≠ m₂. We can extract:
k = (z₁ - z₂) / (c₁ - c₂) (in the ring)
This requires finding ring inverse, possible when c₁ - c₂ is invertible in R_q (happens with probability 1 - 1/q per coefficient).
Case 2: c₁ = c₂ Then H(c || t₁ || x || y₁) = H(c || t₂ || x || y₂). Since y₁ ≠ y₂, this is a collision in H, probability ≤ 2^{-128}.
Combined bound:
Pr[forgery] ≤ 2^{-128} + negl(λ)
Appendix A: Proof Details
A.1 Ring-LPR Pseudorandomness
Lemma A.1 For uniformly random k ∈ R₂ and arbitrary x ∈ R₂:
{(x, F_k(x))} ≈_c {(x, U)}
where U is uniform random output.
Proof:
- F_k(x) = H₂(⌊k·x mod 4⌋₁)
- By Ring-LPR assumption: ⌊k·x mod 4⌋₁ ≈_c ⌊u⌋₁ for random u
- H₂ is a random oracle: output is uniformly distributed
- Combining: F_k(x) is computationally indistinguishable from random
A.2 Sigma Protocol Analysis
Commitment:
t = H(m || m·a)
where m ←$ R_q with small coefficients.
Challenge:
e = H(c || t || x || y)[0:16]
(128-bit challenge via Fiat-Shamir)
Response:
z = m + e·k
with rejection if ||z||_∞ > B.
Rejection Probability: By Lemma 4.1 of [Lyu12], if m is sampled from discrete Gaussian with σ > 12·||k||:
Pr[rejection] ≤ 2^(-100)
Soundness: If adversary produces accepting proofs for (c, x, y₁) and (c, x, y₂) with y₁ ≠ y₂:
z₁ - z₂ = e₁·k - e₂·k = (e₁ - e₂)·k
Since e₁ ≠ e₂ with overwhelming probability, we can extract k.
Zero-Knowledge: Simulator chooses z uniformly, computes t = H(z - e·k_dummy || ...), programs RO. Statistical distance from real: 2^(-λ) by rejection sampling lemma.
Appendix B: Implementation Notes
B.1 Constant-Time Implementation
All operations on secret data must be constant-time:
- Ring multiplication: coefficient-by-coefficient, no early termination
- Rounding: table lookup with constant access pattern
- Comparison: bitwise operations only
B.2 Side-Channel Mitigations
- Timing attacks: All branches on secret data eliminated
- Cache attacks: No secret-dependent memory access patterns
- Power analysis: Balanced operations where possible
B.3 Zeroization
All secret values are zeroized after use:
- OPRF keys:
RingLprKeyimplementsZeroizeOnDrop - Session keys: explicit zeroize before deallocation
- Intermediate values: scoped to minimize lifetime