arnaucube
arnaucube/schnorrPublic Self-hosted repository
schnorr/src/schnorr.rs
src/schnorr.rsRaw
  1use plonky2::hash::poseidon::PoseidonHash;
  2use plonky2::field::goldilocks_field::GoldilocksField;
  3use plonky2::field::types::Field;
  4use plonky2::plonk::config::Hasher;
  5use plonky2::field::types::PrimeField64;
  6use rand;
  7use rand::Rng;
  8
  9const BIG_GROUP_GEN: GoldilocksField = GoldilocksField(14293326489335486720);
 10
 11#[derive(Copy, Clone, Debug)]
 12pub struct SchnorrSigner {
 13    PRIME_GROUP_GEN: GoldilocksField,
 14    PRIME_GROUP_ORDER: u64,
 15}
 16
 17#[derive(Copy, Clone, Debug)]
 18
 19pub struct SchnorrSecretKey {
 20    pub sk: u64,
 21}
 22
 23#[derive(Copy, Clone, Debug)]
 24pub struct SchnorrPublicKey {
 25    pub pk: GoldilocksField,
 26}
 27
 28#[derive(Copy, Clone, Debug)]
 29pub struct SchnorrSignature {
 30    pub s: u64,
 31    pub e: u64,
 32}
 33
 34impl SchnorrSigner{
 35    pub fn new() -> Self {
 36        let quotient_order: u64 = (1 << 48) - (1 << 32);
 37        let PRIME_GROUP_GEN: GoldilocksField = Self::pow(BIG_GROUP_GEN, quotient_order);
 38        let PRIME_GROUP_ORDER: u64 = (1 << 16) + 1;
 39        SchnorrSigner{PRIME_GROUP_GEN, PRIME_GROUP_ORDER}
 40    }
 41
 42    fn pow(x: GoldilocksField, a: u64) -> GoldilocksField {
 43        let mut a_copy = a;
 44        let mut res = GoldilocksField(1);
 45        let mut x_pow_2n = x.clone();
 46        while (a_copy > 0) {
 47            if (a_copy % 2 != 0) {
 48                res *= x_pow_2n;
 49            }
 50            a_copy /= 2;
 51            x_pow_2n *= x_pow_2n;
 52        }
 53        res
 54    }
 55
 56    pub fn keygen(&self, sk: &SchnorrSecretKey) -> SchnorrPublicKey {
 57        let pk: GoldilocksField = Self::pow(self.PRIME_GROUP_GEN, sk.sk).inverse();
 58        println!("{:?}", self.PRIME_GROUP_GEN);
 59        // self.PRIME_GROUP_GEN is 6612579038192137166
 60        SchnorrPublicKey{pk: pk}
 61    }
 62
 63    fn hash_insecure(&self, r: &GoldilocksField, msg: &Vec<GoldilocksField>) -> u64 {
 64        let poseidon_input: Vec<GoldilocksField> = std::iter::once(r)
 65            .chain(msg.iter())
 66            .copied()
 67            .collect();
 68
 69        println!("Running hash on concatenated elts: {:?}", poseidon_input);
 70        let h = PoseidonHash::hash_no_pad(&poseidon_input);
 71        h.elements[0].to_canonical_u64() % self.PRIME_GROUP_ORDER
 72    }
 73
 74    fn rand_group_multiplier(&self, rng: &mut rand::rngs::ThreadRng) -> u64 {
 75        let group_order: u64 = (1 << 16) + 1;
 76        rng.gen_range(0..group_order)
 77    }
 78
 79    pub fn u64_into_goldilocks_vec(&self, msg: Vec<u64>) -> Vec<GoldilocksField> {
 80        msg.into_iter()
 81            .map(|x| GoldilocksField::from_noncanonical_u64(x))
 82            .collect()
 83    }
 84
 85    pub fn sign(&self, msg: &Vec<GoldilocksField>, sk: &SchnorrSecretKey, rng: &mut rand::rngs::ThreadRng) -> SchnorrSignature {
 86        let k: u64 = self.rand_group_multiplier(rng);
 87        let r: GoldilocksField = Self::pow(self.PRIME_GROUP_GEN, k);
 88        let e: u64 = self.hash_insecure(&r, msg);
 89        assert!(k < self.PRIME_GROUP_ORDER);
 90        assert!(sk.sk < self.PRIME_GROUP_ORDER);
 91        assert!(e < self.PRIME_GROUP_ORDER);
 92        //println!("Super secret k: {:?}", k);
 93        //println!("Super secret r: {:?}", r);
 94        //println!("PRIME_GROUP_ORDER: {:?}", self.PRIME_GROUP_ORDER);
 95        let mut s128: u128 = ((k as u128) + (sk.sk as u128) * (e as u128));
 96        s128 %= self.PRIME_GROUP_ORDER as u128;
 97        let s: u64 = s128 as u64;
 98        SchnorrSignature{e, s}
 99    }
100
101    pub fn verify(&self, sig: &SchnorrSignature, msg: &Vec<GoldilocksField>, pk: &SchnorrPublicKey) -> bool {
102        let r: GoldilocksField = Self::pow(self.PRIME_GROUP_GEN, sig.s)
103            * Self::pow(pk.pk, sig.e);
104        let e_v: u64 = self.hash_insecure(&r, msg);
105        e_v == sig.e
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    use plonky2::field::goldilocks_field::GoldilocksField;
112
113    use crate::schnorr::{SchnorrPublicKey, SchnorrSecretKey, SchnorrSigner, SchnorrSignature};
114
115    #[test]
116    fn test_pow() {
117        let g = GoldilocksField(3);
118        let res = GoldilocksField(16305451354880172407);
119        assert_eq!(res, SchnorrSigner::pow(g, 1234567));
120    }
121
122    #[test]
123    fn test_sig() {
124        let mut rng: rand::rngs::ThreadRng = rand::thread_rng();
125        let ss = SchnorrSigner::new();
126        let sk: SchnorrSecretKey = SchnorrSecretKey{ sk: 1422 };
127        let pk: SchnorrPublicKey = ss.keygen(&sk);
128
129        let msg0_u64: Vec<u64> = vec![17, 123985, 3, 12];
130        let msg0: Vec<GoldilocksField> = ss.u64_into_goldilocks_vec(msg0_u64);
131        let sig: SchnorrSignature = ss.sign(&msg0, &sk, &mut rng);
132        let res: bool = ss.verify(&sig, &msg0, &pk);
133        println!("Trying to verify:");
134        println!("Secret key: {:?}", sk);
135        println!("Public key: {:?}", pk);
136        println!("Signature: {:?}", sig);
137        assert!(res);
138    }
139}