-
-
Save callebtc/6e624a4905f8a407cccff12c47fa3e07 to your computer and use it in GitHub Desktop.
Sigma Protocol Proofs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use bitcoin_hashes::{sha256, Hash, HashEngine}; | |
use bls12_381::{G1Affine, G1Projective, Scalar}; | |
use core::array; | |
use ff::Field; | |
use group::Curve; | |
use rand::{thread_rng, SeedableRng}; | |
use rand_chacha::ChaChaRng; | |
use std::io::Write; | |
fn prove<const N: usize, const M: usize, const S: usize>( | |
f: impl Fn([Scalar; N], [G1Affine; M]) -> [G1Affine; S], | |
g: [G1Affine; M], | |
x: [Scalar; N], | |
) -> ([G1Affine; S], [Scalar; N]) { | |
let r = array::from_fn(|_| Scalar::random(&mut thread_rng())); | |
let t = f(r, g); | |
let c = challenge(t); | |
let s = array::from_fn(|i| r[i] + c * x[i]); | |
(t, s) | |
} | |
fn verify<const N: usize, const M: usize, const S: usize>( | |
f: impl Fn([Scalar; N], [G1Affine; M]) -> [G1Affine; S], | |
g: [G1Affine; M], | |
y: [G1Affine; S], | |
r: [G1Affine; S], | |
s: [Scalar; N], | |
) -> bool { | |
let y = y.map(G1Projective::from); | |
let c = challenge(r); | |
let t = array::from_fn(|i| (c * y[i] + r[i]).to_affine()); | |
t == f(s, g) | |
} | |
fn challenge<const N: usize>(y: [G1Affine; N]) -> Scalar { | |
let mut engine = sha256::HashEngine::default(); | |
for point in y { | |
engine | |
.write_all(&point.to_compressed()) | |
.expect("Writing to hash engine can't fail"); | |
} | |
let hash = sha256::Hash::from_engine(engine); | |
map_hash_to_scalar(&hash) | |
} | |
fn map_hash_to_scalar(hash: &sha256::Hash) -> Scalar { | |
Scalar::random(&mut ChaChaRng::from_seed(hash.into_inner())) | |
} | |
fn pedersen_map(x: [Scalar; 2], g: [G1Affine; 2]) -> [G1Affine; 1] { | |
[(x[0] * g[0] + x[1] * g[1]).to_affine()] | |
} | |
fn issue_credential(x: [Scalar; 9], g: [G1Affine; 8]) -> [G1Affine; 6] { | |
let g = g.map(G1Projective::from); | |
let d = x[0]; | |
let m_1 = x[1]; | |
let m_2 = x[2]; | |
let m_3 = x[3]; | |
let o = x[4]; | |
let k_1 = x[5]; | |
let k_2 = x[6]; | |
let k_3 = x[7]; | |
let r_p = x[8]; | |
let rho = g[0]; | |
let g_1 = g[1]; | |
let h_1 = g[2]; | |
let h_2 = g[3]; | |
let h_3 = g[4]; | |
let h = g[5]; | |
let g_p = g[6]; | |
let g_h = g[7]; | |
let rho_tilde = d * g_1; | |
let c_m = (o * g_1) + (m_1 * h_1) + (m_2 * h_2) + (m_3 * h_3); | |
let c_1 = (k_1 * g_1) + (k_1 * rho) + (m_1 * h); | |
let c_2 = (k_2 * g_1) + (k_2 * rho) + (m_2 * h); | |
let c_3 = (k_3 * g_1) + (k_3 * rho) + (m_3 * h); | |
let p = (m_1 * g_p) + (r_p * g_h); | |
[rho_tilde, c_m, c_1, c_2, c_3, p].map(|y| y.to_affine()) | |
} | |
fn proof_credential(x: [Scalar; 4], g: [G1Affine; 6]) -> [G1Affine; 3] { | |
let g = g.map(G1Projective::from); | |
let m_1 = x[0]; | |
let m_2 = x[1]; | |
let r = x[2]; | |
let r_p = x[3]; | |
let beta_1 = g[0]; | |
let beta_2 = g[1]; | |
let g_2 = g[2]; | |
let h = g[3]; | |
let g_p = g[4]; | |
let g_h = g[5]; | |
let k = (m_1 * beta_1) + (m_2 * beta_2) + (r * g_2); | |
let v = r * h; | |
let p = (m_1 * g_p) + (r_p * g_h); | |
[k, v, p].map(|y| y.to_affine()) | |
} | |
#[cfg(test)] | |
mod tests { | |
use crate::{issue_credential, pedersen_map, proof_credential, prove, verify}; | |
use bls12_381::{G1Projective, Scalar}; | |
use core::array; | |
use ff::Field; | |
use group::{Curve, Group}; | |
use rand::thread_rng; | |
#[test] | |
fn test_pedersen_map() { | |
let g = array::from_fn(|_| G1Projective::random(&mut thread_rng()).to_affine()); | |
let x = array::from_fn(|_| Scalar::random(&mut thread_rng())); | |
let y = pedersen_map(x, g); | |
let (r, s) = prove(pedersen_map, g, x); | |
assert!(verify(pedersen_map, g, y, r, s)); | |
} | |
#[test] | |
fn test_issue_credential() { | |
let g = array::from_fn(|_| G1Projective::random(&mut thread_rng()).to_affine()); | |
let x = array::from_fn(|_| Scalar::random(&mut thread_rng())); | |
let y = issue_credential(x, g); | |
let (r, s) = prove(issue_credential, g, x); | |
assert!(verify(issue_credential, g, y, r, s)); | |
} | |
#[test] | |
fn test_proof_credential() { | |
let g = array::from_fn(|_| G1Projective::random(&mut thread_rng()).to_affine()); | |
let x = array::from_fn(|_| Scalar::random(&mut thread_rng())); | |
let y = proof_credential(x, g); | |
let (r, s) = prove(proof_credential, g, x); | |
assert!(verify(proof_credential, g, y, r, s)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment