Skip to content

Commit

Permalink
chore: further examples
Browse files Browse the repository at this point in the history
  • Loading branch information
0xAlcibiades committed Sep 1, 2024
1 parent afa3bd5 commit dd5cf0b
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 94 deletions.
16 changes: 12 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,20 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[[example]]
name = "dkg"
path = "examples/dkg.rs"
name = "DKG"
path = "examples/DKG.rs"

[[example]]
name = "fields"
path = "examples/fields.rs"
name = "ECDH"
path = "examples/ECDH.rs"

[[example]]
name = "threshold_signing"
path = "examples/threshold_signing.rs"

[[example]]
name = "sign_and_verify_multiple_messages"
path = "examples/verify_multiple_messages_same_signer.rs"

[dependencies]
crypto-bigint = "0.6.0-rc.2"
Expand Down
File renamed without changes.
46 changes: 46 additions & 0 deletions examples/ECDH.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use rand::thread_rng;
use sylow::{FieldExtensionTrait, Fp, Fr, G1Projective, GroupTrait};

struct ECDHParty {
private_key: Fr,
public_key: G1Projective,
}

impl ECDHParty {
fn new() -> Self {
let mut rng = thread_rng();
let private_key = Fr::rand(&mut rng);
let public_key = G1Projective::generator() * Fp::from(private_key);

ECDHParty {
private_key,
public_key,
}
}

fn compute_shared_secret(&self, other_public_key: &G1Projective) -> G1Projective {
*other_public_key * Fp::from(self.private_key)
}
}

fn main() {
// Alice generates her key pair
let alice = ECDHParty::new();
println!("Alice's public key: {:?}", alice.public_key);

// Bob generates his key pair
let bob = ECDHParty::new();
println!("Bob's public key: {:?}", bob.public_key);

// Alice computes the shared secret
let alice_shared_secret = alice.compute_shared_secret(&bob.public_key);
println!("Alice's computed shared secret: {:?}", alice_shared_secret);

// Bob computes the shared secret
let bob_shared_secret = bob.compute_shared_secret(&alice.public_key);
println!("Bob's computed shared secret: {:?}", bob_shared_secret);

// Verify that both parties computed the same shared secret
assert_eq!(alice_shared_secret, bob_shared_secret);
println!("ECDH key exchange successful!");
}
75 changes: 0 additions & 75 deletions examples/fields.rs

This file was deleted.

76 changes: 61 additions & 15 deletions examples/verify_multiple_messages_same_signer.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,74 @@
//! This example shows how to leverage the batch computation of the Miller loops, or otherwise
//! reuse the same G2 element in the pairing in repeated verifications.
//! This example demonstrates how to efficiently verify multiple signatures using batch verification
//! and precomputed Miller loop coefficients in Sylow, along with the benefits.

// TODO(This RNG still leaks through the abstraction of crypto_bigint)
use crypto_bigint::rand_core::OsRng;
use subtle::ConstantTimeEq;
use sylow::{
pairing, FieldExtensionTrait, Fp, Fr, G1Affine, G1Projective, G2Projective, GroupTrait,
glued_miller_loop, pairing, FieldExtensionTrait, Fp, Fr, G1Affine, G1Projective, G2Affine,
G2Projective, GroupTrait, Gt,
};
use tracing::info;

fn main() {
// First, let's generate a shared secret ...
tracing_subscriber::fmt().init();
// Generate a private key
let private_key = Fp::new(Fr::rand(&mut OsRng).value());
// ... and a public key from it, at which we evaluate the coefficients of the Miller loops
let pubkey = (G2Projective::generator() * private_key).precompute();
// Now, imagine we have 10 signatures we wish to verify.
let hashed_msgs: Vec<G1Affine> = (0..10).map(|_| G1Affine::rand(&mut OsRng)).collect();

let signatures: Vec<G1Projective> = hashed_msgs
// Compute the corresponding public key
let public_key = G2Projective::generator() * private_key;

// Precompute the public key for efficient pairing
let precomputed_pubkey = G2Affine::from(public_key).precompute();

// Number of messages to sign and verify
const NUM_MESSAGES: usize = 10;

// Generate random messages (in a real scenario, these would be actual messages to sign)
let messages: Vec<G1Affine> = (0..NUM_MESSAGES)
.map(|_| G1Affine::rand(&mut OsRng))
.collect();

// Sign all messages
let signatures: Vec<G1Projective> = messages
.iter()
.map(|x| G1Projective::from(x) * private_key)
.map(|msg| G1Projective::from(msg) * private_key)
.collect();
// We can evaluate each of them individually using the precomputed coefficients ...
for (sig, msg) in signatures.iter().zip(hashed_msgs.iter()) {

info!("Starting batch verification");

// Prepare points for batch verification
let mut g1_points = Vec::with_capacity(NUM_MESSAGES * 2);
let mut g2_points = Vec::with_capacity(NUM_MESSAGES * 2);

for (sig, msg) in signatures.iter().zip(messages.iter()) {
g1_points.push(G1Affine::from(*sig));
g1_points.push(-G1Affine::from(*msg));
g2_points.push(G2Affine::from(G2Projective::generator()));
g2_points.push(G2Affine::from(public_key));
}

// Precompute G2 points for efficient pairing
let g2_precomp: Vec<_> = g2_points.iter().map(|p| p.precompute()).collect();

// Perform batch verification
let miller_result = glued_miller_loop(&g2_precomp, &g1_points);
let batch_result = miller_result.final_exponentiation();

// Check if all signatures are valid
assert_eq!(batch_result, Gt::identity(), "Batch verification failed");
info!("Batch verification successful: All signatures are valid!");

info!("Starting individual verification");

// For comparison, verify each signature individually
for (sig, msg) in signatures.iter().zip(messages.iter()) {
let lhs = pairing(sig, &G2Projective::generator());
let rhs = pubkey.miller_loop(msg).final_exponentiation();
assert!(bool::from(lhs.ct_eq(&rhs)));
let rhs = precomputed_pubkey.miller_loop(msg).final_exponentiation();
assert!(
bool::from(lhs.ct_eq(&rhs)),
"Individual verification failed"
);
}
println!("All signatures are valid!");
info!("Individual verification successful: All signatures are valid!");
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ const DST: &[u8; 30] = b"WARLOCK-CHAOS-V01-CS01-SHA-256";
/// Security parameter in bits
const SECURITY_BITS: u64 = 128;

// TODO(Secret values should perhaps use the secrets crate so they are in protected memory and don’t leak to logs)
/// Represents a pair of secret and public keys for BLS signatures
///
/// This struct contains both the secret key (a scalar in the 𝔽ₚ base field)
Expand Down

0 comments on commit dd5cf0b

Please sign in to comment.