Expand description
ZK-proof, called Пlog* or Rlog* in the CGGMP21 paper.
§Description
A party P has a number X = x G
, with G being a generator of
curve E
. P has encrypted x as C. P shares X and C with V and
wants to prove that the logarithm of X is the plaintext of C, and that the
plaintext (i.e. x) is at most l bits.
Given:
key0
,pkey0
- pair of public and private keys in paillier cryptosystem- Curve
E
X = x G
andC = key0.encrypt(x)
- data to obtain proof about
Prove:
decrypt(C) = log X
bitsize(x) <= l
Disclosing only: key0
, C
, X
§Example
use rug::{Integer, Complete};
use generic_ec::{Point, curves::Secp256k1 as E};
use paillier_zk::{group_element_vs_paillier_encryption_in_range as p, IntegerExt};
// Prover and verifier have a shared protocol state
let shared_state_prover = sha2::Sha256::default();
let shared_state_verifier = sha2::Sha256::default();
let mut rng = rand_core::OsRng;
// 0. Setup: prover and verifier share common Ring-Pedersen parameters:
let aux: p::Aux = pregenerated::verifier_aux();
let security = p::SecurityParams {
l: 1024,
epsilon: 300,
q: (Integer::ONE << 128_u32).complete(),
};
// 1. Setup: prover prepares the paillier keys
let private_key: fast_paillier::DecryptionKey =
pregenerated::prover_decryption_key();
let key0 = private_key.encryption_key();
// 2. Setup: prover has some plaintext `x`, encrypts it and obtains `C`, and computes `X`
let x = Integer::from_rng_pm(&(Integer::ONE << security.l).complete(), &mut rng);
let (C, nonce) = key0.encrypt_with_random(&mut rng, &x)?;
let X = Point::<E>::generator() * x.to_scalar();
// 3. Prover computes a non-interactive proof that plaintext is at most `l` bits:
let data = p::Data {
key0,
c: &C,
x: &X,
b: &Point::<E>::generator().into(),
};
let (commitment, proof) =
p::non_interactive::prove(
shared_state_prover,
&aux,
data,
p::PrivateData { x: &x, nonce: &nonce },
&security,
&mut rng,
)?;
// 4. Prover sends this data to verifier
send(&data, &commitment, &proof);
// 5. Verifier receives the data and the proof and verifies it
let (data, commitment, proof) = recv();
p::non_interactive::verify(
shared_state_verifier,
&aux,
data,
&commitment,
&security,
&proof,
)?;
If the verification succeeded, verifier can continue communication with prover
Modules§
- 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.
- The non-interactive version of proof. Completed in one round, for example see the documentation of parent module.
Structs§
- Auxiliary data known to both prover and verifier
- Prover’s first message, obtained by
interactive::commit
- Public data that both parties know
- Prover’s data accompanying the commitment. Kept as state between rounds in the interactive protocol.
- Private data of prover
- The ZK proof. Computed by
interactive::prove
ornon_interactive::prove
- Security parameters for proof. Choosing the values is a tradeoff between speed and chance of rejecting a valid proof or accepting an invalid proof
Type Aliases§
- Verifier’s challenge to prover. Can be obtained deterministically by
non_interactive::challenge
or randomly byinteractive::challenge