Giter Site home page Giter Site logo

elastic-elgamal's Introduction

ElGamal Encryption and Related Zero-Knowledge Proofs

Build Status License: MIT OR Apache-2.0 rust 1.65+ required no_std supported

Documentation: Docs.rs crate docs (main)

Implementation of ElGamal encryption and related zero-knowledge proofs with pluggable crypto backend.

The following protocols and high-level applications are included:

  • Additively homomorphic ElGamal encryption
  • Zero-knowledge proofs of zero encryption and Boolean value encryption
  • Zero-knowledge range proofs for ElGamal ciphertexts
  • Zero-knowledge proof of equivalence between an ElGamal ciphertext and a Pedersen commitment in the same group
  • Additively homomorphic m-of-n choice encryption with a zero-knowledge proof of correctness
  • Additively homomorphic quadratic voting with a zero-knowledge proof of correctness
  • Threshold ElGamal encryption via Feldman's verifiable secret sharing, including verifiable distributed decryption.
  • As an alternative method to generate a shared key for threshold encryption, there is Pedersen's distributed key generation with prior key commitments by participants. (Beware that this method can theoretically lead to skewed public key distribution as shown by Gennaro et al.)

⚠ Warnings

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.

Usage

Add this to your Crate.toml:

[dependencies]
elastic-elgamal = "0.3.0"

Single-choice polling

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)
    );
}

Quadratic voting

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(&params, &votes, &mut rng);
let encrypted = ballot.verify(&params).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.

Naming

"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.

Alternatives and similar tools

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.

See also

  • elasticpoll.app – an open-source web app that uses this library to implement universally verifiable voting. (Like this library, the website is not audited and should not be used for serious votes.)

Contributing

All contributions are welcome! See the contributing guide to help you get involved.

License

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.

elastic-elgamal's People

Contributors

dependabot[bot] avatar dufkan avatar jirigav avatar slowli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

elastic-elgamal's Issues

`PublicInfo<'_, Ristretto>` doesn't serialize easily

Feature request

I am trying to serialize the polynomials generated by participant.public_info().into_owned() to send them to different peers on a network.

error[E0277]: the trait bound `PublicInfo<'_, Ristretto>: Serialize` is not satisfied
   --> src/lib.rs:21:10
    |
21  | #[derive(Serialize, Deserialize, Debug)]
    |          ^^^^^^^^^ the trait `Serialize` is not implemented for `PublicInfo<'_, Ristretto>`
...
24  |     RequestPoly(PublicInfo<'a, Ristretto>),
    |                 ---------- required by a bound introduced by this call
    |
    = help: the following other types implement trait `Serialize`:
              &'a T
              &'a mut T
              ()
              (T0, T1)
              (T0, T1, T2)
              (T0, T1, T2, T3)
              (T0, T1, T2, T3, T4)
              (T0, T1, T2, T3, T4, T5)
            and 133 others
note: required by a bound in `serialize_newtype_variant`
   --> /Users/tadad/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.188/src/ser/mod.rs:936:12
    |
936 |         T: Serialize;
    |            ^^^^^^^^^ required by this bound in `Serializer::serialize_newtype_variant`

error[E0277]: the trait bound `PublicInfo<'a, Ristretto>: Deserialize<'_>` is not satisfied
    --> src/lib.rs:24:17
     |
24   |     RequestPoly(PublicInfo<'a, Ristretto>),
     |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Deserialize<'_>` is not implemented for `PublicInfo<'a, Ristretto>`
     |
     = help: the following other types implement trait `Deserialize<'de>`:
               &'a Path
               &'a [u8]
               &'a str
               ()
               (T0, T1)
               (T0, T1, T2)
               (T0, T1, T2, T3)
               (T0, T1, T2, T3, T4)
             and 136 others
note: required by a bound in `newtype_variant`
    --> /Users/tadad/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.188/src/de/mod.rs:2117:12
     |
2117 |         T: Deserialize<'de>,
     |            ^^^^^^^^^^^^^^^^ required by this bound in `VariantAccess::newtype_variant`

I believe this might have something to do with Ristretto not implementing Serialize/Deserialize because PublicInfo does. You can serialize Ristretto elements with myElement.serialize_element() but that doesn't let you easily serialize a PublicInfo - maybe not at all, I'm still trying to get it to work. Also possible I'm just doing something wrong...let me know, thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.