Skip to content

Commit 84c089b

Browse files
committed
mod/proofs: completing the missing zero-knowledge proofs
This commit adds the zero-knowlege proof computation and verification for `proof_enc`, `proof_shuffle`, `proof_dlog`, and others.
1 parent 25553b8 commit 84c089b

4 files changed

Lines changed: 779 additions & 218 deletions

File tree

core/Cargo.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ serde = { version = "1.0", default-features = false }
88
rand = "0.8.5"
99
rug = "1.26.1"
1010
sha2 = "0.10.8"
11-
num-bigint = "0.4.6"
11+
num-bigint = { version = "0.4.6", features = ["rand"]}
1212
num-iter = "0.1.45"
1313
num-traits = "0.2.19"
14-
num-integer = "0.1.46"
14+
num-integer = "0.1.46"
15+
rand_chacha = "0.3.1"
16+
hex = "0.4.3"
17+
serde_json = "1.0.133"
18+
zerocopy = "0.8.13"

core/src/gm.rs

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Goldwasser-Micali Encryption and its AND variance
22
// Support 32-bit unsigned integers as plaintext
33

4-
use crate::number::{get_strong_prime, Jacobi};
4+
use crate::number::get_strong_prime;
55
use num_bigint::BigInt;
66
use num_traits::{One, Zero};
77
use rand::{rngs::StdRng, Rng, SeedableRng};
@@ -55,30 +55,29 @@ pub fn generate_keys(prime_size: Option<u64>) -> Keys {
5555

5656
static mut MY_COUNTER: u64 = 0;
5757

58-
pub fn get_next_random(n: BigInt) -> BigInt {
58+
pub fn get_next_random(n: &BigInt) -> BigInt {
5959
unsafe {
6060
MY_COUNTER += 1;
6161
n - BigInt::from(MY_COUNTER)
6262
}
6363
}
6464

65-
pub fn encrypt_bit_gm(bit: u8, n: &BigInt) -> BigInt {
66-
let r = get_next_random(n - 1);
67-
68-
let m = if bit == 1 { BigInt::one() } else { BigInt::zero() };
69-
(r.clone() * r.clone() * &(n - BigInt::one()).modpow(&m, &n)) % n
65+
pub fn encrypt_bit_gm(bit: &BigInt, n: &BigInt) -> BigInt {
66+
let r = get_next_random(&(n - BigInt::one()));
67+
(r.clone() * r.clone() * &(n - BigInt::one()).modpow(&bit, &n)) % n
7068
}
7169

72-
pub fn encrypt_bit_gm_coin(bit: u8, n: &BigInt, r: BigInt) -> BigInt {
70+
pub fn encrypt_bit_gm_coin(bit: &BigInt /* only 0 or 1 */, n: &BigInt, r: BigInt) -> BigInt {
7371
assert!(r >= BigInt::zero() && r <= n - 1);
74-
75-
let m = if bit == 1 { BigInt::one() } else { BigInt::zero() };
76-
(r.clone() * r.clone() * &(n - BigInt::one()).modpow(&m, &n)) % n
72+
(r.clone() * r.clone() * &(n - BigInt::one()).modpow(&bit, &n)) % n
7773
}
7874

79-
pub fn encrypt_gm(number: u32, pub_key: &BigInt) -> Vec<BigInt> {
75+
pub fn encrypt_gm(number: &BigInt, pub_key: &BigInt) -> Vec<BigInt> {
8076
let bits_str = format!("{:032b}", number);
81-
bits_str.chars().map(|bit| encrypt_bit_gm(bit.to_digit(2).unwrap() as u8, pub_key)).collect()
77+
bits_str
78+
.chars()
79+
.map(|bit| encrypt_bit_gm(&BigInt::from(bit.to_digit(2).unwrap()), pub_key))
80+
.collect()
8281
}
8382

8483
pub fn decrypt_bit_gm(c: &BigInt, sk_gm: &BigInt, n: &BigInt) -> u8 {
@@ -89,7 +88,7 @@ pub fn decrypt_bit_gm(c: &BigInt, sk_gm: &BigInt, n: &BigInt) -> u8 {
8988
}
9089
}
9190

92-
pub fn decrypt_gm(cipher_numbers: &[BigInt], priv_key: &(BigInt, BigInt)) -> Option<u32> {
91+
pub fn decrypt_gm(cipher_numbers: &[BigInt], priv_key: &(BigInt, BigInt)) -> Option<BigInt> {
9392
let (p, q) = priv_key;
9493
let n = p * q;
9594

@@ -101,21 +100,21 @@ pub fn decrypt_gm(cipher_numbers: &[BigInt], priv_key: &(BigInt, BigInt)) -> Opt
101100
.map(|bit| if bit == 1 { '1' } else { '0' }) // Convert BigInt to '1' or '0'
102101
.collect();
103102

104-
println!("String is {}", bits_str);
105-
106-
u32::from_str_radix(&bits_str, 2).ok()
103+
Some(BigInt::from(u32::from_str_radix(&bits_str, 2).unwrap()))
107104
}
108105

109106
pub fn encrypt_bit_and(bit: u8, pub_key: &BigInt) -> Vec<BigInt> {
110107
let mut rng = StdRng::from_entropy();
111108
if bit == 1 {
112-
(0..AND_SIZE_FACTOR).map(|_| encrypt_bit_gm(0, pub_key)).collect()
109+
(0..AND_SIZE_FACTOR).map(|_| encrypt_bit_gm(&BigInt::zero(), pub_key)).collect()
113110
} else {
114-
(0..AND_SIZE_FACTOR).map(|_| encrypt_bit_gm(rng.gen_range(0..=1), pub_key)).collect()
111+
(0..AND_SIZE_FACTOR)
112+
.map(|_| encrypt_bit_gm(&BigInt::from(rng.gen_range(0..=1)), pub_key))
113+
.collect()
115114
}
116115
}
117116

118-
pub fn decrypt_bit_and(cipher: &Vec<BigInt>, priv_key: (BigInt, BigInt)) -> u8 {
117+
pub fn decrypt_bit_and(cipher: &Vec<BigInt>, priv_key: &(BigInt, BigInt)) -> u8 {
119118
let (p, q) = priv_key;
120119
let sk_gm: BigInt = ((p.clone() - 1) * (q.clone() - 1)) / 4;
121120
let n = p.clone() * q.clone();
@@ -139,9 +138,9 @@ pub fn embed_bit_and(bit_cipher: &BigInt, pub_key: &BigInt, r: &[BigInt]) -> Vec
139138
(0..AND_SIZE_FACTOR)
140139
.map(|i| {
141140
if rng.gen_range(0..=1) == 1 {
142-
encrypt_bit_gm_coin(0, n, r[i].clone())
141+
encrypt_bit_gm_coin(&BigInt::zero(), n, r[i].clone())
143142
} else {
144-
encrypt_bit_gm_coin(0, n, r[i].clone()) * bit_cipher * (n - 1) % n
143+
encrypt_bit_gm_coin(&BigInt::zero(), n, r[i].clone()) * bit_cipher * (n - 1) % n
145144
}
146145
})
147146
.collect()
@@ -155,13 +154,13 @@ pub fn embed_and(cipher: &[BigInt], pub_key: &BigInt, r: &[Vec<BigInt>]) -> Vec<
155154
.collect()
156155
}
157156

158-
pub fn encrypt_gm_coin(mpz_number: u32, pub_key: BigInt, r: &[BigInt]) -> Vec<BigInt> {
157+
pub fn encrypt_gm_coin(mpz_number: &BigInt, pub_key: &BigInt, r: &[BigInt]) -> Vec<BigInt> {
159158
let bits_str = format!("{:032b}", mpz_number);
160159

161160
(0..32)
162161
.map(|i| {
163162
encrypt_bit_gm_coin(
164-
bits_str.chars().nth(i).unwrap().to_digit(2).unwrap() as u8,
163+
&BigInt::from(bits_str.chars().nth(i).unwrap().to_digit(2).unwrap()),
165164
&pub_key,
166165
r[i].clone(),
167166
)
@@ -172,6 +171,7 @@ pub fn encrypt_gm_coin(mpz_number: u32, pub_key: BigInt, r: &[BigInt]) -> Vec<Bi
172171
#[cfg(test)] // This module is included only during testing
173172
mod tests {
174173
use super::*;
174+
use crate::number::Jacobi;
175175
use std::time::Instant;
176176

177177
#[test]
@@ -199,13 +199,15 @@ mod tests {
199199
let mut rng = StdRng::from_entropy();
200200

201201
for _ in 0..iters {
202-
let num: u32 = rng.gen::<u32>();
203-
let mut cipher = encrypt_gm(num, &n);
202+
let num: BigInt = BigInt::from(rng.gen::<u32>());
203+
let mut cipher = encrypt_gm(&num, &n);
204204

205205
// Re-encryption
206206
for _ in 0..3 {
207-
cipher =
208-
cipher.iter().map(|c| (c * encrypt_gm(0u32, &n)[0].clone()) % &n).collect();
207+
cipher = cipher
208+
.iter()
209+
.map(|c| (c * encrypt_gm(&BigInt::zero(), &n)[0].clone()) % &n)
210+
.collect();
209211
}
210212

211213
let decrypted = decrypt_gm(&cipher, &keys.priv_key);
@@ -227,22 +229,31 @@ mod tests {
227229
let n = keys.pub_key;
228230
let priv_key = keys.priv_key;
229231

230-
let c0 = encrypt_bit_gm(0, &n);
231-
let c1 = encrypt_bit_gm(1, &n);
232+
let c0 = encrypt_bit_gm(&BigInt::zero(), &n);
233+
let c1 = encrypt_bit_gm(&BigInt::one(), &n);
232234

233235
// XOR tests
234-
assert_eq!(decrypt_gm(&[c0.clone() * c1.clone() % n.clone()], &priv_key), Some(1u32));
235-
assert_eq!(decrypt_gm(&[c0.clone() * c0.clone() % n.clone()], &priv_key), Some(0u32));
236-
assert_eq!(decrypt_gm(&[c1.clone() * c1.clone() % n.clone()], &priv_key), Some(0u32));
236+
assert_eq!(
237+
decrypt_gm(&[c0.clone() * c1.clone() % n.clone()], &priv_key),
238+
Some(BigInt::one())
239+
);
240+
assert_eq!(
241+
decrypt_gm(&[c0.clone() * c0.clone() % n.clone()], &priv_key),
242+
Some(BigInt::zero())
243+
);
244+
assert_eq!(
245+
decrypt_gm(&[c1.clone() * c1.clone() % n.clone()], &priv_key),
246+
Some(BigInt::zero())
247+
);
237248

238249
// Flip tests
239250
assert_eq!(
240251
decrypt_gm(&[c0.clone() * (n.clone() - 1) % n.clone()], &priv_key),
241-
Some(1u32)
252+
Some(BigInt::one())
242253
);
243254
assert_eq!(
244255
decrypt_gm(&[c1.clone() * (n.clone() - 1) % n.clone()], &priv_key),
245-
Some(0u32)
256+
Some(BigInt::zero())
246257
);
247258
}
248259

@@ -270,35 +281,26 @@ mod tests {
270281
enc_times.push(start.elapsed().as_secs_f64());
271282

272283
let start = Instant::now();
273-
let bit0 = decrypt_bit_and(&cipher0, priv_key.clone());
284+
let bit0 = decrypt_bit_and(&cipher0, &priv_key);
274285
dec_times.push(start.elapsed().as_secs_f64());
275286

276287
let start = Instant::now();
277-
let bit1 = decrypt_bit_and(&cipher1, priv_key.clone());
288+
let bit1 = decrypt_bit_and(&cipher1, &priv_key);
278289
dec_times.push(start.elapsed().as_secs_f64());
279290

280291
assert_eq!(bit0, 0u8);
281292
assert_eq!(bit1, 1u8);
282293

283294
assert_eq!(
284-
decrypt_bit_and(
285-
&dot_mod(&cipher0, &encrypt_bit_and(1u8, &n), &n),
286-
priv_key.clone()
287-
),
295+
decrypt_bit_and(&dot_mod(&cipher0, &encrypt_bit_and(1u8, &n), &n), &priv_key),
288296
0u8
289297
);
290298
assert_eq!(
291-
decrypt_bit_and(
292-
&dot_mod(&cipher0, &encrypt_bit_and(0u8, &n), &n),
293-
priv_key.clone()
294-
),
299+
decrypt_bit_and(&dot_mod(&cipher0, &encrypt_bit_and(0u8, &n), &n), &priv_key),
295300
0u8
296301
);
297302
assert_eq!(
298-
decrypt_bit_and(
299-
&dot_mod(&cipher1, &encrypt_bit_and(1u8, &n), &n),
300-
priv_key.clone()
301-
),
303+
decrypt_bit_and(&dot_mod(&cipher1, &encrypt_bit_and(1u8, &n), &n), &priv_key),
302304
1u8
303305
);
304306
}

0 commit comments

Comments
 (0)