mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-10 05:09:22 +00:00
Remove DLEq proofs from CLSAG multisig
1) Removes the key image DLEq on the Monero side of things, as the produced signature share serves as a DLEq for it. 2) Removes the nonce DLEqs from modular-frost as they're unnecessary for monero-serai. Updates documentation accordingly. Without the proof the nonces are internally consistent, the produced signatures from modular-frost can be argued as a batch-verifiable CP93 DLEq (R0, R1, s), or as a GSP for the CP93 DLEq statement (which naturally produces (R0, R1, s)). The lack of proving the nonces consistent does make the process weaker, yet it's also unnecessary for the class of protocols this is intended to service. To provide DLEqs for the nonces would be to provide PoKs for the nonce commitments (in the traditional Schnorr case).
This commit is contained in:
@@ -12,7 +12,7 @@ use crate::{
|
||||
|
||||
/// Tests for the nonce handling code.
|
||||
pub mod nonces;
|
||||
use nonces::{test_multi_nonce, test_invalid_commitment, test_invalid_dleq_proof};
|
||||
use nonces::test_multi_nonce;
|
||||
|
||||
/// Vectorized test suite to ensure consistency.
|
||||
pub mod vectors;
|
||||
@@ -267,6 +267,4 @@ pub fn test_ciphersuite<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mut
|
||||
test_schnorr_blame::<R, C, H>(rng);
|
||||
|
||||
test_multi_nonce::<R, C>(rng);
|
||||
test_invalid_commitment::<R, C>(rng);
|
||||
test_invalid_dleq_proof::<R, C>(rng);
|
||||
}
|
||||
|
||||
@@ -9,14 +9,12 @@ use transcript::{Transcript, RecommendedTranscript};
|
||||
|
||||
use ciphersuite::group::{ff::Field, Group, GroupEncoding};
|
||||
|
||||
use dleq::MultiDLEqProof;
|
||||
pub use dkg::tests::{key_gen, recover_key};
|
||||
|
||||
use crate::{
|
||||
Curve, Participant, ThresholdView, ThresholdKeys, FrostError,
|
||||
algorithm::Algorithm,
|
||||
sign::{Writable, SignMachine},
|
||||
tests::{algorithm_machines, preprocess, sign},
|
||||
tests::{algorithm_machines, sign},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -157,75 +155,3 @@ pub fn test_multi_nonce<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
||||
let machines = algorithm_machines(&mut *rng, &MultiNonce::<C>::new(), &keys);
|
||||
sign(&mut *rng, &MultiNonce::<C>::new(), keys.clone(), machines, &[]);
|
||||
}
|
||||
|
||||
/// Test malleating a commitment for a nonce across generators causes the preprocess to error.
|
||||
pub fn test_invalid_commitment<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
||||
let keys = key_gen::<R, C>(&mut *rng);
|
||||
let machines = algorithm_machines(&mut *rng, &MultiNonce::<C>::new(), &keys);
|
||||
let (machines, mut preprocesses) = preprocess(&mut *rng, machines, |_, _| {});
|
||||
|
||||
// Select a random participant to give an invalid commitment
|
||||
let participants = preprocesses.keys().collect::<Vec<_>>();
|
||||
let faulty = *participants
|
||||
[usize::try_from(rng.next_u64() % u64::try_from(participants.len()).unwrap()).unwrap()];
|
||||
|
||||
// Grab their preprocess
|
||||
let mut preprocess = preprocesses.remove(&faulty).unwrap();
|
||||
|
||||
// Mutate one of the commitments
|
||||
let nonce =
|
||||
preprocess.commitments.nonces.get_mut(usize::try_from(rng.next_u64()).unwrap() % 2).unwrap();
|
||||
let generators_len = nonce.generators.len();
|
||||
nonce.generators[usize::try_from(rng.next_u64()).unwrap() % generators_len].0
|
||||
[usize::try_from(rng.next_u64()).unwrap() % 2] = C::G::random(&mut *rng);
|
||||
|
||||
// The commitments are validated at time of deserialization (read_preprocess)
|
||||
// Accordingly, serialize it and read it again to make sure that errors
|
||||
assert!(machines
|
||||
.iter()
|
||||
.next()
|
||||
.unwrap()
|
||||
.1
|
||||
.read_preprocess::<&[u8]>(&mut preprocess.serialize().as_ref())
|
||||
.is_err());
|
||||
}
|
||||
|
||||
/// Test malleating the DLEq proof for a preprocess causes it to error.
|
||||
pub fn test_invalid_dleq_proof<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
||||
let keys = key_gen::<R, C>(&mut *rng);
|
||||
let machines = algorithm_machines(&mut *rng, &MultiNonce::<C>::new(), &keys);
|
||||
let (machines, mut preprocesses) = preprocess(&mut *rng, machines, |_, _| {});
|
||||
|
||||
// Select a random participant to give an invalid DLEq proof
|
||||
let participants = preprocesses.keys().collect::<Vec<_>>();
|
||||
let faulty = *participants
|
||||
[usize::try_from(rng.next_u64() % u64::try_from(participants.len()).unwrap()).unwrap()];
|
||||
|
||||
// Invalidate it by replacing it with a completely different proof
|
||||
let dlogs = [Zeroizing::new(C::F::random(&mut *rng)), Zeroizing::new(C::F::random(&mut *rng))];
|
||||
let mut preprocess = preprocesses.remove(&faulty).unwrap();
|
||||
preprocess.commitments.dleq = Some(MultiDLEqProof::prove(
|
||||
&mut *rng,
|
||||
&mut RecommendedTranscript::new(b"Invalid DLEq Proof"),
|
||||
&nonces::<C>(),
|
||||
&dlogs,
|
||||
));
|
||||
|
||||
assert!(machines
|
||||
.iter()
|
||||
.next()
|
||||
.unwrap()
|
||||
.1
|
||||
.read_preprocess::<&[u8]>(&mut preprocess.serialize().as_ref())
|
||||
.is_err());
|
||||
|
||||
// Also test None for a proof will cause an error
|
||||
preprocess.commitments.dleq = None;
|
||||
assert!(machines
|
||||
.iter()
|
||||
.next()
|
||||
.unwrap()
|
||||
.1
|
||||
.read_preprocess::<&[u8]>(&mut preprocess.serialize().as_ref())
|
||||
.is_err());
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ use ciphersuite::group::{ff::PrimeField, GroupEncoding};
|
||||
use crate::{
|
||||
curve::Curve,
|
||||
Participant, ThresholdCore, ThresholdKeys,
|
||||
algorithm::{IetfTranscript, Hram, IetfSchnorr},
|
||||
algorithm::{Hram, IetfSchnorr},
|
||||
sign::{
|
||||
Writable, Nonce, GeneratorCommitments, NonceCommitments, Commitments, Preprocess,
|
||||
PreprocessMachine, SignMachine, SignatureMachine, AlgorithmMachine,
|
||||
@@ -191,7 +191,6 @@ pub fn test_with_vectors<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(
|
||||
nonces: vec![NonceCommitments {
|
||||
generators: vec![GeneratorCommitments(these_commitments)],
|
||||
}],
|
||||
dleq: None,
|
||||
},
|
||||
addendum: (),
|
||||
};
|
||||
@@ -301,12 +300,8 @@ pub fn test_with_vectors<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(
|
||||
}
|
||||
|
||||
// Also test it at the Commitments level
|
||||
let (generated_nonces, commitments) = Commitments::<C>::new::<_, IetfTranscript>(
|
||||
&mut TransparentRng(randomness),
|
||||
&share,
|
||||
&[vec![C::generator()]],
|
||||
&[],
|
||||
);
|
||||
let (generated_nonces, commitments) =
|
||||
Commitments::<C>::new::<_>(&mut TransparentRng(randomness), &share, &[vec![C::generator()]]);
|
||||
|
||||
assert_eq!(generated_nonces.len(), 1);
|
||||
assert_eq!(generated_nonces[0].0, [nonces[0].clone(), nonces[1].clone()]);
|
||||
|
||||
Reference in New Issue
Block a user