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)]
12struct SchnorrSigner {
13 PRIME_GROUP_GEN: GoldilocksField,
14 PRIME_GROUP_ORDER: u64,
15}
16
17#[derive(Copy, Clone, Debug)]
18
19struct SchnorrSecretKey {
20 sk: u64,
21}
22
23#[derive(Copy, Clone, Debug)]
24struct SchnorrPublicKey {
25 pk: GoldilocksField,
26}
27
28#[derive(Copy, Clone, Debug)]
29struct SchnorrSignature {
30 s: u64,
31 e: u64,
32}
33
34impl SchnorrSigner{
35 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 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 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 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 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 println!("NOT IMPLEMENTED");
125 let mut rng: rand::rngs::ThreadRng = rand::thread_rng();
126 let ss = SchnorrSigner::new();
127 let sk: SchnorrSecretKey = SchnorrSecretKey{ sk: 1422 };
128 let pk: SchnorrPublicKey = ss.keygen(&sk);
129
130 let msg0_u64: Vec<u64> = vec![17, 123985, 3, 12];
131 let msg0: Vec<GoldilocksField> = ss.u64_into_goldilocks_vec(msg0_u64);
132 let sig: SchnorrSignature = ss.sign(&msg0, &sk, &mut rng);
133 let res: bool = ss.verify(&sig, &msg0, &pk);
134 println!("Trying to verify:");
135 println!("Secret key: {:?}", sk);
136 println!("Public key: {:?}", pk);
137 println!("Signature: {:?}", sig);
138 assert!(res);
139 }
140}