Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of SimplPedPoP #106

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b93d5ea
Implementation of SimplPedPoP
Fiono11 May 6, 2024
0229035
Improvements
Fiono11 May 6, 2024
059b601
Add tests
Fiono11 May 6, 2024
bbb6b74
Fix tests
Fiono11 May 6, 2024
2e557c9
Return keys from simplpedpop_recipient_all instead of points and scalars
Fiono11 May 6, 2024
5fc364a
Replace pub(crate) with pub(super)
Fiono11 May 6, 2024
1b387d2
Fix in ciphertexts loop
Fiono11 May 7, 2024
cf308ba
Add wrapper types
Fiono11 May 7, 2024
ff8d132
Implement SecretShare and EncryptedSecretShare types
Fiono11 May 8, 2024
2e9b153
Implement SecretPolynomial and PolynomialCommitment types
Fiono11 May 8, 2024
9420ff4
Restructuring of files
Fiono11 May 8, 2024
69473c4
Remove derive_key_from_scalar
Fiono11 May 8, 2024
51d16cd
Remove ephemeral key
Fiono11 May 8, 2024
0be043a
Add Identifier type
Fiono11 May 8, 2024
cc2fd93
Add identifiers to dkg_output
Fiono11 May 8, 2024
d7d061d
Remove proof of possession signature
Fiono11 May 8, 2024
9ed307f
Improvements
Fiono11 May 8, 2024
8b9726e
Fix deserialization of dkg output
Fiono11 May 8, 2024
3771fd5
Remove unwrap
Fiono11 May 9, 2024
04546ed
Improve errors
Fiono11 May 9, 2024
030ce7a
Add polynomial tests
Fiono11 May 9, 2024
443a40f
Reimplement ephemeral key and proof of possession
Fiono11 May 10, 2024
524b01e
Merge changes from final_frost branch to simplpedpop
Fiono11 May 17, 2024
1a9c024
Undo formatting
Fiono11 May 17, 2024
1402b1e
Implementation of SimplPedPoP
Fiono11 May 6, 2024
689bfed
Merge remote-tracking branch 'fiono/final_simplpedpop' into final_sim…
Fiono11 May 19, 2024
63cbcdf
Sign the whole message with the secret of the polynomial
Fiono11 May 18, 2024
35518c6
Fixes
Fiono11 May 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ curve25519-dalek = { version = "4.1.0", default-features = false, features = [
"zeroize",
"precomputed-tables",
"legacy_compatibility",
"rand_core",
] }
subtle = { version = "2.4.1", default-features = false }
merlin = { version = "3.0.0", default-features = false }
Expand All @@ -32,7 +33,10 @@ serde_bytes = { version = "0.11.5", default-features = false, optional = true }
cfg-if = { version = "1.0.0", optional = true }
sha2 = { version = "0.10.7", default-features = false }
failure = { version = "0.1.8", default-features = false, optional = true }
zeroize = { version = "1.6", default-features = false, features = ["zeroize_derive"] }
zeroize = { version = "1.6", default-features = false, features = [
"zeroize_derive",
] }
chacha20poly1305 = { version = "0.10.1", default-features = false }

[dev-dependencies]
rand = "0.8.5"
Expand All @@ -47,17 +51,38 @@ serde_json = "1.0.68"
name = "schnorr_benchmarks"
harness = false

[[bench]]
name = "olaf_benchmarks"
required-features = ["alloc", "aead"]
harness = false

[features]
default = ["std", "getrandom"]
preaudit_deprecated = []
nightly = []
alloc = ["curve25519-dalek/alloc", "rand_core/alloc", "getrandom_or_panic/alloc", "serde_bytes/alloc"]
std = ["alloc", "getrandom", "serde_bytes/std", "rand_core/std", "getrandom_or_panic/std"]
alloc = [
"curve25519-dalek/alloc",
"rand_core/alloc",
"getrandom_or_panic/alloc",
"serde_bytes/alloc",
]
std = [
"alloc",
"getrandom",
"serde_bytes/std",
"rand_core/std",
"getrandom_or_panic/std",
"chacha20poly1305/std",
]
asm = ["sha2/asm"]
serde = ["serde_crate", "serde_bytes", "cfg-if"]
# We cannot make getrandom a direct dependency because rand_core makes
# getrandom a feature name, which requires forwarding.
getrandom = ["rand_core/getrandom", "getrandom_or_panic/getrandom", "aead?/getrandom"]
getrandom = [
"rand_core/getrandom",
"getrandom_or_panic/getrandom",
"aead?/getrandom",
]
# We thus cannot forward the wasm-bindgen feature of getrandom,
# but our consumers could depend upon getrandom and activate its
# wasm-bindgen feature themselve, which works due to cargo features
Expand Down
53 changes: 53 additions & 0 deletions benches/olaf_benchmarks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use criterion::criterion_main;

mod olaf_benches {
use criterion::{criterion_group, BenchmarkId, Criterion};
use schnorrkel::keys::{PublicKey, Keypair};
use schnorrkel::olaf::simplpedpop::AllMessage;

fn benchmark_simplpedpop(c: &mut Criterion) {
let mut group = c.benchmark_group("SimplPedPoP");

for &n in [3, 10, 100, 1000].iter() {
let participants = n;
let threshold = (n * 2 + 2) / 3;

let keypairs: Vec<Keypair> = (0..participants).map(|_| Keypair::generate()).collect();
let public_keys: Vec<PublicKey> = keypairs.iter().map(|kp| kp.public).collect();

let mut all_messages: Vec<AllMessage> = Vec::new();

for i in 0..participants {
let message = keypairs[i]
.simplpedpop_contribute_all(threshold as u16, public_keys.clone())
.unwrap();
all_messages.push(message);
}

group.bench_function(BenchmarkId::new("round1", participants), |b| {
b.iter(|| {
keypairs[0]
.simplpedpop_contribute_all(threshold as u16, public_keys.clone())
.unwrap();
})
});

group.bench_function(BenchmarkId::new("round2", participants), |b| {
b.iter(|| {
keypairs[0].simplpedpop_recipient_all(&all_messages).unwrap();
})
});
}

group.finish();
}

criterion_group! {
name = olaf_benches;
config = Criterion::default();
targets =
benchmark_simplpedpop,
}
}

criterion_main!(olaf_benches::olaf_benches);
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,9 @@ pub mod derive;
pub mod cert;
pub mod errors;

#[cfg(all(feature = "alloc", feature = "aead"))]
pub mod olaf;

#[cfg(all(feature = "aead", feature = "getrandom"))]
pub mod aead;

Expand Down
73 changes: 73 additions & 0 deletions src/olaf/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//! Implementation of the Olaf protocol (<https://eprint.iacr.org/2023/899>), which is composed of the Distributed
//! Key Generation (DKG) protocol SimplPedPoP and the Threshold Signing protocol FROST.

/// Implementation of the SimplPedPoP protocol.
pub mod simplpedpop;

use curve25519_dalek::{constants::RISTRETTO_BASEPOINT_POINT, RistrettoPoint, Scalar};
use merlin::Transcript;
use zeroize::ZeroizeOnDrop;
use crate::{context::SigningTranscript, Keypair, PublicKey, SignatureError, KEYPAIR_LENGTH};

pub(super) const MINIMUM_THRESHOLD: u16 = 2;
pub(super) const GENERATOR: RistrettoPoint = RISTRETTO_BASEPOINT_POINT;
pub(super) const COMPRESSED_RISTRETTO_LENGTH: usize = 32;
pub(crate) const SCALAR_LENGTH: usize = 32;

/// The threshold public key generated in the SimplPedPoP protocol, used to validate the threshold signatures of the FROST protocol.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ThresholdPublicKey(pub(crate) PublicKey);

/// The verifying share of a participant generated in the SimplPedPoP protocol, used to verify its signatures shares in the FROST protocol.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct VerifyingShare(pub(crate) PublicKey);

/// The signing keypair of a participant generated in the SimplPedPoP protocol, used to produce its signatures shares in the FROST protocol.
#[derive(Clone, Debug, ZeroizeOnDrop)]
pub struct SigningKeypair(pub(crate) Keypair);

impl SigningKeypair {
/// Serializes `SigningKeypair` to bytes.
pub fn to_bytes(&self) -> [u8; KEYPAIR_LENGTH] {
self.0.to_bytes()
}

/// Deserializes a `SigningKeypair` from bytes.
pub fn from_bytes(bytes: &[u8]) -> Result<SigningKeypair, SignatureError> {
let keypair = Keypair::from_bytes(bytes)?;
Ok(SigningKeypair(keypair))
}
}

/// The identifier of a participant, which must be the same in the SimplPedPoP protocol and in the FROST protocol.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Identifier(pub(crate) Scalar);

impl Identifier {
pub(super) fn generate(recipients_hash: &[u8; 16], index: u16) -> Identifier {
let mut pos = Transcript::new(b"Identifier");
pos.append_message(b"RecipientsHash", recipients_hash);
pos.append_message(b"i", &index.to_le_bytes()[..]);

Identifier(pos.challenge_scalar(b"evaluation position"))
}
}

#[cfg(test)]
pub(crate) mod test_utils {
use rand::{thread_rng, Rng};
use crate::olaf::simplpedpop::Parameters;

const MAXIMUM_PARTICIPANTS: u16 = 10;
const MINIMUM_PARTICIPANTS: u16 = 2;

pub(crate) fn generate_parameters() -> Parameters {
use super::MINIMUM_THRESHOLD;

let mut rng = thread_rng();
let participants = rng.gen_range(MINIMUM_PARTICIPANTS..=MAXIMUM_PARTICIPANTS);
let threshold = rng.gen_range(MINIMUM_THRESHOLD..=participants);

Parameters { participants, threshold }
}
}
Loading