Skip to content

Instantly share code, notes, and snippets.

@bquast
Last active January 3, 2024 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bquast/151fddbddc4b5539c65d780440476f72 to your computer and use it in GitHub Desktop.
Save bquast/151fddbddc4b5539c65d780440476f72 to your computer and use it in GitHub Desktop.
BFV in python without using functions
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