schnorr_signatures/
lib.rs1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
2#![doc = include_str!("../README.md")]
3#![cfg_attr(not(feature = "std"), no_std)]
4
5use core::ops::Deref;
6#[cfg(not(feature = "std"))]
7#[macro_use]
8extern crate alloc;
9use std_shims::{
10 vec::Vec,
11 io::{self, Read, Write},
12};
13
14use rand_core::{RngCore, CryptoRng};
15
16use zeroize::{Zeroize, Zeroizing};
17
18use ciphersuite::{
19 group::{
20 ff::{Field, PrimeField},
21 Group, GroupEncoding,
22 },
23 Ciphersuite,
24};
25use multiexp::{multiexp_vartime, BatchVerifier};
26
27#[cfg(feature = "aggregate")]
29pub mod aggregate;
30
31#[cfg(test)]
32mod tests;
33
34#[allow(non_snake_case)]
43#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
44pub struct SchnorrSignature<C: Ciphersuite> {
45 pub R: C::G,
46 pub s: C::F,
47}
48
49impl<C: Ciphersuite> SchnorrSignature<C> {
50 pub fn read<R: Read>(reader: &mut R) -> io::Result<Self> {
52 Ok(SchnorrSignature { R: C::read_G(reader)?, s: C::read_F(reader)? })
53 }
54
55 pub fn write<W: Write>(&self, writer: &mut W) -> io::Result<()> {
57 writer.write_all(self.R.to_bytes().as_ref())?;
58 writer.write_all(self.s.to_repr().as_ref())
59 }
60
61 pub fn serialize(&self) -> Vec<u8> {
63 let mut buf = vec![];
64 self.write(&mut buf).unwrap();
65 buf
66 }
67
68 #[allow(clippy::needless_pass_by_value)] pub fn sign(
75 private_key: &Zeroizing<C::F>,
76 nonce: Zeroizing<C::F>,
77 challenge: C::F,
78 ) -> SchnorrSignature<C> {
79 SchnorrSignature {
80 R: C::generator() * nonce.deref(),
82 s: (challenge * private_key.deref()) + nonce.deref(),
83 }
84 }
85
86 pub fn batch_statements(&self, public_key: C::G, challenge: C::F) -> [(C::F, C::G); 3] {
89 [
93 (C::F::ONE, self.R),
95 (challenge, public_key),
97 (-self.s, C::generator()),
99 ]
100 }
101
102 #[must_use]
108 pub fn verify(&self, public_key: C::G, challenge: C::F) -> bool {
109 multiexp_vartime(&self.batch_statements(public_key, challenge)).is_identity().into()
110 }
111
112 pub fn batch_verify<R: RngCore + CryptoRng, I: Copy + Zeroize>(
118 &self,
119 rng: &mut R,
120 batch: &mut BatchVerifier<I, C::G>,
121 id: I,
122 public_key: C::G,
123 challenge: C::F,
124 ) {
125 batch.queue(rng, id, self.batch_statements(public_key, challenge));
126 }
127}