Skip to main content

Module paillier_encryption_in_range_with_el_gamal

Module paillier_encryption_in_range_with_el_gamal 

Source
Expand description

ZK-proof of paillier encryption in range with El-Gamal commitment. Called Пenc-elg or Renc-elg in the CGGMP24 paper.

§Description

Common (public) inputs: verifier’s Aux data, SecurityParams containing $\ell$ and $\varepsilon$, curve E, Paillier public key, a ciphertext, and elliptic points $A, B, X$.

Prover secret inputs: plaintext, nonce, scalars $a, b$, such that:

  • plaintext $\in \pm 2^\ell$
  • ciphertext == key.encrypt_with(plaintext, nonce)
  • $A = a \cdot G$
  • $B = b \cdot G$
  • $X = (a b + \text{plaintext}) \cdot G$

Proof guarantees that plaintext $\in \pm 2^{\ell + \varepsilon}$.

§Example

use paillier_zk::{paillier_encryption_in_range_with_el_gamal as p, IntegerExt};
use fast_paillier::backend::Integer;
use generic_ec::{Point, Scalar, curves::Secp256k1 as E};

let shared_state = "some shared state";

let mut rng = rand_core::OsRng;

// Both parties know predefined security parameters and verifier's aux data
let aux: p::Aux = pregenerated::verifier_aux();
let security = p::SecurityParams {
    l: 256,
    epsilon: 512,
};
// ...and someone's encryption key
let key: fast_paillier::EncryptionKey =
    pregenerated::someone_encryption_key();

// Prover knows its secret `pdata` and `a`
let a = Scalar::random(&mut rng);
let pdata = p::PrivateData {
    plaintext: &Integer::from_rng_half_pm(&mut rng, &(Integer::one() << security.l)),
    nonce: &Integer::sample_in_mult_group_of(&mut rng, key.n()),
    b: &Scalar::random(&mut rng),
};

// Both parties know the public data
let data = p::Data {
    key: &key,
    ciphertext: &key
        .encrypt_with(pdata.plaintext, pdata.nonce)
        .unwrap(),
    a: &(Point::generator() * a),
    b: &(Point::generator() * pdata.b),
    x: &(Point::generator() * (a * pdata.b + pdata.plaintext.to_scalar())),
};

// Prover computes a non-interactive proof:
let proof = p::non_interactive::prove::<E, sha2::Sha256>(
    &shared_state,
    &aux,
    data,
    pdata,
    &security,
    &mut rng,
)?;

// Prover sends this data to verifier
send(&data, &proof);

// Verifier receives the data and the proof and verifies it
let (data, proof) = recv();
p::non_interactive::verify::<E, sha2::Sha256>(
    &shared_state,
    &aux,
    data,
    &proof,
    &security,
);

If the verification succeeded, verifier can continue communication with prover

Modules§

interactive
The interactive version of the ZK proof. Should be completed in 3 rounds: prover commits to data, verifier responds with a random challenge, and prover gives proof with commitment and challenge.
non_interactive
The non-interactive version of proof. Completed in one round, for example see the documentation of parent module.

Structs§

Aux
Auxiliary data known to both prover and verifier
Commitment
Prover’s public commitment
Data
Public data that both parties know
InvalidProof
Error indicating that proof is invalid
NiProof
The non-interactive ZK proof. Computed by non_interactive::prove. Combines commitment and proof.
PrivateCommitment
Prover’s secret commitment nonce
PrivateData
Private data of prover
Proof
Range Proof with El-Gamal commitment. Computed by interactive::prove
SecurityParams
Security parameters for proof. Choosing the values is a tradeoff between security, speed and correctness

Type Aliases§

Challenge
Verifier’s challenge to prover. Can be obtained deterministically by non_interactive::challenge or randomly by interactive::challenge