-
Notifications
You must be signed in to change notification settings - Fork 78
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
scalar product between plain vector and cipher vector #176
Comments
Your best bet is to encode the plaintext vectors: def scalar_product_pc(HE, v1, v2):
# Encrypt each vector into one (if l <= n_slots) or several ciphertexts (l>n)
p1 = [HE.encode(v1[j:j+HE.get_nSlots()]) for j in range(0,l,HE.get_nSlots())]
c2 = [HE.encrypt(v2[j:j+HE.get_nSlots()]) for j in range(0,l,HE.get_nSlots())]
if len(p1)==len(c2)==1:
cRes = p1 [0] @ c2[0]
else:
cRes = [~(p1[i]*c2[i]) for i in range(len(c1))]
for i in range(1,len(cRes)):
cRes[0] += cRes[i]
cRes = HE.cumul_add(cRes[0])
return cRes |
I encode v1 and meet import numpy as np
rng = np.random.default_rng(42)
CASE_SELECTOR = 2 # 1 or 2
case_params = {
1: {'l': 256}, # small l
2: {'l': 65536}, # large l
}[CASE_SELECTOR]
l = case_params['l']
from Pyfhel import Pyfhel
def get_CKKS_context_scalar_prod(l: int, sec: int=128, use_n_min: bool=True) ->Pyfhel:
n_min = 2**13
if use_n_min: n = n_min # use n_min regardless of l
elif 2*l < n_min: n = n_min # Smallest
elif 2*l > 2**15: n = 2**15 # Largest
else: n = get_closest_power_of_two(2*l)
context_params = {
'scheme': 'CKKS',
'n': n, # Poly modulus degree. BFV ptxt is a n//2 by 2 matrix.
'sec': sec, # Security level.
'scale': 2**20,
'qi_sizes': [60, 20, 60], # Max number of multiplications = 1
}
HE = Pyfhel(context_params)
return HE
def scalar_product_cc(HE, v1, v2):
# Encrypt each vector into one (if l <= n_slots) or several ciphertexts (l>n)
c1 = [HE.encrypt(v1[j:j+HE.get_nSlots()]) for j in range(0,l,HE.get_nSlots())]
c2 = [HE.encrypt(v2[j:j+HE.get_nSlots()]) for j in range(0,l,HE.get_nSlots())]
if len(c1)==len(c2)==1:
cRes = c1[0] @ c2[0]
else:
cRes = [~(c1[i]*c2[i]) for i in range(len(c1))]
for i in range(1,len(cRes)):
cRes[0] += cRes[i]
cRes = HE.cumul_add(cRes[0])
return cRes
def scalar_product_pc(HE, v1, v2):
# Encrypt each vector into one (if l <= n_slots) or several ciphertexts (l>n)
p1 = [HE.encode(v1[j:j+HE.get_nSlots()]) for j in range(0,l,HE.get_nSlots())]
c2 = [HE.encrypt(v2[j:j+HE.get_nSlots()]) for j in range(0,l,HE.get_nSlots())]
if len(p1)==len(c2)==1:
cRes = p1 [0] @ c2[0]
else:
cRes = [~(p1[i]*c2[i]) for i in range(len(p1))]
for i in range(1,len(cRes)):
cRes[0] += cRes[i]
cRes = HE.cumul_add(cRes[0])
return cRes
if __name__ == '__main__':
HE = get_CKKS_context_scalar_prod(l, sec=128, use_n_min=True)
HE.keyGen()
HE.relinKeyGen()
HE.rotateKeyGen()
v1 = np.random.rand(768)
v2 = np.random.rand(768)
spRes = v1@v2
print("Plain Res:", spRes)
cRes = scalar_product_cc(HE, v1, v2)
res = HE.decrypt(cRes)[0]
print("HE Res bwtween cipher and cipher:", res)
cRes = scalar_product_pc(HE, v1, v2)
res = HE.decrypt(cRes)[0]
print("HE Res bwtween plaintext and cipher:", res) error info: Plain Res: 198.24648958483448
HE Res bwtween cipher and cipher: 198.24917665919565
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
Cell In[13], line 79
76 res = HE.decrypt(cRes)[0]
77 print("HE Res bwtween cipher and cipher:", res)
---> 79 cRes = scalar_product_pc(HE, v1, v2)
80 res = HE.decrypt(cRes)[0]
82 print("HE Res bwtween plaintext and cipher:", res)
Cell In[13], line 55, in scalar_product_pc(HE, v1, v2)
53 cRes = p1 [0] @ c2[0]
54 else:
---> 55 cRes = [~(p1[i]*c2[i]) for i in range(len(p1))]
56 for i in range(1,len(cRes)):
57 cRes[0] += cRes[i]
Cell In[13], line 55, in <listcomp>(.0)
53 cRes = p1 [0] @ c2[0]
54 else:
---> 55 cRes = [~(p1[i]*c2[i]) for i in range(len(p1))]
56 for i in range(1,len(cRes)):
57 cRes[0] += cRes[i]
File Pyfhel/PyCtxt.pyx:473, in Pyfhel.PyCtxt.PyCtxt.__rmul__()
File Pyfhel/PyCtxt.pyx:468, in Pyfhel.PyCtxt.PyCtxt.__mul__()
File Pyfhel/Pyfhel.pyx:1224, in Pyfhel.Pyfhel.Pyfhel.multiply_plain()
RuntimeError: result ciphertext is transparent |
This basically means that you are multiplying a ciphertext with a plaintext full of zeros. This is bad for security. If you know that the ciphertext is full of zeros, operate in cleartext directly (p1 * p2). If you don't know this and you still wish to proceed despite the security implications, then you can solve the error following #124 . Note that you can also find more info by searching for that error in the SEAL repository. Looking at your code, you are generating random vectors of size 768, but then you encrypt vectors with a total length of To avoid the problem completely, it suffices to:
#[...]
v1 = np.random.rand(l)
v2 = np.random.rand(l)
#[...]
l = 768
HE = get_CKKS_context_scalar_prod(l, sec=128, use_n_min=True)
# [...] |
scalar product between plain vector and cipher vector
I need calculate scalar product between plain vector and cipher vector:
output:
I honestly do not understand how to deal plain vector v1 at step "Encrypt each vector into one (if l <= n_slots) or several ciphertexts (l>n) ".
The text was updated successfully, but these errors were encountered: