Skip to content

Instantly share code, notes, and snippets.

@bquast
Created January 3, 2024 14:05
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/ae54db3a1c3087420995a27d855ba986 to your computer and use it in GitHub Desktop.
Save bquast/ae54db3a1c3087420995a27d855ba986 to your computer and use it in GitHub Desktop.
BGV in Python
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(123)
# Parameters
d = 4
n = 2 ** d
p = (n // 2) - 1
q = 868
# 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 + p * e), pm)
pk1 = mod_on_coefficients(pk1, q)
pk2 = a
# Message
m = Polynomial([3, 2, 1] + [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
ct1 = polynomial_modulo(pk1 * u + p * e1 + m, pm)
ct1 = mod_on_coefficients(ct1, q)
ct2 = polynomial_modulo(pk2 * u + p * e2, pm)
ct2 = mod_on_coefficients(ct2, q)
# Decryption
decrypt = polynomial_modulo(ct2 * s + ct1, pm)
decrypt = mod_on_coefficients(decrypt, q)
rounded_decrypt = Polynomial(np.round(decrypt.coef))
decrypt = mod_on_coefficients(rounded_decrypt, p)
# Print results
print("decrypt:", decrypt.coef)
# Continuing from the previous translated Python code
# Cipher sum
ct1sum = ct1 + ct1
ct2sum = ct2 + ct2
# Decrypt cipher sum
decrypt_sum = polynomial_modulo(ct2sum * s + ct1sum, pm)
decrypt_sum = mod_on_coefficients(decrypt_sum, q)
rounded_decrypt_sum = Polynomial(np.round(decrypt_sum.coef))
decrypt_sum = mod_on_coefficients(rounded_decrypt_sum, p)
# Print results for cipher sum decryption
print("decrypt_sum:", decrypt_sum.coef)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment