Rust implementation of silent threshold encryption from ePrint:2024/263.
- Silent Threshold Encryption: Encrypt to n parties, decrypt with t+1 collaborators
- TLS 1.3 Protection: Secure network communication for distributed protocol
- Memory Safety: Automatic zeroization of cryptographic secrets
- Constant-Time Operations: Timing attack resistance for sensitive operations
- Enhanced Error Handling: Comprehensive error types with
thiserror
./test_distributed_simple.shBuild:
cargo build --bin distributed_protocol --features distributed --releaseStart Coordinator:
./target/release/distributed_protocol coordinator \
--port 8080 \
--parties 4 \
--threshold 2 \
--cert ./coordinator_cert.pem \
--key ./coordinator_key.pemStart Parties (4 terminals):
./target/release/distributed_protocol party --id 0 --coordinator localhost:8080 --server-cert ./coordinator_cert.pem
./target/release/distributed_protocol party --id 1 --coordinator localhost:8080 --server-cert ./coordinator_cert.pem
./target/release/distributed_protocol party --id 2 --coordinator localhost:8080 --server-cert ./coordinator_cert.pem
./target/release/distributed_protocol party --id 3 --coordinator localhost:8080 --server-cert ./coordinator_cert.pemuse silent_threshold_encryption::*;
use ark_bls12_381::Bls12_381 as E;
use ark_std::rand::rngs::OsRng;
let mut rng = OsRng;
let n = 4; // Total parties
let t = 2; // Threshold (need t+1 to decrypt)
// Setup
let tau = Fr::rand(&mut rng);
let params = KZG10::setup(n, &tau)?;
let lagrange_params = LagrangePowers::new(tau, n)?;
// Generate keys
let sk: Vec<SecretKey<E>> = (0..n).map(|_| SecretKey::new(&mut rng)).collect();
let pk: Vec<PublicKey<E>> = sk.iter()
.enumerate()
.map(|(i, sk)| sk.get_pk(&lagrange_params, i, n))
.collect::<Result<Vec<_>, _>>()?;
let agg_key = AggregateKey::new(pk, &lagrange_params, n)?;
// Encrypt
let message = Fr::rand(&mut rng);
let ct = encrypt(&message, &agg_key, ¶ms, &mut rng)?;
// Decrypt (with t+1 parties)
let mut partial_decs = vec![G2::zero(); n];
let mut selector = vec![false; n];
for i in 0..=t {
selector[i] = true;
partial_decs[i] = sk[i].partial_decryption(&ct);
}
let recovered = agg_dec(&partial_decs, &ct, &selector, &agg_key, ¶ms)?;
assert_eq!(message, recovered);SensitiveScalar<F>: Auto-zeroizing wrapper for secretsSecretKeyZeroization: Volatile writes prevent compiler optimization- Debug Redaction: Sensitive types hide values in debug output
use silent_threshold_encryption::security::SensitiveScalar;
let tau = SensitiveScalar::new(Fr::rand(&mut rng));
// Automatically zeroized when droppeduse silent_threshold_encryption::security::*;
// Constant-time comparisons
constant_time_eq(&a, &b); // Field elements
constant_time_eq_g1::<E>(&p1, &p2); // G1 elements
constant_time_eq_g2::<E>(&q1, &q2); // G2 elements
// Constant-time BLS signature verification
verify_bls_signature_ct::<E>(&sig, &pk, &msg);use silent_threshold_encryption::SteError;
match operation() {
Err(SteError::InvalidThreshold(msg)) => // Handle threshold error
Err(SteError::DecryptionFailure(msg)) => // Handle decryption error
Err(SteError::NetworkError(msg)) => // Handle network error
Ok(result) => // Success
}# Run tests
cargo test
# Run benchmarks
cargo bench
# Build library
cargo build --release
# Build distributed protocol
cargo build --features distributed --releaseThe distributed protocol uses TLS 1.3 for encrypted communication:
- Certificate pinning: Parties can (and by default must) trust a specific coordinator certificate via
--server-cert - Auto-generated certificates remain available for local experiments (combine with
--allow-insecureon parties) - Forward secrecy with X25519/P-256
- Modern ciphers: AES-GCM, ChaCha20-Poly1305
- Production-ready certificate loading
All cryptographic material (keys, ciphertexts, partial decryptions) is encrypted in transit. For development-only scenarios you can bypass verification with --allow-insecure, but this is not recommended.
src/
├── setup.rs # Key generation & aggregation
├── encryption.rs # Silent threshold encryption
├── decryption.rs # Partial decryption aggregation
├── security.rs # Memory protection & constant-time ops
├── error.rs # Error types with thiserror
├── kzg.rs # KZG commitments
├── trusted_setup.rs # Multi-party ceremony
└── bin/
└── distributed_protocol.rs # TLS-enabled distributed protocol
Before production use:
- Security audit required - Not formally audited
- Trusted setup - Use multi-party ceremony (see
trusted_setupmodule) - TLS certificates - Use CA-signed certificates for production
- RNG: Always use
OsRng, nevertest_rng()
use silent_threshold_encryption::trusted_setup::Ceremony;
// Initialize ceremony
let mut ceremony = Ceremony::<E>::new(max_degree, &mut rng)?;
// Each participant contributes
ceremony.contribute(&mut participant_rng)?;
// Verify contributions
for i in 1..ceremony.num_participants() {
assert!(ceremony.verify_contribution(i));
}
// Finalize
let params = ceremony.finalize()?;Browser-based party implementation available in wasm-client/:
cd wasm-client
wasm-pack build --target web --release
# Open distributed_party.html in browserSmall committee (4 parties, need 3):
./target/release/distributed_protocol coordinator --parties 4 --threshold 2Board of directors (8 parties, need majority):
./target/release/distributed_protocol coordinator --parties 8 --threshold 4Large organization (16 parties, high threshold):
./target/release/distributed_protocol coordinator --parties 16 --threshold 10- Paper: ePrint:2024/263
- rustls: https://docs.rs/rustls/
- TLS 1.3: RFC 8446
MIT License