-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
afa3bd5
commit dd5cf0b
Showing
6 changed files
with
120 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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!"); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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!"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters