1use p256k1::{
2 field,
3 point::{Error as PointError, Point, G},
4 scalar::Scalar,
5};
6
7use crate::{common::Signature, compute};
8
9#[derive(Debug)]
11pub enum Error {
12 OddR,
14 Point(PointError),
16}
17
18#[allow(non_snake_case)]
20#[derive(Debug, PartialEq, Eq)]
21pub struct SchnorrProof {
22 pub r: field::Element,
24 pub s: Scalar,
26}
27
28impl SchnorrProof {
29 pub fn new(sig: &Signature) -> Result<Self, Error> {
31 if !sig.R.has_even_y() {
32 Err(Error::OddR)
33 } else {
34 Ok(Self {
35 r: sig.R.x(),
36 s: sig.z,
37 })
38 }
39 }
40
41 #[allow(non_snake_case)]
43 pub fn verify(&self, public_key: &field::Element, msg: &[u8]) -> bool {
44 let Y = match Point::lift_x(public_key) {
45 Ok(Y) => Y,
46 Err(_) => return false,
47 };
48 let R = match Point::lift_x(&self.r) {
49 Ok(R) => R,
50 Err(_) => return false,
51 };
52 let c = compute::challenge(&Y, &R, msg);
53 let Rp = self.s * G - c * Y;
54
55 Rp.x() == self.r
56 }
57
58 pub fn to_bytes(&self) -> [u8; 64] {
60 let mut bytes = [0u8; 64];
61
62 bytes[0..32].copy_from_slice(&self.r.to_bytes());
63 bytes[32..64].copy_from_slice(&self.s.to_bytes());
64
65 bytes
66 }
67}
68
69impl From<[u8; 64]> for SchnorrProof {
70 fn from(bytes: [u8; 64]) -> Self {
71 let mut r_bytes = [0u8; 32];
72 let mut s_bytes = [0u8; 32];
73
74 r_bytes.copy_from_slice(&bytes[0..32]);
75 s_bytes.copy_from_slice(&bytes[32..64]);
76
77 Self {
78 r: field::Element::from(r_bytes),
79 s: Scalar::from(s_bytes),
80 }
81 }
82}
83
84pub mod test_helpers {
86 use crate::{
87 common::{PolyCommitment, PublicNonce, SignatureShare},
88 errors::DkgError,
89 traits, Point,
90 };
91
92 use hashbrown::HashMap;
93 use rand_core::{CryptoRng, RngCore};
94
95 #[allow(non_snake_case)]
97 pub fn dkg<RNG: RngCore + CryptoRng, Signer: traits::Signer>(
98 signers: &mut [Signer],
99 rng: &mut RNG,
100 ) -> Result<Vec<PolyCommitment>, HashMap<usize, DkgError>> {
101 let mut A: Vec<PolyCommitment> = signers
102 .iter()
103 .flat_map(|s| s.get_poly_commitments(rng))
104 .collect();
105
106 loop {
108 let group_key = A.iter().fold(Point::new(), |s, a| s + a.A[0]);
109 if group_key.has_even_y() {
110 break;
111 }
112
113 for signer in signers.iter_mut() {
114 signer.reset_polys(rng);
115 }
116
117 A = signers
118 .iter()
119 .flat_map(|s| s.get_poly_commitments(rng))
120 .collect();
121 }
122
123 let mut private_shares = HashMap::new();
124 for signer in signers.iter() {
125 for (signer_id, signer_shares) in signer.get_shares() {
126 private_shares.insert(signer_id, signer_shares);
127 }
128 }
129
130 let mut secret_errors = HashMap::new();
131 for signer in signers.iter_mut() {
132 if let Err(signer_secret_errors) = signer.compute_secrets(&private_shares, &A) {
133 secret_errors.extend(signer_secret_errors.into_iter());
134 }
135 }
136
137 if secret_errors.is_empty() {
138 Ok(A)
139 } else {
140 Err(secret_errors)
141 }
142 }
143
144 #[allow(non_snake_case)]
146 pub fn sign<RNG: RngCore + CryptoRng, Signer: traits::Signer>(
147 msg: &[u8],
148 signers: &mut [Signer],
149 rng: &mut RNG,
150 ) -> (Vec<PublicNonce>, Vec<SignatureShare>) {
151 let signer_ids: Vec<usize> = signers.iter().map(|s| s.get_id()).collect();
152 let key_ids: Vec<usize> = signers.iter().flat_map(|s| s.get_key_ids()).collect();
153 let mut nonces: Vec<PublicNonce> =
154 signers.iter_mut().flat_map(|s| s.gen_nonces(rng)).collect();
155
156 loop {
157 let (_, R) = Signer::compute_intermediate(msg, &signer_ids, &key_ids, &nonces);
158 if R.has_even_y() {
159 break;
160 }
161 nonces = signers.iter_mut().flat_map(|s| s.gen_nonces(rng)).collect();
162 }
163
164 let shares = signers
165 .iter()
166 .flat_map(|s| s.sign(msg, &signer_ids, &key_ids, &nonces))
167 .collect();
168
169 (nonces, shares)
170 }
171}
172
173#[cfg(test)]
174mod test {
175 use super::{test_helpers, SchnorrProof};
176
177 use crate::{traits::Signer, v1, v2};
178 use rand_core::OsRng;
179
180 #[test]
181 #[allow(non_snake_case)]
182 fn test_schnorr_sign_verify_v1() {
183 let mut rng = OsRng::default();
184
185 let msg = "It was many and many a year ago".as_bytes();
187 let N: usize = 10;
188 let T: usize = 7;
189 let signer_ids: Vec<Vec<usize>> = [
190 [0, 1, 2].to_vec(),
191 [3, 4].to_vec(),
192 [5, 6, 7].to_vec(),
193 [8, 9].to_vec(),
194 ]
195 .to_vec();
196 let mut signers: Vec<v1::Signer> = signer_ids
197 .iter()
198 .map(|ids| v1::Signer::new(ids, N, T, &mut rng))
199 .collect();
200
201 let A = match test_helpers::dkg(&mut signers, &mut rng) {
202 Ok(A) => A,
203 Err(secret_errors) => {
204 panic!("Got secret errors from DKG: {:?}", secret_errors);
205 }
206 };
207
208 let mut S = [signers[0].clone(), signers[1].clone(), signers[3].clone()].to_vec();
209 let mut sig_agg =
210 v1::SignatureAggregator::new(N, T, A.clone()).expect("aggregator ctor failed");
211
212 let (nonces, sig_shares) = test_helpers::sign(&msg, &mut S, &mut rng);
213 let sig = match sig_agg.sign(&msg, &nonces, &sig_shares) {
214 Err(e) => panic!("Aggregator sign failed: {:?}", e),
215 Ok(sig) => sig,
216 };
217
218 let proof = SchnorrProof::new(&sig).unwrap();
220
221 assert!(proof.verify(&sig_agg.poly[0].x(), msg));
222
223 let proof_bytes = proof.to_bytes();
225 let proof_deser = SchnorrProof::from(proof_bytes);
226
227 assert_eq!(proof, proof_deser);
228 assert!(proof_deser.verify(&sig_agg.poly[0].x(), msg));
229 }
230
231 #[test]
232 #[allow(non_snake_case)]
233 fn test_schnorr_sign_verify_v2() {
234 let mut rng = OsRng::default();
235
236 let msg = "It was many and many a year ago".as_bytes();
238 let Nk: usize = 10;
239 let Np: usize = 4;
240 let T: usize = 7;
241 let signer_ids: Vec<Vec<usize>> = [
242 [0, 1, 2].to_vec(),
243 [3, 4].to_vec(),
244 [5, 6, 7].to_vec(),
245 [8, 9].to_vec(),
246 ]
247 .to_vec();
248 let mut signers: Vec<v2::Signer> = signer_ids
249 .iter()
250 .enumerate()
251 .map(|(id, ids)| v2::Signer::new(id, ids, Np, Nk, T, &mut rng))
252 .collect();
253
254 let A = match test_helpers::dkg(&mut signers, &mut rng) {
255 Ok(A) => A,
256 Err(secret_errors) => {
257 panic!("Got secret errors from DKG: {:?}", secret_errors);
258 }
259 };
260
261 let mut S = [signers[0].clone(), signers[1].clone(), signers[3].clone()].to_vec();
262 let key_ids = S
263 .iter()
264 .flat_map(|s| s.get_key_ids())
265 .collect::<Vec<usize>>();
266 let mut sig_agg =
267 v2::SignatureAggregator::new(Nk, T, A.clone()).expect("aggregator ctor failed");
268
269 let (nonces, sig_shares) = test_helpers::sign(&msg, &mut S, &mut rng);
270 let sig = match sig_agg.sign(&msg, &nonces, &sig_shares, &key_ids) {
271 Err(e) => panic!("Aggregator sign failed: {:?}", e),
272 Ok(sig) => sig,
273 };
274
275 let proof = SchnorrProof::new(&sig).unwrap();
277
278 assert!(proof.verify(&sig_agg.poly[0].x(), msg));
279
280 let proof_bytes = proof.to_bytes();
282 let proof_deser = SchnorrProof::from(proof_bytes);
283
284 assert_eq!(proof, proof_deser);
285 assert!(proof_deser.verify(&sig_agg.poly[0].x(), msg));
286 }
287}