Last active
January 3, 2024 13:56
-
-
Save bquast/151fddbddc4b5539c65d780440476f72 to your computer and use it in GitHub Desktop.
BFV in python without using functions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
from numpy.polynomial import Polynomial | |
def polynomial_modulo(polynomial, mod): | |
""" | |
Perform polynomial modulo operation using divmod. | |
""" | |
q, r = divmod(polynomial, mod) | |
return r | |
def mod_on_coefficients(polynomial, modulo): | |
""" | |
Apply the modulo on the coefficients of a polynomial. | |
""" | |
coefs = polynomial.coef | |
mod_coefs = [c % modulo for c in coefs] | |
return Polynomial(mod_coefs) | |
# Set seed for reproducibility | |
np.random.seed(1) | |
# Parameters | |
d = 4 | |
n = 2 ** d | |
p = (n // 2) - 1 | |
q = 874 | |
# Generate polynomials | |
pm = Polynomial([1] + [0]*(n - 1) + [1]) # Polynomial for modulo operation | |
s = Polynomial(np.random.randint(-1, 2, n)) # Secret key | |
a = Polynomial(np.random.randint(0, q, n)) # a | |
e = Polynomial(np.round(np.random.normal(0, n / 3, n))) # Error term | |
# Public keys | |
pk1 = polynomial_modulo(-(a * s + e), pm) | |
pk1 = mod_on_coefficients(pk1, q) | |
pk2 = a | |
# Message | |
m = Polynomial([6, 4, 2] + [0]*(n - 3)) | |
# Encryption polynomials | |
e1 = Polynomial(np.round(np.random.normal(0, n / 3, n))) | |
e2 = Polynomial(np.round(np.random.normal(0, n / 3, n))) | |
u = Polynomial(np.random.randint(-1, 2, n - 1)) | |
# Ciphertexts | |
floor_q_p = np.floor(q / p) | |
ct1 = polynomial_modulo(pk1 * u + e1 + floor_q_p * m, pm) | |
ct1 = mod_on_coefficients(ct1, q) | |
ct2 = polynomial_modulo(pk2 * u + e2, pm) | |
ct2 = mod_on_coefficients(ct2, q) | |
# Decryption | |
decrypt = polynomial_modulo(ct2 * s + ct1, pm) | |
decrypt = mod_on_coefficients(decrypt, q) | |
# Rescale and round then mod p | |
rescale_factor = p / q | |
rescaled_decrypt = decrypt * rescale_factor | |
rounded_rescaled_decrypt = np.round(rescaled_decrypt.coef).astype(int) | |
# Apply mod p to the rounded, rescaled coefficients | |
final_decrypt = np.mod(rounded_rescaled_decrypt, p) | |
# Print results | |
print("decrypt:", final_decrypt) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment