2022-05-25 00:22:00 -04:00
|
|
|
use rand_core::{RngCore, CryptoRng};
|
|
|
|
|
|
2022-06-28 01:25:26 -04:00
|
|
|
use group::{ff::{Field, PrimeField}, GroupEncoding};
|
2022-05-25 00:22:00 -04:00
|
|
|
|
2022-05-27 00:52:44 -04:00
|
|
|
use multiexp::BatchVerifier;
|
|
|
|
|
|
2022-06-30 18:46:18 -04:00
|
|
|
use crate::{Curve, F_len, G_len};
|
2022-05-25 00:22:00 -04:00
|
|
|
|
|
|
|
|
#[allow(non_snake_case)]
|
|
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
|
|
|
|
pub struct SchnorrSignature<C: Curve> {
|
|
|
|
|
pub R: C::G,
|
|
|
|
|
pub s: C::F,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<C: Curve> SchnorrSignature<C> {
|
|
|
|
|
pub fn serialize(&self) -> Vec<u8> {
|
2022-06-30 18:46:18 -04:00
|
|
|
let mut res = Vec::with_capacity(G_len::<C>() + F_len::<C>());
|
2022-06-28 01:25:26 -04:00
|
|
|
res.extend(self.R.to_bytes().as_ref());
|
|
|
|
|
res.extend(self.s.to_repr().as_ref());
|
2022-05-25 00:22:00 -04:00
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn sign<C: Curve>(
|
|
|
|
|
private_key: C::F,
|
|
|
|
|
nonce: C::F,
|
|
|
|
|
challenge: C::F
|
|
|
|
|
) -> SchnorrSignature<C> {
|
|
|
|
|
SchnorrSignature {
|
2022-06-30 18:46:18 -04:00
|
|
|
R: C::GENERATOR * nonce,
|
2022-05-25 00:22:00 -04:00
|
|
|
s: nonce + (private_key * challenge)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn verify<C: Curve>(
|
|
|
|
|
public_key: C::G,
|
|
|
|
|
challenge: C::F,
|
|
|
|
|
signature: &SchnorrSignature<C>
|
|
|
|
|
) -> bool {
|
2022-06-30 18:46:18 -04:00
|
|
|
(C::GENERATOR * signature.s) == (signature.R + (public_key * challenge))
|
2022-05-25 00:22:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn batch_verify<C: Curve, R: RngCore + CryptoRng>(
|
|
|
|
|
rng: &mut R,
|
|
|
|
|
triplets: &[(u16, C::G, C::F, SchnorrSignature<C>)]
|
|
|
|
|
) -> Result<(), u16> {
|
2022-06-03 23:22:08 -04:00
|
|
|
let mut values = [(C::F::one(), C::GENERATOR); 3];
|
2022-06-30 09:30:24 -04:00
|
|
|
let mut batch = BatchVerifier::new(triplets.len());
|
2022-05-25 00:22:00 -04:00
|
|
|
for triple in triplets {
|
2022-05-27 02:01:01 -04:00
|
|
|
// s = r + ca
|
|
|
|
|
// sG == R + cA
|
|
|
|
|
// R + cA - sG == 0
|
|
|
|
|
|
2022-05-27 00:52:44 -04:00
|
|
|
// R
|
|
|
|
|
values[0].1 = triple.3.R;
|
|
|
|
|
// cA
|
|
|
|
|
values[1] = (triple.2, triple.1);
|
|
|
|
|
// -sG
|
|
|
|
|
values[2].0 = -triple.3.s;
|
2022-05-25 00:22:00 -04:00
|
|
|
|
2022-05-27 00:52:44 -04:00
|
|
|
batch.queue(rng, triple.0, values);
|
2022-05-25 00:22:00 -04:00
|
|
|
}
|
|
|
|
|
|
2022-05-27 02:01:01 -04:00
|
|
|
batch.verify_vartime_with_vartime_blame()
|
2022-05-25 00:22:00 -04:00
|
|
|
}
|