Expand description
ZK-proof of paillier operation with group commitment in range. Called Пaff-g or Raff-g in the CGGMP21 paper.
§Description
A party P performs a paillier affine operation with C, Y, and X
obtaining D = C*X + Y
. X
and Y
are encrypted values of x
and y
. P
then wants to prove that y
and x
are at most L
and L'
bits,
correspondingly, and P doesn’t want to disclose none of the plaintexts
Given:
key0
,pkey0
,key1
,pkey1
- pairs of public and private keys in paillier cryptosystemnonce_y
,nonce
- nonces in paillier encryptionx
,y
- some numbersq
,g
such that<g> = Zq*
- prime order groupC
is some ciphertext encrypted bykey0
Y = key1.encrypt(y, nonce_y)
X = g * x
D = oadd(enc(y, nonce), omul(x, C))
whereenc
,oadd
andomul
are paillier encryption, homomorphic addition and multiplication withkey0
Prove:
bitsize(abs(x)) <= l_x
bitsize(abs(y)) <= l_y
Disclosing only: key0
, key1
, C
, D
, Y
, X
§Example
use paillier_zk::{paillier_affine_operation_in_range as p, IntegerExt};
use rug::{Integer, Complete};
use generic_ec::{Point, curves::Secp256k1 as E};
// 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_x: 256,
l_y: 848,
epsilon: 230,
q: (Integer::ONE << 128_u32).complete(),
};
// 1. Setup: prover prepares the paillier keys
// C and D are encrypted by this key
let key0: fast_paillier::EncryptionKey = pregenerated::someone_encryption_key0();
// Y is encrypted using this key
let key1: fast_paillier::EncryptionKey = pregenerated::someone_encryption_key1();
// C is some number encrypted using key0. Neither of parties
// need to know the plaintext
let ciphertext_c = Integer::gen_invertible(&key0.nn(), &mut rng);
// 2. Setup: prover prepares all plaintexts
// x in paper
let plaintext_x = Integer::from_rng_pm(
&(Integer::ONE << security.l_x).complete(),
&mut rng,
);
// y in paper
let plaintext_y = Integer::from_rng_pm(
&(Integer::ONE << security.l_y).complete(),
&mut rng,
);
// 3. Setup: prover encrypts everything on correct keys and remembers some nonces
// X in paper
let ciphertext_x = Point::<E>::generator() * plaintext_x.to_scalar();
// Y and ρ_y in paper
let (ciphertext_y, nonce_y) = key1.encrypt_with_random(
&mut rng,
&(plaintext_y.signed_modulo(key1.n())),
)?;
// nonce is ρ in paper
let (ciphertext_y_by_key1, nonce) = key0.encrypt_with_random(
&mut rng,
&(plaintext_y.signed_modulo(key0.n()))
)?;
// D in paper
let ciphertext_d = key0
.oadd(
&key0.omul(&plaintext_x, &ciphertext_c)?,
&ciphertext_y_by_key1,
)?;
// 4. Prover computes a non-interactive proof that plaintext_x and
// plaintext_y are at most `l_x` and `l_y` bits
let data = p::Data {
key0: &key0,
key1: &key1,
c: &ciphertext_c,
d: &ciphertext_d,
x: &ciphertext_x,
y: &ciphertext_y,
};
let pdata = p::PrivateData {
x: &plaintext_x,
y: &plaintext_y,
nonce: &nonce,
nonce_y: &nonce_y,
};
let (commitment, proof) =
p::non_interactive::prove(
shared_state_prover,
&aux,
data,
pdata,
&security,
&mut rng,
)?;
// 5. Prover sends this data to verifier
send(&data, &commitment, &proof);
// 6. Verifier receives the data and the proof and verifies it
let (data, commitment, proof) = recv();
let r = 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
- Error indicating that proof is invalid
- 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