Make Schnorr modular to its transcript

This commit is contained in:
Luke Parker
2023-03-07 05:30:21 -05:00
parent 6bff3866ea
commit 837c776297
6 changed files with 43 additions and 27 deletions

View File

@@ -127,28 +127,42 @@ pub trait Hram<C: Curve>: Send + Clone {
fn hram(R: &C::G, A: &C::G, m: &[u8]) -> C::F;
}
/// IETF-compliant Schnorr signature algorithm ((R, s) where s = r + cx).
/// Schnorr signature algorithm ((R, s) where s = r + cx).
#[derive(Clone)]
pub struct Schnorr<C: Curve, H: Hram<C>> {
transcript: IetfTranscript,
pub struct Schnorr<C: Curve, T: Clone + Debug + Transcript, H: Hram<C>> {
transcript: T,
c: Option<C::F>,
_hram: PhantomData<H>,
}
impl<C: Curve, H: Hram<C>> Default for Schnorr<C, H> {
fn default() -> Self {
Self::new()
/// IETF-compliant Schnorr signature algorithm.
///
/// This algorithm specifically uses the transcript format defined in the FROST IETF draft.
/// It's a naive transcript format not viable for usage in larger protocols, yet is presented here
/// in order to provide compatibility.
///
/// Usage of this with key offsets will break the intended compatibility as the IETF draft does not
/// specify a protocol for offsets.
pub type IetfSchnorr<C, H> = Schnorr<C, IetfTranscript, H>;
impl<C: Curve, T: Clone + Debug + Transcript, H: Hram<C>> Schnorr<C, T, H> {
/// Construct a Schnorr algorithm continuing the specified transcript.
pub fn new(transcript: T) -> Schnorr<C, T, H> {
Schnorr { transcript, c: None, _hram: PhantomData }
}
}
impl<C: Curve, H: Hram<C>> Schnorr<C, H> {
pub fn new() -> Schnorr<C, H> {
Schnorr { transcript: IetfTranscript(vec![]), c: None, _hram: PhantomData }
impl<C: Curve, H: Hram<C>> IetfSchnorr<C, H> {
/// Construct a IETF-compatible Schnorr algorithm.
///
/// Please see the IetfSchnorr documentation for the full details of this.
pub fn ietf() -> IetfSchnorr<C, H> {
Schnorr::new(IetfTranscript(vec![]))
}
}
impl<C: Curve, H: Hram<C>> Algorithm<C> for Schnorr<C, H> {
type Transcript = IetfTranscript;
impl<C: Curve, T: Clone + Debug + Transcript, H: Hram<C>> Algorithm<C> for Schnorr<C, T, H> {
type Transcript = T;
type Addendum = ();
type Signature = SchnorrSignature<C>;

View File

@@ -6,7 +6,7 @@ pub use dkg::tests::{key_gen, recover_key};
use crate::{
Curve, Participant, ThresholdKeys, FrostError,
algorithm::{Algorithm, Hram, Schnorr},
algorithm::{Algorithm, Hram, IetfSchnorr},
sign::{Writable, PreprocessMachine, SignMachine, SignatureMachine, AlgorithmMachine},
};
@@ -197,8 +197,8 @@ pub fn test_schnorr<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mut R) {
const MSG: &[u8] = b"Hello, World!";
let keys = key_gen(&mut *rng);
let machines = algorithm_machines(&mut *rng, Schnorr::<C, H>::new(), &keys);
let sig = sign(&mut *rng, Schnorr::<C, H>::new(), keys.clone(), machines, MSG);
let machines = algorithm_machines(&mut *rng, IetfSchnorr::<C, H>::ietf(), &keys);
let sig = sign(&mut *rng, IetfSchnorr::<C, H>::ietf(), keys.clone(), machines, MSG);
let group_key = keys[&Participant::new(1).unwrap()].group_key();
assert!(sig.verify(group_key, H::hram(&sig.R, &group_key, MSG)));
}
@@ -217,8 +217,8 @@ pub fn test_offset_schnorr<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &m
assert_eq!(keys.group_key(), offset_key);
}
let machines = algorithm_machines(&mut *rng, Schnorr::<C, H>::new(), &keys);
let sig = sign(&mut *rng, Schnorr::<C, H>::new(), keys.clone(), machines, MSG);
let machines = algorithm_machines(&mut *rng, IetfSchnorr::<C, H>::ietf(), &keys);
let sig = sign(&mut *rng, IetfSchnorr::<C, H>::ietf(), keys.clone(), machines, MSG);
let group_key = keys[&Participant::new(1).unwrap()].group_key();
assert!(sig.verify(offset_key, H::hram(&sig.R, &group_key, MSG)));
}
@@ -228,7 +228,7 @@ pub fn test_schnorr_blame<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mu
const MSG: &[u8] = b"Hello, World!";
let keys = key_gen(&mut *rng);
let machines = algorithm_machines(&mut *rng, Schnorr::<C, H>::new(), &keys);
let machines = algorithm_machines(&mut *rng, IetfSchnorr::<C, H>::ietf(), &keys);
let (mut machines, shares) = preprocess_and_shares(&mut *rng, machines, |_, _| {}, MSG);

View File

@@ -14,7 +14,7 @@ use ciphersuite::group::{ff::PrimeField, GroupEncoding};
use crate::{
curve::Curve,
Participant, ThresholdCore, ThresholdKeys,
algorithm::{IetfTranscript, Hram, Schnorr},
algorithm::{IetfTranscript, Hram, IetfSchnorr},
sign::{
Writable, Nonce, GeneratorCommitments, NonceCommitments, Commitments, Preprocess,
PreprocessMachine, SignMachine, SignatureMachine, AlgorithmMachine,
@@ -160,7 +160,8 @@ pub fn test_with_vectors<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(
let mut machines = vec![];
for i in &vectors.included {
machines.push((i, AlgorithmMachine::new(Schnorr::<C, H>::new(), keys[i].clone()).unwrap()));
machines
.push((i, AlgorithmMachine::new(IetfSchnorr::<C, H>::ietf(), keys[i].clone()).unwrap()));
}
let mut commitments = HashMap::new();
@@ -342,7 +343,8 @@ pub fn test_with_vectors<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(
// Create the machines
let mut machines = vec![];
for i in &vectors.included {
machines.push((i, AlgorithmMachine::new(Schnorr::<C, H>::new(), keys[i].clone()).unwrap()));
machines
.push((i, AlgorithmMachine::new(IetfSchnorr::<C, H>::ietf(), keys[i].clone()).unwrap()));
}
for (i, machine) in machines.drain(..) {