Hi, I am using the openfhe-python
wrapper and I noticed that when using EvalMultMutable()
with BFVRNS the produced result is not correct. I played around a bit and found out that with BGVRNS the function works properly. Additionally, the result stays the same across multiple calls of the function in the same script, but changes when you run the script again.
In the same time I found out that EvalMultMutableInPlace()
does not work for either BFVRNS or BGVRNS. Any insight?
Currently I have only tested it in openfhe-python
. I am using python-openfhe
version 0.8.1 with openfhe
version 1.2.0 on Ubuntu 22.04 with gcc
version 11.4.0.
I include an example below to reproduce this behavior.
from openfhe import *
# Set CryptoContext and FHE parameters
parameters = CCParamsBFVRNS()
depth = 1
plainmod = 786433
parameters.SetPlaintextModulus(plainmod)
parameters.SetMultiplicativeDepth(depth)
parameters.SetSecurityLevel(HEStd_128_classic)
crypto_context = GenCryptoContext(parameters)
crypto_context.Enable(PKESchemeFeature.PKE)
crypto_context.Enable(PKESchemeFeature.KEYSWITCH)
crypto_context.Enable(PKESchemeFeature.LEVELEDSHE)
crypto_context.Enable(ADVANCEDSHE)
# Generate a public/private key pair
key_pair = crypto_context.KeyGen()
# Generate the relinearization key
crypto_context.EvalMultKeyGen(key_pair.secretKey)
a = [5]
b = [8]
packed_a = crypto_context.MakePackedPlaintext(a)
packed_b = crypto_context.MakePackedPlaintext(b)
enc_a = crypto_context.Encrypt(key_pair.publicKey, packed_a)
enc_b = crypto_context.Encrypt(key_pair.publicKey, packed_b)
print("a: ", a)
print("b: ", b)
print(f"EvalMultMutable() with a and b with BFV...")
enc_result = []
for i in range(2):
enc_result.append(crypto_context.EvalMultMutable(enc_a, enc_b))
# Decrypt, set length and unpack
decrypted_result = crypto_context.Decrypt(enc_result[i], key_pair.secretKey)
decrypted_result.SetLength(1)
dec = decrypted_result.GetPackedValue()
print ("a * b: ", dec)
print(f"EvalMultMutableInPlace() with a and b with BFV...")
enc_result = []
for i in range(2):
crypto_context.EvalMultMutableInPlace(enc_a, enc_b)
enc_result.append(enc_a)
# Decrypt, set length and unpack
decrypted_result = crypto_context.Decrypt(enc_result[i], key_pair.secretKey)
decrypted_result.SetLength(1)
dec = decrypted_result.GetPackedValue()
print ("a * b: ", dec)
# Set CryptoContext and FHE parameters
parameters = CCParamsBGVRNS()
depth = 1
plainmod = 786433
parameters.SetPlaintextModulus(plainmod)
parameters.SetMultiplicativeDepth(depth)
parameters.SetSecurityLevel(HEStd_128_classic)
crypto_context = GenCryptoContext(parameters)
crypto_context.Enable(PKESchemeFeature.PKE)
crypto_context.Enable(PKESchemeFeature.KEYSWITCH)
crypto_context.Enable(PKESchemeFeature.LEVELEDSHE)
crypto_context.Enable(ADVANCEDSHE)
# Generate a public/private key pair
key_pair = crypto_context.KeyGen()
# Generate the relinearization key
crypto_context.EvalMultKeyGen(key_pair.secretKey)
packed_a = crypto_context.MakePackedPlaintext(a)
packed_b = crypto_context.MakePackedPlaintext(b)
enc_a = crypto_context.Encrypt(key_pair.publicKey, packed_a)
enc_b = crypto_context.Encrypt(key_pair.publicKey, packed_b)
print(f"EvalMultMutable() with a and b with BGV...")
enc_result = []
for i in range(2):
enc_result.append(crypto_context.EvalMultMutable(enc_a, enc_b))
# Decrypt, set length and unpack
decrypted_result = crypto_context.Decrypt(enc_result[i], key_pair.secretKey)
decrypted_result.SetLength(1)
dec = decrypted_result.GetPackedValue()
print ("a * b: ", dec)
print(f"EvalMultMutableInPlace() with a and b with BGV...")
enc_result = []
for i in range(2):
crypto_context.EvalMultMutableInPlace(enc_a, enc_b)
enc_result.append(enc_a)
# Decrypt, set length and unpack
decrypted_result = crypto_context.Decrypt(enc_result[i], key_pair.secretKey)
decrypted_result.SetLength(1)
dec = decrypted_result.GetPackedValue()
print ("a * b: ", dec)
and this is a sample output:
a: [5]
b: [8]
EvalMultMutable() with a and b with BFV...
a * b: [77167]
a * b: [77167]
EvalMultMutableInPlace() with a and b with BFV...
a * b: [5]
a * b: [5]
EvalMultMutable() with a and b with BGV...
a * b: [40]
a * b: [40]
EvalMultMutableInPlace() with a and b with BGV...
a * b: [5]
a * b: [5]