Skip to content

Instantly share code, notes, and snippets.

@callebtc
Forked from joschisan/proofs.rs
Created February 29, 2024 19:43
Show Gist options
  • Save callebtc/6e624a4905f8a407cccff12c47fa3e07 to your computer and use it in GitHub Desktop.
Save callebtc/6e624a4905f8a407cccff12c47fa3e07 to your computer and use it in GitHub Desktop.
Sigma Protocol Proofs
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