1use alloc::vec::Vec;
5use core::{
6 cmp::Ordering,
7 hash::{Hash, Hasher},
8 ops::{Add, Mul},
9};
10
11use rand_core::{CryptoRng, RngCore};
12use snafu::prelude::*;
13use tari_utilities::ByteArray;
14
15use crate::{
16 alloc::borrow::ToOwned,
17 commitment::{HomomorphicCommitment, HomomorphicCommitmentFactory},
18 keys::{PublicKey, SecretKey},
19 signatures::SchnorrSignature,
20};
21
22#[derive(Clone, Debug, Snafu, PartialEq, Eq)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25#[allow(missing_docs)]
26pub enum CommitmentAndPublicKeySignatureError {
27 #[snafu(display("An invalid challenge was provided"))]
28 InvalidChallenge,
29}
30
31#[derive(Debug, Clone)]
60#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))]
61#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
62pub struct CommitmentAndPublicKeySignature<P, K> {
63 pub(crate) ephemeral_commitment: HomomorphicCommitment<P>,
64 pub(crate) ephemeral_pubkey: P,
65 pub(crate) u_a: K,
66 pub(crate) u_x: K,
67 pub(crate) u_y: K,
68}
69
70impl<P, K> CommitmentAndPublicKeySignature<P, K>
71where
72 P: PublicKey<K = K>,
73 K: SecretKey,
74{
75 pub fn new(ephemeral_commitment: HomomorphicCommitment<P>, ephemeral_pubkey: P, u_a: K, u_x: K, u_y: K) -> Self {
77 CommitmentAndPublicKeySignature {
78 ephemeral_commitment,
79 ephemeral_pubkey,
80 u_a,
81 u_x,
82 u_y,
83 }
84 }
85
86 #[allow(clippy::too_many_arguments)]
90 pub fn sign<C>(
91 a: &K,
92 x: &K,
93 y: &K,
94 r_a: &K,
95 r_x: &K,
96 r_y: &K,
97 challenge: &[u8],
98 factory: &C,
99 ) -> Result<Self, CommitmentAndPublicKeySignatureError>
100 where
101 K: Mul<P, Output = P>,
102 for<'a> &'a K: Add<&'a K, Output = K>,
103 for<'a> &'a K: Mul<&'a K, Output = K>,
104 C: HomomorphicCommitmentFactory<P = P>,
105 {
106 let e = match K::from_uniform_bytes(challenge) {
108 Ok(e) => e,
109 Err(_) => return Err(CommitmentAndPublicKeySignatureError::InvalidChallenge),
110 };
111
112 if e == K::default() {
114 return Err(CommitmentAndPublicKeySignatureError::InvalidChallenge);
115 }
116
117 let ea = &e * a;
119 let ex = &e * x;
120 let ey = &e * y;
121
122 let u_a = r_a + &ea;
123 let u_x = r_x + &ex;
124 let u_y = r_y + &ey;
125
126 let ephemeral_commitment = factory.commit(r_x, r_a);
128 let ephemeral_pubkey = P::from_secret_key(r_y);
129
130 Ok(Self::new(ephemeral_commitment, ephemeral_pubkey, u_a, u_x, u_y))
131 }
132
133 pub fn verify_challenge<'a, C, R>(
135 &self,
136 commitment: &'a HomomorphicCommitment<P>,
137 pubkey: &'a P,
138 challenge: &[u8],
139 factory: &C,
140 rng: &mut R,
141 ) -> bool
142 where
143 for<'b> &'a HomomorphicCommitment<P>: Mul<&'b K, Output = HomomorphicCommitment<P>>,
144 for<'b> &'b P: Mul<&'b K, Output = P>,
145 for<'b> &'b HomomorphicCommitment<P>: Add<&'b HomomorphicCommitment<P>, Output = HomomorphicCommitment<P>>,
146 for<'b> &'b P: Add<&'b P, Output = P>,
147 for<'b> &'b K: Mul<&'b K, Output = K>,
148 for<'b> &'b K: Add<&'b K, Output = K>,
149 C: HomomorphicCommitmentFactory<P = P>,
150 R: RngCore + CryptoRng,
151 {
152 let e = match K::from_uniform_bytes(challenge) {
154 Ok(e) => e,
155 Err(_) => return false,
156 };
157
158 self.verify(commitment, pubkey, &e, factory, rng)
159 }
160
161 pub fn verify<'a, C, R>(
163 &self,
164 commitment: &'a HomomorphicCommitment<P>,
165 pubkey: &'a P,
166 challenge: &K,
167 factory: &C,
168 rng: &mut R,
169 ) -> bool
170 where
171 for<'b> &'a HomomorphicCommitment<P>: Mul<&'b K, Output = HomomorphicCommitment<P>>,
172 for<'b> &'b P: Mul<&'b K, Output = P>,
173 for<'b> &'b HomomorphicCommitment<P>: Add<&'b HomomorphicCommitment<P>, Output = HomomorphicCommitment<P>>,
174 for<'b> &'b P: Add<&'b P, Output = P>,
175 for<'b> &'b K: Mul<&'b K, Output = K>,
176 for<'b> &'b K: Add<&'b K, Output = K>,
177 C: HomomorphicCommitmentFactory<P = P>,
178 R: RngCore + CryptoRng,
179 {
180 if commitment.as_public_key() == &P::default() || pubkey == &P::default() {
182 return false;
183 }
184
185 if *challenge == K::default() {
187 return false;
188 }
189
190 let w = K::random(rng); let verifier_lhs = factory
197 .commit(&(&self.u_x + &(&w * &self.u_y)), &self.u_a)
198 .as_public_key()
199 .to_owned();
200 let verifier_rhs_unweighted =
201 self.ephemeral_commitment.as_public_key() + (commitment * challenge).as_public_key();
202 let verifier_rhs_weighted = &self.ephemeral_pubkey * &w + pubkey * &(&w * challenge);
203
204 verifier_lhs == verifier_rhs_unweighted + verifier_rhs_weighted
205 }
206
207 pub fn complete_signature_tuple(&self) -> (&HomomorphicCommitment<P>, &P, &K, &K, &K) {
209 (
210 &self.ephemeral_commitment,
211 &self.ephemeral_pubkey,
212 &self.u_a,
213 &self.u_x,
214 &self.u_y,
215 )
216 }
217
218 pub fn u_a(&self) -> &K {
220 &self.u_a
221 }
222
223 pub fn u_x(&self) -> &K {
225 &self.u_x
226 }
227
228 pub fn u_y(&self) -> &K {
230 &self.u_y
231 }
232
233 pub fn ephemeral_commitment(&self) -> &HomomorphicCommitment<P> {
235 &self.ephemeral_commitment
236 }
237
238 pub fn ephemeral_pubkey(&self) -> &P {
240 &self.ephemeral_pubkey
241 }
242
243 pub fn to_vec(&self) -> Vec<u8> {
245 let mut buf = Vec::with_capacity(2 * P::key_length() + 3 * K::key_length());
246 buf.extend_from_slice(self.ephemeral_commitment().as_bytes());
247 buf.extend_from_slice(self.ephemeral_pubkey().as_bytes());
248 buf.extend_from_slice(self.u_a().as_bytes());
249 buf.extend_from_slice(self.u_x().as_bytes());
250 buf.extend_from_slice(self.u_y().as_bytes());
251 buf
252 }
253}
254
255impl<'a, 'b, P, K> Add<&'b CommitmentAndPublicKeySignature<P, K>> for &'a CommitmentAndPublicKeySignature<P, K>
256where
257 P: PublicKey<K = K>,
258 &'a HomomorphicCommitment<P>: Add<&'b HomomorphicCommitment<P>, Output = HomomorphicCommitment<P>>,
259 &'a P: Add<&'b P, Output = P>,
260 K: SecretKey,
261 &'a K: Add<&'b K, Output = K>,
262{
263 type Output = CommitmentAndPublicKeySignature<P, K>;
264
265 fn add(self, rhs: &'b CommitmentAndPublicKeySignature<P, K>) -> CommitmentAndPublicKeySignature<P, K> {
266 let ephemeral_commitment_sum = self.ephemeral_commitment() + rhs.ephemeral_commitment();
267 let ephemeral_pubkey_sum_sum = self.ephemeral_pubkey() + rhs.ephemeral_pubkey();
268 let u_a_sum = self.u_a() + rhs.u_a();
269 let u_x_sum = self.u_x() + rhs.u_x();
270 let u_y_sum = self.u_y() + rhs.u_y();
271
272 CommitmentAndPublicKeySignature::new(
273 ephemeral_commitment_sum,
274 ephemeral_pubkey_sum_sum,
275 u_a_sum,
276 u_x_sum,
277 u_y_sum,
278 )
279 }
280}
281
282impl<'a, P, K> Add<CommitmentAndPublicKeySignature<P, K>> for &'a CommitmentAndPublicKeySignature<P, K>
283where
284 P: PublicKey<K = K>,
285 for<'b> &'a HomomorphicCommitment<P>: Add<&'b HomomorphicCommitment<P>, Output = HomomorphicCommitment<P>>,
286 for<'b> &'a P: Add<&'b P, Output = P>,
287 K: SecretKey,
288 for<'b> &'a K: Add<&'b K, Output = K>,
289{
290 type Output = CommitmentAndPublicKeySignature<P, K>;
291
292 fn add(self, rhs: CommitmentAndPublicKeySignature<P, K>) -> CommitmentAndPublicKeySignature<P, K> {
293 let ephemeral_commitment_sum = self.ephemeral_commitment() + rhs.ephemeral_commitment();
294 let ephemeral_pubkey_sum_sum = self.ephemeral_pubkey() + rhs.ephemeral_pubkey();
295 let u_a_sum = self.u_a() + rhs.u_a();
296 let u_x_sum = self.u_x() + rhs.u_x();
297 let u_y_sum = self.u_y() + rhs.u_y();
298
299 CommitmentAndPublicKeySignature::new(
300 ephemeral_commitment_sum,
301 ephemeral_pubkey_sum_sum,
302 u_a_sum,
303 u_x_sum,
304 u_y_sum,
305 )
306 }
307}
308
309impl<'a, 'b, P, K> Add<&'b SchnorrSignature<P, K>> for &'a CommitmentAndPublicKeySignature<P, K>
310where
311 P: PublicKey<K = K>,
312 &'a HomomorphicCommitment<P>: Add<&'b HomomorphicCommitment<P>, Output = HomomorphicCommitment<P>>,
313 &'a P: Add<&'b P, Output = P>,
314 K: SecretKey,
315 &'a K: Add<&'b K, Output = K>,
316{
317 type Output = CommitmentAndPublicKeySignature<P, K>;
318
319 fn add(self, rhs: &'b SchnorrSignature<P, K>) -> CommitmentAndPublicKeySignature<P, K> {
320 let ephemeral_commitment_sum = self.ephemeral_commitment().clone();
321 let ephemeral_pubkey_sum_sum = self.ephemeral_pubkey() + rhs.get_public_nonce();
322 let u_a_sum = self.u_a().clone();
323 let u_x_sum = self.u_x().clone();
324 let u_y_sum = self.u_y() + rhs.get_signature();
325
326 CommitmentAndPublicKeySignature::new(
327 ephemeral_commitment_sum,
328 ephemeral_pubkey_sum_sum,
329 u_a_sum,
330 u_x_sum,
331 u_y_sum,
332 )
333 }
334}
335
336impl<'a, P, K> Add<SchnorrSignature<P, K>> for &'a CommitmentAndPublicKeySignature<P, K>
337where
338 P: PublicKey<K = K>,
339 for<'b> &'a HomomorphicCommitment<P>: Add<&'b HomomorphicCommitment<P>, Output = HomomorphicCommitment<P>>,
340 for<'b> &'a P: Add<&'b P, Output = P>,
341 K: SecretKey,
342 for<'b> &'a K: Add<&'b K, Output = K>,
343{
344 type Output = CommitmentAndPublicKeySignature<P, K>;
345
346 fn add(self, rhs: SchnorrSignature<P, K>) -> CommitmentAndPublicKeySignature<P, K> {
347 let ephemeral_commitment_sum = self.ephemeral_commitment().clone();
348 let ephemeral_pubkey_sum_sum = self.ephemeral_pubkey() + rhs.get_public_nonce();
349 let u_a_sum = self.u_a().clone();
350 let u_x_sum = self.u_x().clone();
351 let u_y_sum = self.u_y() + rhs.get_signature();
352
353 CommitmentAndPublicKeySignature::new(
354 ephemeral_commitment_sum,
355 ephemeral_pubkey_sum_sum,
356 u_a_sum,
357 u_x_sum,
358 u_y_sum,
359 )
360 }
361}
362
363impl<P, K> Default for CommitmentAndPublicKeySignature<P, K>
364where
365 P: PublicKey<K = K>,
366 K: SecretKey,
367{
368 fn default() -> Self {
369 CommitmentAndPublicKeySignature::new(
370 HomomorphicCommitment::<P>::default(),
371 P::default(),
372 K::default(),
373 K::default(),
374 K::default(),
375 )
376 }
377}
378
379impl<P, K> Ord for CommitmentAndPublicKeySignature<P, K>
382where
383 P: PublicKey<K = K>,
384 K: SecretKey,
385{
386 fn cmp(&self, other: &Self) -> Ordering {
387 let mut compare = self.ephemeral_commitment().cmp(other.ephemeral_commitment());
388 if compare != Ordering::Equal {
389 return compare;
390 }
391
392 compare = self.ephemeral_pubkey().cmp(other.ephemeral_pubkey());
393 if compare != Ordering::Equal {
394 return compare;
395 }
396
397 compare = self.u_a().as_bytes().cmp(other.u_a().as_bytes());
398 if compare != Ordering::Equal {
399 return compare;
400 }
401
402 compare = self.u_x().as_bytes().cmp(other.u_x().as_bytes());
403 if compare != Ordering::Equal {
404 return compare;
405 }
406
407 self.u_y().as_bytes().cmp(other.u_y().as_bytes())
408 }
409}
410
411impl<P, K> PartialOrd for CommitmentAndPublicKeySignature<P, K>
412where
413 P: PublicKey<K = K>,
414 K: SecretKey,
415{
416 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
417 Some(self.cmp(other))
418 }
419}
420
421impl<P, K> PartialEq for CommitmentAndPublicKeySignature<P, K>
422where
423 P: PublicKey<K = K>,
424 K: SecretKey,
425{
426 fn eq(&self, other: &Self) -> bool {
427 self.ephemeral_commitment().eq(other.ephemeral_commitment()) &&
428 self.ephemeral_pubkey().eq(other.ephemeral_pubkey()) &&
429 self.u_a().eq(other.u_a()) &&
430 self.u_x().eq(other.u_x()) &&
431 self.u_y().eq(other.u_y())
432 }
433}
434
435impl<P, K> Eq for CommitmentAndPublicKeySignature<P, K>
436where
437 P: PublicKey<K = K>,
438 K: SecretKey,
439{
440}
441
442impl<P, K> Hash for CommitmentAndPublicKeySignature<P, K>
443where
444 P: PublicKey<K = K>,
445 K: SecretKey,
446{
447 fn hash<H: Hasher>(&self, state: &mut H) {
448 state.write(&self.to_vec())
449 }
450}