Crates.io | elastic-elgamal |
lib.rs | elastic-elgamal |
version | 0.3.1 |
source | src |
created_at | 2021-06-28 20:17:42.777082 |
updated_at | 2024-11-10 15:29:05.155905 |
description | Implementation of ElGamal encryption and related zero-knowledge proofs with pluggable crypto backend |
homepage | |
repository | https://github.com/slowli/elastic-elgamal |
max_upload_size | |
id | 415865 |
size | 454,705 |
Implementation of ElGamal encryption and related zero-knowledge proofs with pluggable crypto backend.
The following protocols and high-level applications are included:
While the logic in this crate relies on standard cryptographic assumptions (complexity of decisional Diffie–Hellman, computational Diffie–Hellman and discrete log problems in certain groups), it has not been independently verified for correctness or absence of side-channel attack vectors. Use at your own risk.
ElGamal encryption is not a good choice for general-purpose public-key encryption since it is vulnerable to chosen-ciphertext attacks. For security, decryption operations should be limited on the application level.
Add this to your Crate.toml
:
[dependencies]
elastic-elgamal = "0.3.1"
use elastic_elgamal::app::{ChoiceParams, EncryptedChoice};
use elastic_elgamal::{group::Ristretto, DiscreteLogTable, Keypair};
use rand::thread_rng;
let mut rng = thread_rng();
// Generate a keypair for encrypting ballots. In more realistic setup,
// this keypair would be distributed among multiple talliers.
let (pk, sk) = Keypair::<Ristretto>::generate(&mut rng).into_tuple();
let choice_params = ChoiceParams::single(pk, 5);
// ^ single-choice polling with 5 options encrypted for `pk`
let choice = 2; // voter's choice
let enc = EncryptedChoice::single(&choice_params, choice, &mut rng);
let choices = enc.verify(&choice_params).unwrap();
// ^ 5 Boolean value ciphertexts that can be homomorphically added
// across ballots
// Decrypt a separate ballot for demo purposes.
let lookup_table = DiscreteLogTable::new(0..=1);
for (idx, &v) in choices.iter().enumerate() {
assert_eq!(
sk.decrypt(v, &lookup_table),
Some((idx == choice) as u64)
);
}
use elastic_elgamal::app::{QuadraticVotingParams, QuadraticVotingBallot};
use elastic_elgamal::{group::Ristretto, Keypair, DiscreteLogTable};
use rand::thread_rng;
let mut rng = thread_rng();
let (pk, sk) = Keypair::<Ristretto>::generate(&mut rng).into_tuple();
let params = QuadraticVotingParams::new(pk, 5, 20);
// ^ 5 options, 20 credits (= 4 max votes per option)
assert_eq!(params.max_votes(), 4);
let votes = [4, 0, 0, 1, 1]; // voter's votes
let ballot = QuadraticVotingBallot::new(¶ms, &votes, &mut rng);
let encrypted = ballot.verify(¶ms).unwrap();
// ^ 5 vote ciphertexts that can be homomorphically added across ballots
// Decrypt a separate ballot for demo purposes.
let lookup = DiscreteLogTable::new(0..=params.max_votes());
let decrypted: Vec<_> = encrypted
.map(|vote| sk.decrypt(vote, &lookup).unwrap())
.collect();
assert_eq!(decrypted, votes);
See the crate docs for more examples of usage.
"Elastic" refers to pluggable backends, encryption with a key shared
among a variable number of participants, and the construction of zero-knowledge ring proofs
(a proof consists of a variable number of rings, each of which consists of a variable number
of admissible values).
elastic_elgamal
is also one of autogenerated Docker container names.
There are several Rust crates implementing ElGamal encryption
on elliptic curves, such as elgamal_ristretto
(this one features zero-knowledge proofs
of correct decryption and knowledge of the secret key).
As mentioned in the Warnings section, ElGamal is not a good choice for general-purpose
public-key encryption. RSA or ECIES schemes (such as the box
primitive from NaCl / libsodium)
can be used instead.
All contributions are welcome! See the contributing guide to help you get involved.
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in elastic-elgamal
by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.