Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Public Key Encryption circuit #31

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
745 changes: 745 additions & 0 deletions scripts/circuit_pk.py

Large diffs are not rendered by default.

20 changes: 13 additions & 7 deletions scripts/circuit_sk.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import os
from bfv.crt import CRTModuli
from bfv.bfv import BFVCrt
from bfv.bfv import BFV
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not required

from bfv.discrete_gauss import DiscreteGaussian
from bfv.polynomial import Polynomial, poly_div
from random import randint
import copy
from utils import assign_to_circuit, count_advice_cells_needed_for_poly_range_check, print_advice_cells_info
import argparse
import json
import numpy as np
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not required





def main(args):

Expand Down Expand Up @@ -36,9 +41,9 @@ def main(args):

ctis = bfv_crt.SecretKeyEncrypt(s, ais, e, m)

# Sanity check for valid decryption
# Sanity check for valid decryption
message_prime = bfv_crt.Decrypt(s, ctis)

assert m == message_prime

# k1 = [QM]t namely the scaled message polynomial
Expand Down Expand Up @@ -287,10 +292,11 @@ def main(args):

# sanity check. The coefficients of ai * s + e should be in the range $- (N \cdot \frac{q_i - 1}{2} + B), N \cdot \frac{q_i - 1}{2} + B]$
bound = int((qis[i] - 1) / 2) * n + b
res = ais[i] * s + e
print(f" sk r2 bound = {bound}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rmv

res = Polynomial(ais[i]) * s + e
assert all(coeff >= -bound and coeff <= bound for coeff in res.coefficients)

# constraint. The coefficients of r2i should be in the range [-(qi-1)/2, (qi-1)/2]
# constraint. The coefficients of r`2i should be in the range [-(qi-1)/2, (qi-1)/2]
r2i_bound = int((qis[i] - 1) / 2)
r2_bounds.append(r2i_bound)
assert all(coeff >= -r2i_bound and coeff <= r2i_bound for coeff in r2is[i].coefficients)
Expand Down Expand Up @@ -411,7 +417,7 @@ def main(args):
# Construct the dynamic filename
filename = f"sk_enc_{args.n}_{qis_len}x{qis_bitsize}_{args.t}.json"

output_path = os.path.join("src", "data", filename)
output_path = os.path.join("src", "data", "sk_enc_data",filename)

with open(output_path, 'w') as f:
json.dump(json_input, f)
Expand All @@ -427,12 +433,12 @@ def main(args):
"ct0is": [["0" for _ in ct0i_in_p.coefficients] for ct0i_in_p in ct0is_in_p],
}

output_path = os.path.join("src", "data", f"sk_enc_{args.n}_{qis_len}x{qis_bitsize}_{args.t}_zeroes.json")
output_path = os.path.join("src", "data","sk_enc_data", f"sk_enc_{args.n}_{qis_len}x{qis_bitsize}_{args.t}_zeroes.json")

with open(output_path, 'w') as f:
json.dump(json_input_zeroes, f)

output_path = os.path.join("src", "constants", f"sk_enc_constants_{args.n}_{qis_len}x{qis_bitsize}_{args.t}.rs")
output_path = os.path.join("src", "constants","sk_enc_constants", f"sk_enc_constants_{args.n}_{qis_len}x{qis_bitsize}_{args.t}.rs")

with open(output_path, 'w') as f:
f.write(f"/// `N` is the degree of the cyclotomic polynomial defining the ring `Rq = Zq[X]/(X^N + 1)`.\n")
Expand Down
99 changes: 99 additions & 0 deletions scripts/test_pk_enc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import os
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file shouldn't be here. If you want to test it, do it externally or fork the python bfv dependency and add a test there

from bfv.crt import CRTModuli
from bfv.bfv import BFVCrt
import numpy as np
from bfv.discrete_gauss import DiscreteGaussian
from bfv.polynomial import Polynomial, poly_div
from random import randint
import copy
from utils import assign_to_circuit, count_advice_cells_needed_for_poly_range_check, print_advice_cells_info
import argparse
import json

def main():
qis = [1152921504606584833,
1152921504598720513,
1152921504597016577,
1152921504595968001,
1152921504595640321,
1152921504593412097,
1152921504592822273,
1152921504592429057,
1152921504589938689,
1152921504586530817,
1152921504585547777,
1152921504583647233,
1152921504581877761,
1152921504581419009,
1152921504580894721]
crt_moduli = CRTModuli(qis)
n = 1024
sigma = 3.2
discrete_gaussian = DiscreteGaussian(sigma)
t = 65537
bfv_crt = BFVCrt(crt_moduli, n, t, discrete_gaussian)

s = bfv_crt.SecretKeyGen()
print(f"SECRET KEY LENGTH {len(s.coefficients)}")
e = bfv_crt.bfv_q.rlwe.SampleFromErrorDistribution()
ais = []
for i in range(len(crt_moduli.qis)):
ais.append(bfv_crt.bfv_qis[i].rlwe.Rq.sample_polynomial())

pub_keys = bfv_crt.PublicKeyGen(s,e,ais)
message = bfv_crt.bfv_q.rlwe.Rt.sample_polynomial()

pk_array = []
print(f"NUMBER OF PUBLIC KEY {len(pub_keys)}")

for i,pk in enumerate(pub_keys):
print(f"pk length ={len(pk[0].coefficients)}")
pk_array.append(pk[0].coefficients)

print(f"LENGTH OF PK ARRAY {len(pk_array)}")



e0 = bfv_crt.bfv_q.rlwe.SampleFromErrorDistribution()
e1 = bfv_crt.bfv_q.rlwe.SampleFromErrorDistribution()
u = bfv_crt.bfv_q.rlwe.SampleFromTernaryDistribution()

ciphertexts = bfv_crt.PubKeyEncrypt(pub_keys,message,e0,e1,u)
print(f"NUMBER OF CIPHER TEXTS {len(ciphertexts)}")
message_prime = bfv_crt.DecryptDummy(s,ciphertexts)




message_prime == message

cyclo = [1] + [0] * (n - 1) + [1]
cyclo = Polynomial(cyclo)

k1 = message.scalar_mul(crt_moduli.q)
k1.reduce_coefficients_by_modulus(t)

for i, cti in enumerate(ciphertexts):
ct0i =cti[0]

k0i = pow(-t,-1,qis[i])
pk0 = Polynomial(pk_array[i])

ct0i_hat = pk0 * u + e0 + k1.scalar_mul(k0i)
assert(len(ct0i_hat.coefficients) - 1 == 2 * n - 2)

ct0i_hat_clone = copy.deepcopy(ct0i_hat)

ct0i_hat_clone.reduce_coefficients_by_cyclo(cyclo.coefficients)
ct0i_hat_clone.reduce_coefficients_by_modulus(qis[i])
print(f"for iteration ith ={i}")
assert ct0i_hat_clone == ct0i

print(" CHECK PASSED ")





main()

2 changes: 1 addition & 1 deletion scripts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def count_advice_cells_needed_for_poly_range_check(poly: Polynomial, bound: int,

count = 0

# 4 advice cells for each coefficient needed for the shift addition operation
# 4 advice cells for each coefficient needed for the shift addition operation``
count += 4 * len(poly.coefficients)

# further advice cells for range check inside `check_less_than_safe`
Expand Down
8 changes: 2 additions & 6 deletions src/constants/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
pub mod sk_enc_constants_1024_1x27_65537;
pub mod sk_enc_constants_16384_8x54_65537;
pub mod sk_enc_constants_2048_1x53_65537;
pub mod sk_enc_constants_32768_15x59_65537;
pub mod sk_enc_constants_4096_2x55_65537;
pub mod sk_enc_constants_8192_4x55_65537;
pub mod pk_enc_constants;
pub mod sk_enc_constants;
1 change: 1 addition & 0 deletions src/constants/pk_enc_constants/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod pk_enc_constants_1024_15x60_65537;
108 changes: 108 additions & 0 deletions src/constants/pk_enc_constants/pk_enc_constants_1024_15x60_65537.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/// `N` is the degree of the cyclotomic polynomial defining the ring `Rq = Zq[X]/(X^N + 1)`.
pub const N: usize = 1024;
///'The coefficients pf the polynomial 'pk0is` and 'pk1is' should exist in the interval '[-PK_BOUND, PK_BOUND]`.
pub const PK_BOUND: [u64; 15] = [
576460752303292416,
576460752299360256,
576460752298508288,
576460752297984000,
576460752297820160,
576460752296706048,
576460752296411136,
576460752296214528,
576460752294969344,
576460752293265408,
576460752292773888,
576460752291823616,
576460752290938880,
576460752290709504,
576460752290447360,
];
///'The coefficients pf the polynomial 'pk1is` should exist in the interval '[-PK0_BOUND, PK0_BOUND]`.
/// The coefficients of the polynomial `e` should exist in the interval `[-E_BOUND, E_BOUND]` where `E_BOUND` is the upper bound of the gaussian distribution with 𝜎 = 3.2
pub const E_BOUND: u64 = 19;
/// The coefficients of the polynomial `s` should exist in the interval `[-S_BOUND, S_BOUND]`.
pub const U_BOUND: u64 = 1;
/// The coefficients of the polynomials `r1is` should exist in the interval `[-R1_BOUND[i], R1_BOUND[i]]` where `R1_BOUND[i]` is equal to `(qi-1)/2`
pub const R1_BOUNDS: [u64; 15] = [
32472, 21654, 32101, 32263, 14784, 16206, 30376, 18254, 9343, 14780, 9752, 27859, 2356, 17131,
17884,
];
/// The coefficients of the polynomials `r2is` should exist in the interval `[-R2_BOUND[i], R2_BOUND[i]]` where `R2_BOUND[i]` is equal to $\frac{(N+2) \cdot \frac{q_i - 1}{2} + B + \frac{t - 1}{2} \cdot |K_{0,i}|}{q_i}$
pub const R2_BOUNDS: [u64; 15] = [
576460752303292416,
576460752299360256,
576460752298508288,
576460752297984000,
576460752297820160,
576460752296706048,
576460752296411136,
576460752296214528,
576460752294969344,
576460752293265408,
576460752292773888,
576460752291823616,
576460752290938880,
576460752290709504,
576460752290447360,
];
/// The coefficients of the polynomials `p1is` should exist in the interval `[-P1_BOUND[i], P1_BOUND[i]]` where `P1_BOUND[i]` is equal to (((qis[i] - 1) / 2) * (n + 2) + b ) / qis[i]
pub const P1_BOUNDS: [u64; 15] = [
513, 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, 513,
];
/// The coefficients of the polynomials `p2is` should exist in the interval `[-P2_BOUND[i], P2_BOUND[i]]` where `P2_BOUND[i]` is equal to (qis[i] - 1) / 2
pub const P2_BOUNDS: [u64; 15] = [
576460752303292416,
576460752299360256,
576460752298508288,
576460752297984000,
576460752297820160,
576460752296706048,
576460752296411136,
576460752296214528,
576460752294969344,
576460752293265408,
576460752292773888,
576460752291823616,
576460752290938880,
576460752290709504,
576460752290447360,
];
/// The coefficients of `k1` should exist in the interval `[-K1_BOUND, K1_BOUND]` where `K1_BOUND` is equal to `(t-1)/2`
pub const K1_BOUND: u64 = 32768;
/// List of scalars `qis` such that `qis[i]` is the modulus of the i-th CRT basis of `q` (ciphertext space modulus)
pub const QIS: [&str; 15] = [
"1152921504606584833",
"1152921504598720513",
"1152921504597016577",
"1152921504595968001",
"1152921504595640321",
"1152921504593412097",
"1152921504592822273",
"1152921504592429057",
"1152921504589938689",
"1152921504586530817",
"1152921504585547777",
"1152921504583647233",
"1152921504581877761",
"1152921504581419009",
"1152921504580894721",
];
/// List of scalars `k0is` such that `k0i[i]` is equal to the negative of the multiplicative inverses of t mod qi.
pub const K0IS: [&str; 15] = [
"1124457781908666798",
"743839052427601194",
"1111422170948171465",
"1117121952253736973",
"502126104424574846",
"552157518114552474",
"1050730055179823439",
"624214012656257690",
"310690856959624444",
"501985369079705462",
"325081045565655086",
"962154749991507364",
"64878992155545191",
"584702565692244436",
"611213585534257079",
];
18 changes: 18 additions & 0 deletions src/constants/pk_enc_constants_1024_15x60_65537.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// `N` is the degree of the cyclotomic polynomial defining the ring `Rq = Zq[X]/(X^N + 1)`.
pub const N: usize = 1024;
///'The coefficients pf the polynomial 'pk0is` should exist in the interval '[-PK0_BOUND, PK0_BOUND]`.
pub const PK0_BOUND:u64 = 590295810345418096640;
/// The coefficients of the polynomial `e` should exist in the interval `[-E_BOUND, E_BOUND]` where `E_BOUND` is the upper bound of the gaussian distribution with 𝜎 = 3.2
pub const E_BOUND: u64 = 19;
/// The coefficients of the polynomial `s` should exist in the interval `[-S_BOUND, S_BOUND]`.
pub const u_BOUND: u64 = 1;
/// The coefficients of the polynomials `r1is` should exist in the interval `[-R1_BOUND[i], R1_BOUND[i]]` where `R1_BOUND[i]` is equal to `(qi-1)/2`
pub const R1_BOUNDS: [u64; 15] = [32472, 21654, 32101, 32263, 14784, 16206, 30376, 18254, 9343, 14780, 9752, 27859, 2356, 17131, 17884];
/// The coefficients of the polynomials `r2is` should exist in the interval `[-R2_BOUND[i], R2_BOUND[i]]` where `R2_BOUND[i]` is equal to $\frac{(N+2) \cdot \frac{q_i - 1}{2} + B + \frac{t - 1}{2} \cdot |K_{0,i}|}{q_i}$
pub const R2_BOUNDS: [u64; 15] = [576460752303292416, 576460752299360256, 576460752298508288, 576460752297984000, 576460752297820160, 576460752296706048, 576460752296411136, 576460752296214528, 576460752294969344, 576460752293265408, 576460752292773888, 576460752291823616, 576460752290938880, 576460752290709504, 576460752290447360];
/// The coefficients of `k1` should exist in the interval `[-K1_BOUND, K1_BOUND]` where `K1_BOUND` is equal to `(t-1)/2`
pub const K1_BOUND: u64 = 32768;
/// List of scalars `qis` such that `qis[i]` is the modulus of the i-th CRT basis of `q` (ciphertext space modulus)
pub const QIS: [&str; 15] = ["1152921504606584833", "1152921504598720513", "1152921504597016577", "1152921504595968001", "1152921504595640321", "1152921504593412097", "1152921504592822273", "1152921504592429057", "1152921504589938689", "1152921504586530817", "1152921504585547777", "1152921504583647233", "1152921504581877761", "1152921504581419009", "1152921504580894721"];
/// List of scalars `k0is` such that `k0i[i]` is equal to the negative of the multiplicative inverses of t mod qi.
pub const K0IS: [&str; 15] = ["1124457781908666798", "743839052427601194", "1111422170948171465", "1117121952253736973", "502126104424574846", "552157518114552474", "1050730055179823439", "624214012656257690", "310690856959624444", "501985369079705462", "325081045565655086", "962154749991507364", "64878992155545191", "584702565692244436", "611213585534257079"];
1 change: 1 addition & 0 deletions src/constants/sk_enc_constants/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod sk_enc_constants_4096_2x55_65537;
18 changes: 18 additions & 0 deletions src/constants/sk_enc_constants_1024_15x60_65537.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// `N` is the degree of the cyclotomic polynomial defining the ring `Rq = Zq[X]/(X^N + 1)`.
pub const N: usize = 1024;
///'The coefficients pf the polynomial 'pk0is` should exist in the interval '[-PK0_BOUND, PK0_BOUND]`.
pub const PK0_BOUND:u64 = 590295810345418096640;
/// The coefficients of the polynomial `e` should exist in the interval `[-E_BOUND, E_BOUND]` where `E_BOUND` is the upper bound of the gaussian distribution with 𝜎 = 3.2
pub const E_BOUND: u64 = 19;
/// The coefficients of the polynomial `s` should exist in the interval `[-S_BOUND, S_BOUND]`.
pub const u_BOUND: u64 = 1;
/// The coefficients of the polynomials `r1is` should exist in the interval `[-R1_BOUND[i], R1_BOUND[i]]` where `R1_BOUND[i]` is equal to `(qi-1)/2`
pub const R1_BOUNDS: [u64; 15] = [32472, 21654, 32101, 32263, 14784, 16206, 30376, 18254, 9343, 14780, 9752, 27859, 2356, 17131, 17884];
/// The coefficients of the polynomials `r2is` should exist in the interval `[-R2_BOUND[i], R2_BOUND[i]]` where `R2_BOUND[i]` is equal to $\frac{(N+2) \cdot \frac{q_i - 1}{2} + B + \frac{t - 1}{2} \cdot |K_{0,i}|}{q_i}$
pub const R2_BOUNDS: [u64; 15] = [576460752303292416, 576460752299360256, 576460752298508288, 576460752297984000, 576460752297820160, 576460752296706048, 576460752296411136, 576460752296214528, 576460752294969344, 576460752293265408, 576460752292773888, 576460752291823616, 576460752290938880, 576460752290709504, 576460752290447360];
/// The coefficients of `k1` should exist in the interval `[-K1_BOUND, K1_BOUND]` where `K1_BOUND` is equal to `(t-1)/2`
pub const K1_BOUND: u64 = 32768;
/// List of scalars `qis` such that `qis[i]` is the modulus of the i-th CRT basis of `q` (ciphertext space modulus)
pub const QIS: [&str; 15] = ["1152921504606584833", "1152921504598720513", "1152921504597016577", "1152921504595968001", "1152921504595640321", "1152921504593412097", "1152921504592822273", "1152921504592429057", "1152921504589938689", "1152921504586530817", "1152921504585547777", "1152921504583647233", "1152921504581877761", "1152921504581419009", "1152921504580894721"];
/// List of scalars `k0is` such that `k0i[i]` is equal to the negative of the multiplicative inverses of t mod qi.
pub const K0IS: [&str; 15] = ["1124457781908666798", "743839052427601194", "1111422170948171465", "1117121952253736973", "502126104424574846", "552157518114552474", "1050730055179823439", "624214012656257690", "310690856959624444", "501985369079705462", "325081045565655086", "962154749991507364", "64878992155545191", "584702565692244436", "611213585534257079"];
16 changes: 0 additions & 16 deletions src/constants/sk_enc_constants_16384_8x54_65537.rs

This file was deleted.

16 changes: 0 additions & 16 deletions src/constants/sk_enc_constants_2048_1x53_65537.rs

This file was deleted.

Loading
Loading