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

Simple Example - Centralized Telescope with BLS #120

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
175447e
a simple example for demo
curiecrypt Jan 10, 2025
907907c
clippy warnings
curiecrypt Jan 10, 2025
9247cea
revise
curiecrypt Jan 14, 2025
a1ade3d
clippy
curiecrypt Jan 14, 2025
de18f05
clippy error
curiecrypt Jan 14, 2025
bb4a648
clippy warning
curiecrypt Jan 14, 2025
bb96e53
fmt
curiecrypt Jan 14, 2025
c162f35
move blst to dev dependencies
curiecrypt Jan 15, 2025
1ff40a7
simplify aggregation
curiecrypt Jan 15, 2025
1915514
cargo fmt
curiecrypt Jan 15, 2025
20cedea
moving structs to separate files
curiecrypt Jan 16, 2025
acb5159
removing generics
curiecrypt Jan 16, 2025
8775e19
signatures verified individually
curiecrypt Jan 16, 2025
5e6b257
signature struct, no hashmap to collect signatures
curiecrypt Jan 16, 2025
e35ed4c
remove compy paste left over
curiecrypt Jan 16, 2025
f170607
remove key_list from ThresholdSignature
curiecrypt Jan 16, 2025
63503c7
some improvements
curiecrypt Jan 16, 2025
b36c5ba
change params for main function
curiecrypt Jan 16, 2025
744eca9
Merge branch 'main' into curiecrypt/simple-example
curiecrypt Jan 21, 2025
0c8b17a
Merge branch 'curiecrypt/simple-example' of https://github.com/cardan…
curiecrypt Jan 21, 2025
f6e84f2
new structure adjustments
curiecrypt Jan 21, 2025
c95f1fe
revision
curiecrypt Jan 21, 2025
08811a6
Merge branch 'main' into curiecrypt/simple-example
curiecrypt Jan 21, 2025
1f604d3
Update examples/simple_threshold_signature/threshold_signature.rs
curiecrypt Jan 22, 2025
b7f71f9
sent all public keys to verification
curiecrypt Jan 22, 2025
cb2bd3d
more comments on functions
curiecrypt Jan 22, 2025
d21df97
nbelements signers
curiecrypt Jan 22, 2025
3547e01
Merge branch 'main' into curiecrypt/simple-example
curiecrypt Jan 23, 2025
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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ blake2 = "0.10.6"
rand_core = "0.6.4"
rand_chacha = "0.3.1"
test-case = "3.3.1"
blst = "0.3.13"

[lints.rust]
missing-copy-implementations = "warn"
Expand Down
68 changes: 68 additions & 0 deletions examples/simple_example.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//! Centralized Telescope example with BLS signatures

mod simple_threshold_signature;

use crate::simple_threshold_signature::signature::Signature;
use crate::simple_threshold_signature::signer::Signer;
use crate::simple_threshold_signature::threshold_signature::ThresholdSignature;
use alba::centralized_telescope::Telescope;
use blst::min_sig::PublicKey;
use rand_chacha::ChaCha20Rng;
use rand_core::{RngCore, SeedableRng};

const DATA_LENGTH: usize = 48;
type Element = [u8; DATA_LENGTH];

fn main() {
curiecrypt marked this conversation as resolved.
Show resolved Hide resolved
let mut rng = ChaCha20Rng::from_seed(Default::default());
let mut msg = [0u8; 16];
rng.fill_bytes(&mut msg);

println!("\n-------------- ALBA with Multi-Signature ---------------");
println!("--------------------------------------------------------");

// Define telescope parameters
let nb_elements: u64 = 1_000;
let soundness_param = 128.0;
let completeness_param = 128.0;
let set_size = nb_elements.saturating_mul(80).div_ceil(100);
let lower_bound = nb_elements.saturating_mul(20).div_ceil(100);

println!(" - Soundness parameter: {soundness_param}");
println!(" - Completeness parameter: {completeness_param}");
println!(" - Prover set size: {set_size}");
println!(" - Lower bound: {lower_bound}");

// Create the telescope structure
let alba = Telescope::create(soundness_param, completeness_param, set_size, lower_bound);

let mut public_key_list: Vec<(usize, PublicKey)> = Vec::with_capacity(nb_elements as usize);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The usize variable always contains its own index, so it is redundant and can be removed.

let mut signature_list: Vec<Signature> = Vec::with_capacity(set_size as usize);

// Generate `nb_elements` signers and `set_size` signatures
for i in 0..nb_elements as usize {
let signer = Signer::new(&mut rng);
public_key_list.push((i, signer.verification_key));
if i < set_size as usize {
signature_list.push(signer.sign(&msg, i));
}
}
println!("--------------------------------------------------------");
println!(" -- {nb_elements} (sk, pk) are generated.");
println!(" -- {set_size} signatures are generated.");

println!("--------------------------------------------------------");
println!("----------- Generating Alba multi-signature. -----------");
let (threshold_signature, indices) =
ThresholdSignature::aggregate(&signature_list, &alba, &public_key_list);
println!("-- Alba multi-signature is generated.");
println!("--------------------------------------------------------");
println!("----------- Verifying Alba multi-signature. ------------");

if threshold_signature.verify(&msg, &alba, &public_key_list, &indices) {
println!("-- Verification successful.");
} else {
println!("-- Verification failed.");
}
println!("--------------------------------------------------------");
}
3 changes: 3 additions & 0 deletions examples/simple_threshold_signature/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub(crate) mod signature;
pub(crate) mod signer;
pub(crate) mod threshold_signature;
10 changes: 10 additions & 0 deletions examples/simple_threshold_signature/signature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use blst::min_sig::Signature as BlsSignature;

/// Single signature
#[derive(Debug, Clone)]
pub(crate) struct Signature {
/// Signature of type bls signature
pub(crate) signature: BlsSignature,
/// Verification index of the signer
pub(crate) index: usize,
}
31 changes: 31 additions & 0 deletions examples/simple_threshold_signature/signer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::simple_threshold_signature::signature::Signature;
use blst::min_sig::{PublicKey, SecretKey};
use rand_core::{CryptoRng, RngCore};

pub(crate) struct Signer {
signing_key: SecretKey,
pub(crate) verification_key: PublicKey,
}

impl Signer {
/// Create a pair of bls signing key and verification key
pub(crate) fn new(rng: &mut (impl RngCore + CryptoRng)) -> Self {
let mut ikm = [0u8; 32];
rng.fill_bytes(&mut ikm);
let sk = SecretKey::key_gen(&ikm, &[])
.expect("Error occurs when the length of ikm < 32. This will not happen here.");
let pk: PublicKey = sk.sk_to_pk();
Self {
signing_key: sk,
verification_key: pk,
}
}

/// Sign given message. Return the signature and given signer index.
pub(crate) fn sign(&self, msg: &[u8], index: usize) -> Signature {
Signature {
signature: self.signing_key.sign(msg, &[], &[]),
index,
}
}
}
114 changes: 114 additions & 0 deletions examples/simple_threshold_signature/threshold_signature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use crate::simple_threshold_signature::signature::Signature;
use crate::Element;
use alba::centralized_telescope::proof::Proof;
use alba::centralized_telescope::Telescope;
use blst::min_sig::{PublicKey, Signature as BlsSignature};
use blst::BLST_ERROR;

pub(crate) struct ThresholdSignature {
proof: Proof,
}

impl ThresholdSignature {
// Create the Alba proof. Convert signatures to bytes and use them as the prover set. Create Alba proof with the
// prover set. Collect signatures by converting proof elements to bls signatures. Find each signature's index and
// collect them in a list. Return alba proof and the indices.
pub(crate) fn aggregate(
signatures: &[Signature],
alba: &Telescope,
public_key_list: &[(usize, PublicKey)],
) -> (Self, Vec<usize>) {
// Convert signatures to bytes and collect as the prover set.
let prover_set = signatures
.iter()
.map(|s| s.signature.to_bytes())
.collect::<Vec<Element>>();

println!("-- Creating alba proof. ");
// Create alba proof with the prover set
let proof = alba.prove(&prover_set).unwrap();
println!("-- Alba proof created: ");
println!(
" - Numbers of retries done to find the proof: {}",
proof.retry_counter
curiecrypt marked this conversation as resolved.
Show resolved Hide resolved
);
println!(
" - Index of the searched subtree to find the proof: {}",
proof.search_counter
);
println!(
" - Number of elements in the proof sequence: {}",
proof.element_sequence.len()
);

// Convert proof elements to signatures to obtain their indexes
let proof_signatures: Vec<BlsSignature> = proof
.element_sequence
.iter()
.filter_map(|element| BlsSignature::from_bytes(element).ok())
.collect();

// Collect the indices of the signatures that create alba proof.
let mut indices = Vec::with_capacity(proof_signatures.len());
for sig in &proof_signatures {
if let Some(signature_entry) = signatures.iter().find(|entry| entry.signature == *sig) {
if public_key_list
.iter()
.any(|entry| entry.0 == signature_entry.index)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this logic wouldn't work if you pass signatures to this function that are not index 0, 1, ..., n_p-1. That's why in my document Aggregate gets triples (i, s_i, w_i). In particular, the index i of the signature is included.

Also, public_key_list seems redundant in this function.

{
indices.push(signature_entry.index);
}
}
}
(Self { proof }, indices)
}

/// Validates individual signatures in the threshold signature
/// This function verifies each individual signature separately.
/// The verification could also be done by using aggregation from blst library as follows:
/// - Aggregate signatures with: `AggregateSignature::aggregate`,
/// - Aggregate public keys with: `AggregatePublicKey::aggregate`,
/// - Convert aggregate signature to a signature and aggregate public key to a public key
/// - Verify the signature with public key against given message.
fn validate_signatures(
&self,
msg: &[u8],
public_key_list: &[(usize, PublicKey)],
indices: &[usize],
) -> bool {
let mut signatures = Vec::with_capacity(self.proof.element_sequence.len());
// Get the bls signatures from byte representation
for sig_bytes in &self.proof.element_sequence {
let Ok(signature) = BlsSignature::from_bytes(sig_bytes.as_slice()) else {
return false;
};
signatures.push(signature);
}

// Find the public key from the public key lest for the corresponding index (and signature)
// Verify the signature with this public key against given message.
for (signature, &index) in signatures.iter().zip(indices.iter()) {
if let Some((_, public_key)) = public_key_list.iter().find(|(idx, _)| *idx == index) {
if signature.verify(false, msg, &[], &[], public_key, false)
!= BLST_ERROR::BLST_SUCCESS
{
return false;
}
} else {
return false;
}
}
true
}

/// Verify `ThresholdSignature` by validating the signatures included in alba proof and verifying the alba proof.
pub(crate) fn verify(
&self,
msg: &[u8],
alba: &Telescope,
public_key_list: &[(usize, PublicKey)],
indices: &[usize],
) -> bool {
self.validate_signatures(msg, public_key_list, indices) && alba.verify(&self.proof)
}
}
Loading