|
@@ -0,0 +1,1240 @@
|
|
|
+from openfhe import *
|
|
|
+from math import *
|
|
|
+
|
|
|
+def main():
|
|
|
+ SwitchCKKSToFHEW()
|
|
|
+ SwitchFHEWtoCKKS()
|
|
|
+ FloorViaSchemeSwitching()
|
|
|
+
|
|
|
+
|
|
|
+ ComparisonViaSchemeSwitching()
|
|
|
+ ArgminViaSchemeSwitching()
|
|
|
+ ArgminViaSchemeSwitchingAlt()
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def SwitchCKKSToFHEW():
|
|
|
+
|
|
|
+
|
|
|
+ print("\n-----SwitchCKKSToFHEW-----\n")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ multDepth = 3
|
|
|
+ firstModSize = 60
|
|
|
+ scaleModSize = 50
|
|
|
+ ringDim = 4096
|
|
|
+ sl = HEStd_NotSet
|
|
|
+ slBin = TOY
|
|
|
+ logQ_ccLWE = 25
|
|
|
+
|
|
|
+ slots = 16
|
|
|
+ batchSize = slots
|
|
|
+
|
|
|
+ parameters = CCParamsCKKSRNS()
|
|
|
+
|
|
|
+ parameters.SetMultiplicativeDepth(multDepth)
|
|
|
+ parameters.SetFirstModSize(firstModSize)
|
|
|
+ parameters.SetScalingModSize(scaleModSize)
|
|
|
+ parameters.SetScalingTechnique(FIXEDMANUAL)
|
|
|
+ parameters.SetSecurityLevel(sl)
|
|
|
+ parameters.SetRingDim(ringDim)
|
|
|
+ parameters.SetBatchSize(batchSize)
|
|
|
+
|
|
|
+ cc = GenCryptoContext(parameters)
|
|
|
+
|
|
|
+
|
|
|
+ cc.Enable(PKE)
|
|
|
+ cc.Enable(KEYSWITCH)
|
|
|
+ cc.Enable(LEVELEDSHE)
|
|
|
+ cc.Enable(SCHEMESWITCH)
|
|
|
+
|
|
|
+ print(f"CKKS scheme is using ring dimension {cc.GetRingDimension()},")
|
|
|
+ print(f"number of slots {slots}, and supports a multiplicative depth of {multDepth}\n")
|
|
|
+
|
|
|
+
|
|
|
+ keys = cc.KeyGen()
|
|
|
+
|
|
|
+
|
|
|
+ FHEWparams = cc.EvalCKKStoFHEWSetup(sl, slBin, False, logQ_ccLWE, False, slots)
|
|
|
+ ccLWE = FHEWparams[0]
|
|
|
+ privateKeyFHEW = FHEWparams[1]
|
|
|
+ cc.EvalCKKStoFHEWKeyGen(keys, privateKeyFHEW)
|
|
|
+
|
|
|
+ print(f"FHEW scheme is using a lattice parameter {ccLWE.Getn()},")
|
|
|
+ print(f"logQ {logQ_ccLWE},")
|
|
|
+ print(f"and modulus q {ccLWE.Getq()}\n")
|
|
|
+
|
|
|
+
|
|
|
+ modulus_CKKS_from = cc.GetModulusCKKS()
|
|
|
+
|
|
|
+ pLWE1 = ccLWE.GetMaxPlaintextSpace()
|
|
|
+ modulus_LWE = 1 << logQ_ccLWE
|
|
|
+ beta = ccLWE.GetBeta()
|
|
|
+ pLWE2 = modulus_LWE / (2*beta)
|
|
|
+
|
|
|
+ scFactor = cc.GetScalingFactorReal(0)
|
|
|
+
|
|
|
+
|
|
|
+ scale1 = modulus_CKKS_from / (scFactor * pLWE1)
|
|
|
+ scale2 = modulus_CKKS_from / (scFactor * pLWE2)
|
|
|
+
|
|
|
+
|
|
|
+ cc.EvalCKKStoFHEWPrecompute(scale1)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ x1 = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
|
|
|
+ x2 = [0.0, 271.1, 30000.0, pLWE2-2]
|
|
|
+ encodedLength1 = len(x1)
|
|
|
+ encodedLength2 = len(x2)
|
|
|
+
|
|
|
+
|
|
|
+ ptxt1 = cc.MakeCKKSPackedPlaintext(x1, 1, 0)
|
|
|
+ ptxt2 = cc.MakeCKKSPackedPlaintext(x2, 1, 0)
|
|
|
+
|
|
|
+
|
|
|
+ c1 = cc.Encrypt(keys.publicKey, ptxt1)
|
|
|
+ c2 = cc.Encrypt(keys.publicKey, ptxt2)
|
|
|
+
|
|
|
+
|
|
|
+ cTemp = cc.EvalCKKStoFHEW(c1, encodedLength1)
|
|
|
+
|
|
|
+ print(f"\n---Decrypting switched ciphertext with small precision (plaintext modulus {pLWE1}) ---\n")
|
|
|
+
|
|
|
+ x1Int = [round(x) % pLWE1 for x in x1]
|
|
|
+
|
|
|
+ ptxt1.SetLength(encodedLength1)
|
|
|
+ print(f"Input x1: {ptxt1.GetRealPackedValue()}; which rounds to {x1Int}")
|
|
|
+ print("FHEW Decryption")
|
|
|
+
|
|
|
+ for i in range(len(cTemp)):
|
|
|
+ result = ccLWE.Decrypt(privateKeyFHEW, cTemp[i], pLWE1)
|
|
|
+ print(result, end=" ")
|
|
|
+ print("\n")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ cc.EvalCKKStoFHEWPrecompute(scale2)
|
|
|
+
|
|
|
+
|
|
|
+ cTemp2 = cc.EvalCKKStoFHEW(c2, encodedLength2)
|
|
|
+
|
|
|
+ print(f"\n---Decrypting switched ciphertext with large precision (plaintext modulus {pLWE2}) ---\n")
|
|
|
+ ptxt2.SetLength(encodedLength2)
|
|
|
+ print(f"Input x2: {ptxt2.GetRealPackedValue()}")
|
|
|
+ print("FHEW Decryption")
|
|
|
+
|
|
|
+ for i in range(len(cTemp2)):
|
|
|
+ result = ccLWE.Decrypt(privateKeyFHEW, cTemp2[i], int(pLWE2))
|
|
|
+ print(result, end=" ")
|
|
|
+ print("\n")
|
|
|
+
|
|
|
+
|
|
|
+ print(f"Decomposed values for digit size of {pLWE1}:")
|
|
|
+
|
|
|
+ ccLWE.BTKeyGen(privateKeyFHEW)
|
|
|
+
|
|
|
+ for j in range(len(cTemp2)):
|
|
|
+
|
|
|
+ decomp = ccLWE.EvalDecomp(cTemp2[j])
|
|
|
+
|
|
|
+
|
|
|
+ p = ccLWE.GetMaxPlaintextSpace()
|
|
|
+ for i in range(len(decomp)):
|
|
|
+ ct = decomp[i]
|
|
|
+ if i == len(decomp) - 1:
|
|
|
+ p = int(pLWE2 / (pLWE1 ** floor(log(pLWE2)/log(pLWE1))))
|
|
|
+
|
|
|
+ resultDecomp = ccLWE.Decrypt(privateKeyFHEW, ct, p)
|
|
|
+ print(f"( {resultDecomp} * {pLWE1} ^ {i} )")
|
|
|
+ if i != len(decomp) - 1:
|
|
|
+ print("+", end=" ")
|
|
|
+ print("\n")
|
|
|
+
|
|
|
+def SwitchFHEWtoCKKS():
|
|
|
+ print("\n-----SwitchFHEWtoCKKS-----\n")
|
|
|
+ print("Output precision is only wrt the operations in CKKS after switching back.\n")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ scTech = FIXEDAUTO
|
|
|
+ multDepth = 3 + 9 + 1
|
|
|
+
|
|
|
+ if scTech == FLEXIBLEAUTOEXT:
|
|
|
+ multDepth += 1
|
|
|
+ scaleModSize = 50
|
|
|
+ ringDim = 8192
|
|
|
+ sl = HEStd_NotSet
|
|
|
+ logQ_ccLWE = 28
|
|
|
+
|
|
|
+
|
|
|
+ slots = 16
|
|
|
+ batchSize = slots
|
|
|
+
|
|
|
+ parameters = CCParamsCKKSRNS()
|
|
|
+ parameters.SetMultiplicativeDepth(multDepth)
|
|
|
+ parameters.SetScalingModSize(scaleModSize)
|
|
|
+ parameters.SetScalingTechnique(scTech)
|
|
|
+ parameters.SetSecurityLevel(sl)
|
|
|
+ parameters.SetRingDim(ringDim)
|
|
|
+ parameters.SetBatchSize(batchSize)
|
|
|
+
|
|
|
+ cc = GenCryptoContext(parameters)
|
|
|
+
|
|
|
+
|
|
|
+ cc.Enable(PKE)
|
|
|
+ cc.Enable(KEYSWITCH)
|
|
|
+ cc.Enable(LEVELEDSHE)
|
|
|
+ cc.Enable(ADVANCEDSHE)
|
|
|
+ cc.Enable(SCHEMESWITCH)
|
|
|
+
|
|
|
+ print(f"CKKS scheme is using ring dimension {cc.GetRingDimension()},\n number of slots {slots}, and suports a multiplicative depth of {multDepth}\n")
|
|
|
+
|
|
|
+
|
|
|
+ keys = cc.KeyGen()
|
|
|
+
|
|
|
+
|
|
|
+ ccLWE = BinFHEContext()
|
|
|
+ ccLWE.GenerateBinFHEContext(TOY, False, logQ_ccLWE, 0, GINX, False)
|
|
|
+
|
|
|
+
|
|
|
+ lwesk = ccLWE.KeyGen()
|
|
|
+
|
|
|
+ print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
|
|
|
+
|
|
|
+
|
|
|
+ cc.EvalFHEWtoCKKSSetup(ccLWE, slots, logQ_ccLWE)
|
|
|
+
|
|
|
+ cc.EvalFHEWtoCKKSKeyGen(keys, lwesk)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ pLWE1 = ccLWE.GetMaxPlaintextSpace()
|
|
|
+ pLWE2 = 256
|
|
|
+ modulus_LWE = 1 << logQ_ccLWE
|
|
|
+ beta = ccLWE.GetBeta()
|
|
|
+ pLWE3 = int(modulus_LWE / (2 * beta))
|
|
|
+ x1 = [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0]
|
|
|
+ x2 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
|
|
+ if len(x1) < slots:
|
|
|
+ zeros = [0] * (slots - len(x1))
|
|
|
+ x1.extend(zeros)
|
|
|
+ x2.extend(zeros)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ ctxtsLWE1 = [ccLWE.Encrypt(lwesk, x1[i]) for i in range(slots)]
|
|
|
+
|
|
|
+ ctxtsLWE2 = [ccLWE.Encrypt(lwesk, x1[i], FRESH, pLWE1) for i in range(slots)]
|
|
|
+
|
|
|
+ ctxtsLWE3 = [ccLWE.Encrypt(lwesk, x2[i], FRESH, pLWE2, modulus_LWE) for i in range(slots)]
|
|
|
+
|
|
|
+ ctxtsLWE4 = [ccLWE.Encrypt(lwesk, x2[i], FRESH, pLWE3, modulus_LWE) for i in range(slots)]
|
|
|
+
|
|
|
+
|
|
|
+ cTemp = cc.EvalFHEWtoCKKS(ctxtsLWE1, slots, slots)
|
|
|
+
|
|
|
+ print(f"\n---Input x1: {x1} encrypted under p = 4 and Q = {ctxtsLWE1[0].GetModulus()} ---")
|
|
|
+
|
|
|
+
|
|
|
+ plaintextDec = cc.Decrypt(keys.secretKey, cTemp)
|
|
|
+ plaintextDec.SetLength(slots)
|
|
|
+ print(f"Switched CKKS decryption 1: {plaintextDec}")
|
|
|
+
|
|
|
+
|
|
|
+ cTemp = cc.EvalFHEWtoCKKS(ctxtsLWE2, slots, slots, pLWE1, 0, pLWE1)
|
|
|
+
|
|
|
+ print(f"\n---Input x1: {x1} encrypted under p = {pLWE1} and Q = {ctxtsLWE2[0].GetModulus()} ---")
|
|
|
+
|
|
|
+
|
|
|
+ plaintextDec = cc.Decrypt(keys.secretKey, cTemp)
|
|
|
+ plaintextDec.SetLength(slots)
|
|
|
+ print(f"Switched CKKS decryption 2: {plaintextDec}")
|
|
|
+
|
|
|
+
|
|
|
+ cTemp = cc.EvalFHEWtoCKKS(ctxtsLWE3, slots, slots, pLWE2, 0, pLWE2)
|
|
|
+
|
|
|
+ print(f"\n---Input x2: {x2} encrypted under p = {pLWE2} and Q = {ctxtsLWE3[0].GetModulus()} ---")
|
|
|
+
|
|
|
+
|
|
|
+ plaintextDec = cc.Decrypt(keys.secretKey, cTemp)
|
|
|
+ plaintextDec.SetLength(slots)
|
|
|
+ print(f"Switched CKKS decryption 3: {plaintextDec}")
|
|
|
+
|
|
|
+
|
|
|
+ cTemp2 = cc.EvalFHEWtoCKKS(ctxtsLWE4, slots, slots, pLWE3, 0, pLWE3)
|
|
|
+
|
|
|
+ print(f"\n---Input x2: {x2} encrypted under p = {pLWE3} and Q = {ctxtsLWE4[0].GetModulus()} ---")
|
|
|
+
|
|
|
+
|
|
|
+ plaintextDec = cc.Decrypt(keys.secretKey, cTemp2)
|
|
|
+ plaintextDec.SetLength(slots)
|
|
|
+ print(f"Switched CKKS decryption 4: {plaintextDec}")
|
|
|
+
|
|
|
+def FloorViaSchemeSwitching():
|
|
|
+ print("\n-----FloorViaSchemeSwitching-----\n")
|
|
|
+ print("Output precision is only wrt the operations in CKKS after switching back.\n")
|
|
|
+
|
|
|
+
|
|
|
+ scTech = FIXEDAUTO
|
|
|
+ multDepth = 3 + 9 + 1
|
|
|
+ if scTech == FLEXIBLEAUTOEXT:
|
|
|
+ multDepth += 1
|
|
|
+
|
|
|
+ scaleModSize = 50
|
|
|
+ ringDim = 8192
|
|
|
+ sl = HEStd_NotSet
|
|
|
+ slBin = TOY
|
|
|
+ logQ_ccLWE = 23
|
|
|
+ slots = 16
|
|
|
+ batchSize = slots
|
|
|
+
|
|
|
+ parameters = CCParamsCKKSRNS()
|
|
|
+ parameters.SetMultiplicativeDepth(multDepth)
|
|
|
+ parameters.SetScalingModSize(scaleModSize)
|
|
|
+ parameters.SetScalingTechnique(scTech)
|
|
|
+ parameters.SetSecurityLevel(sl)
|
|
|
+ parameters.SetRingDim(ringDim)
|
|
|
+ parameters.SetBatchSize(batchSize)
|
|
|
+
|
|
|
+ cc = GenCryptoContext(parameters)
|
|
|
+
|
|
|
+
|
|
|
+ cc.Enable(PKE)
|
|
|
+ cc.Enable(KEYSWITCH)
|
|
|
+ cc.Enable(LEVELEDSHE)
|
|
|
+ cc.Enable(ADVANCEDSHE)
|
|
|
+ cc.Enable(SCHEMESWITCH)
|
|
|
+
|
|
|
+ print(f"CKKS scheme is using ring dimension {cc.GetRingDimension()},\n number of slots {slots}, and suports a multiplicative depth of {multDepth}\n")
|
|
|
+
|
|
|
+
|
|
|
+ keys = cc.KeyGen()
|
|
|
+
|
|
|
+
|
|
|
+ arbFunc = False
|
|
|
+ FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, False, slots)
|
|
|
+
|
|
|
+ ccLWE = FHEWparams[0]
|
|
|
+ privateKeyFHEW = FHEWparams[1]
|
|
|
+
|
|
|
+ cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW)
|
|
|
+
|
|
|
+
|
|
|
+ ccLWE.BTKeyGen(privateKeyFHEW)
|
|
|
+
|
|
|
+ print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
|
|
|
+
|
|
|
+
|
|
|
+ modulus_CKKS_from = cc.GetModulusCKKS()
|
|
|
+
|
|
|
+ modulus_LWE = 1 << logQ_ccLWE
|
|
|
+ beta = ccLWE.GetBeta()
|
|
|
+ pLWE = int(modulus_LWE / (2 * beta))
|
|
|
+
|
|
|
+ scFactor = cc.GetScalingFactorReal(0)
|
|
|
+ if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
|
|
|
+ scFactor = cc.GetScalingFactorReal(1)
|
|
|
+ scaleCF = int(modulus_CKKS_from) / (scFactor * pLWE)
|
|
|
+
|
|
|
+ cc.EvalCKKStoFHEWPrecompute(scaleCF)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ x1 = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0]
|
|
|
+
|
|
|
+
|
|
|
+ ptxt1 = cc.MakeCKKSPackedPlaintext(x1, 1, 0)
|
|
|
+
|
|
|
+
|
|
|
+ c1 = cc.Encrypt(keys.publicKey, ptxt1)
|
|
|
+
|
|
|
+
|
|
|
+ cTemp = cc.EvalCKKStoFHEW(c1)
|
|
|
+
|
|
|
+
|
|
|
+ bits = 2
|
|
|
+
|
|
|
+ cFloor = [ccLWE.EvalFloor(cTemp[i], bits) for i in range(len(cTemp))]
|
|
|
+
|
|
|
+ print(f"Input x1: {ptxt1.GetRealPackedValue()}")
|
|
|
+ print(f"Expected result for EvalFloor with {bits} bits: ", end="")
|
|
|
+ for i in range(slots):
|
|
|
+ print(int(ptxt1.GetRealPackedValue()[i]) >> bits, end=" ")
|
|
|
+
|
|
|
+ print(f"\nFHEW decryption p = {pLWE}/(1 << bits) = {pLWE // (1 << bits)}: ", end="")
|
|
|
+ for i in range(len(cFloor)):
|
|
|
+ pFloor = ccLWE.Decrypt(privateKeyFHEW, cFloor[i], pLWE // (1 << bits))
|
|
|
+ print(pFloor, end=" ")
|
|
|
+ print("\n")
|
|
|
+
|
|
|
+
|
|
|
+ cTemp2 = cc.EvalFHEWtoCKKS(cFloor, slots, slots, pLWE // (1 << bits), 0, pLWE / (1 << bits))
|
|
|
+
|
|
|
+ plaintextDec2 = cc.Decrypt(keys.secretKey, cTemp2)
|
|
|
+ plaintextDec2.SetLength(slots)
|
|
|
+ print(f"Switched floor decryption modulus_LWE mod {pLWE // (1 << bits)}: {plaintextDec2}")
|
|
|
+
|
|
|
+def FuncViaSchemeSwitching():
|
|
|
+ print("\n-----FuncViaSchemeSwitching-----\n")
|
|
|
+ print("Output precision is only wrt the operations in CKKS after switching back.\n")
|
|
|
+
|
|
|
+
|
|
|
+ multDepth = 9 + 3 + 2
|
|
|
+ scaleModSize = 50
|
|
|
+ ringDim = 2048
|
|
|
+ sl = HEStd_NotSet
|
|
|
+ slBin = TOY
|
|
|
+ logQ_ccLWE = 25
|
|
|
+ arbFunc = True
|
|
|
+ slots = 8
|
|
|
+ batchSize = slots
|
|
|
+
|
|
|
+ parameters = CCParamsCKKSRNS()
|
|
|
+ parameters.SetMultiplicativeDepth(multDepth)
|
|
|
+ parameters.SetScalingModSize(scaleModSize)
|
|
|
+ parameters.SetScalingTechnique(FIXEDMANUAL)
|
|
|
+ parameters.SetSecurityLevel(sl)
|
|
|
+ parameters.SetRingDim(ringDim)
|
|
|
+ parameters.SetBatchSize(batchSize)
|
|
|
+
|
|
|
+ cc = GenCryptoContext(parameters)
|
|
|
+
|
|
|
+
|
|
|
+ cc.Enable(PKE)
|
|
|
+ cc.Enable(KEYSWITCH)
|
|
|
+ cc.Enable(LEVELEDSHE)
|
|
|
+ cc.Enable(ADVANCEDSHE)
|
|
|
+ cc.Enable(SCHEMESWITCH)
|
|
|
+
|
|
|
+ print(f"CKKS scheme is using ring dimension {cc.GetRingDimension()},\n and number of slots {slots}\n")
|
|
|
+
|
|
|
+
|
|
|
+ keys = cc.KeyGen()
|
|
|
+
|
|
|
+
|
|
|
+ FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, False, slots)
|
|
|
+
|
|
|
+ ccLWE = FHEWparams[0]
|
|
|
+ privateKeyFHEW = FHEWparams[1]
|
|
|
+
|
|
|
+ cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW)
|
|
|
+
|
|
|
+
|
|
|
+ ccLWE.BTKeyGen(privateKeyFHEW)
|
|
|
+
|
|
|
+ print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
|
|
|
+
|
|
|
+
|
|
|
+ modulus_CKKS_from = cc.GetModulusCKKS()
|
|
|
+ pLWE = ccLWE.GetMaxPlaintextSpace()
|
|
|
+ scFactor = cc.GetScalingFactorReal(0)
|
|
|
+ if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
|
|
|
+ scFactor = cc.GetScalingFactorReal(1)
|
|
|
+ scaleCF = modulus_CKKS_from / (scFactor * pLWE)
|
|
|
+
|
|
|
+ cc.EvalCKKStoFHEWPrecompute(scaleCF)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ def fp(m, p1):
|
|
|
+ if m < p1:
|
|
|
+ return (m * m * m + 2 * m * m + 1) % p1
|
|
|
+ else:
|
|
|
+ return ((m - p1 / 2) * (m - p1 / 2) * (m - p1 / 2) + 2 * (m - p1 / 2) * (m - p1 / 2) + 1) % p1
|
|
|
+
|
|
|
+
|
|
|
+ lut = ccLWE.GenerateLUTviaFunction(fp, pLWE)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ x1 = [0.0, 0.3, 2.0, 4.0, 5.0, 6.0, 7.0, 8.0]
|
|
|
+
|
|
|
+
|
|
|
+ ptxt1 = cc.MakeCKKSPackedPlaintext(x1, 1, 0, None)
|
|
|
+
|
|
|
+
|
|
|
+ c1 = cc.Encrypt(keys.publicKey, ptxt1)
|
|
|
+
|
|
|
+
|
|
|
+ cTemp = cc.EvalCKKStoFHEW(c1)
|
|
|
+
|
|
|
+ print(f"Input x1: {ptxt1.GetRealPackedValue()}")
|
|
|
+ print("FHEW decryption: ", end="")
|
|
|
+ for i in range(len(cTemp)):
|
|
|
+ result = ccLWE.Decrypt(privateKeyFHEW, cTemp[i], pLWE)
|
|
|
+ print(result, end=" ")
|
|
|
+
|
|
|
+
|
|
|
+ cFunc = [ccLWE.EvalFunc(cTemp[i], lut) for i in range(len(cTemp))]
|
|
|
+
|
|
|
+ print("\nExpected result x^3 + 2*x + 1 mod p: ", end="")
|
|
|
+ for i in range(slots):
|
|
|
+ print(fp(int(x1[i]) % pLWE, pLWE), end=" ")
|
|
|
+
|
|
|
+ print(f"\nFHEW decryption mod {pLWE}: ", end="")
|
|
|
+ for i in range(len(cFunc)):
|
|
|
+ pFunc = ccLWE.Decrypt(privateKeyFHEW, cFunc[i], pLWE)
|
|
|
+ print(pFunc, end=" ")
|
|
|
+ print("\n")
|
|
|
+
|
|
|
+
|
|
|
+ cTemp2 = cc.EvalFHEWtoCKKS(cFunc, slots, slots, pLWE, 0, pLWE)
|
|
|
+
|
|
|
+ plaintextDec2 = cc.Decrypt(keys.secretKey, cTemp2)
|
|
|
+ plaintextDec2.SetLength(slots)
|
|
|
+ print(f"\nSwitched decryption modulus_LWE mod {pLWE}\nwoeks only for messages << p: {plaintextDec2}")
|
|
|
+
|
|
|
+
|
|
|
+ cTemp2 = cc.EvalFHEWtoCKKS(cFunc, slots, slots, 4, 0, 2)
|
|
|
+
|
|
|
+ plaintextDec2 = cc.Decrypt(keys.secretKey, cTemp2)
|
|
|
+ plaintextDec2.SetLength(slots)
|
|
|
+
|
|
|
+ print("Arcsin(switched result) * p/2pi gives the correct result if messages are < p/4: ", end="")
|
|
|
+ for i in range(slots):
|
|
|
+ x = max(min(plaintextDec2.GetRealPackedValue()[i], 1.0), -1.0)
|
|
|
+ print(asin(x) * pLWE / (2 * pi), end=" ")
|
|
|
+ print()
|
|
|
+
|
|
|
+
|
|
|
+def PolyViaSchemeSwitching():
|
|
|
+ print("\n-----PolyViaSchemeSwitching-----\n")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ scTech = FIXEDAUTO
|
|
|
+ multDepth = 3 + 9 + 1 + 2
|
|
|
+ if scTech == FLEXIBLEAUTOEXT:
|
|
|
+ multDepth += 1
|
|
|
+ scaleModSize = 50
|
|
|
+ ringDim = 2048
|
|
|
+ sl = HEStd_NotSet
|
|
|
+ slBin = TOY
|
|
|
+ logQ_ccLWE = 25
|
|
|
+
|
|
|
+ slots = 16
|
|
|
+ batchSize = slots
|
|
|
+
|
|
|
+
|
|
|
+ parameters = CCParamsCKKSRNS()
|
|
|
+ parameters.SetMultiplicativeDepth(multDepth)
|
|
|
+ parameters.SetScalingModSize(scaleModSize)
|
|
|
+ parameters.SetScalingTechnique(scTech)
|
|
|
+ parameters.SetSecurityLevel(sl)
|
|
|
+ parameters.SetRingDim(ringDim)
|
|
|
+ parameters.SetBatchSize(batchSize)
|
|
|
+
|
|
|
+ cc = GenCryptoContext(parameters)
|
|
|
+
|
|
|
+
|
|
|
+ cc.Enable(PKE)
|
|
|
+ cc.Enable(KEYSWITCH)
|
|
|
+ cc.Enable(LEVELEDSHE)
|
|
|
+ cc.Enable(ADVANCEDSHE)
|
|
|
+ cc.Enable(SCHEMESWITCH)
|
|
|
+
|
|
|
+ print(f"CKKS scheme is using ring dimension {cc.GetRingDimension()},\n number of slots {slots}, and suports a multiplicative depth of {multDepth}\n")
|
|
|
+
|
|
|
+
|
|
|
+ keys = cc.KeyGen()
|
|
|
+
|
|
|
+
|
|
|
+ FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, False, logQ_ccLWE, False, slots)
|
|
|
+
|
|
|
+ ccLWE = FHEWparams[0]
|
|
|
+ privateKeyFHEW = FHEWparams[1]
|
|
|
+
|
|
|
+
|
|
|
+ cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW, slots)
|
|
|
+
|
|
|
+ print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
|
|
|
+
|
|
|
+ pLWE1 = ccLWE.GetMaxPlaintextSpace()
|
|
|
+ modulus_LWE = 1 << logQ_ccLWE
|
|
|
+ beta = ccLWE.GetBeta()
|
|
|
+ pLWE2 = modulus_LWE // (2 * beta)
|
|
|
+
|
|
|
+ modulus_from_CKKS = cc.GetModulusCKKS()
|
|
|
+ scFactor = cc.GetScalingFactorReal(0)
|
|
|
+ if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
|
|
|
+ scFactor = cc.GetScalingFactorReal(1)
|
|
|
+ scale1 = modulus_from_CKKS // (scFactor * pLWE1)
|
|
|
+ scale2 = modulus_from_CKKS // (scFactor * pLWE2)
|
|
|
+
|
|
|
+
|
|
|
+ cc.EvalMultKeyGen(keys.secretKey)
|
|
|
+ cc.EvalRotateKeyGen(keys.secretKey, [1,2])
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ x1 = [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0]
|
|
|
+ x2 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
|
|
+
|
|
|
+ x1Rot = RotateInt(x1,1)
|
|
|
+ x1Rot = [x1Rot[i] + x1[i] for i in range(len(x1))]
|
|
|
+ x1Int = [int(round(0.25 * elem * elem) % pLWE1) for elem in x1Rot]
|
|
|
+
|
|
|
+ x2Rot = RotateInt(x2,2)
|
|
|
+ x2Rot = [x2Rot[i] + x2[i] for i in range(len(x2))]
|
|
|
+ x2Int = [int(round(0.25 * elem * elem) % pLWE2) for elem in x2Rot]
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ ctxtsLWE1 = [ccLWE.Encrypt(privateKeyFHEW, x1[i]) for i in range(slots)]
|
|
|
+
|
|
|
+ ctxtsLWE2 = [ccLWE.Encrypt(privateKeyFHEW, x2[i], FRESH, pLWE2, modulus_LWE) for i in range(slots)]
|
|
|
+
|
|
|
+
|
|
|
+ cTemp = cc.EvalFHEWtoCKKS(ctxtsLWE1, slots, slots)
|
|
|
+
|
|
|
+ print(f"\n---Input x1: {x1} encrypted under p = 4 and Q = {ctxtsLWE1[0].GetModulus()} ---\n")
|
|
|
+ print(f"round( 0.5 * (x1 + rot(x1,1) )^2 ): {x1Int}\n")
|
|
|
+
|
|
|
+
|
|
|
+ cPoly = cc.EvalAdd(cTemp, cc.EvalRotate(cTemp, 1))
|
|
|
+ cPoly = cc.EvalMult(cc.EvalMult(cPoly, cPoly), 0.25)
|
|
|
+
|
|
|
+
|
|
|
+ cc.EvalCKKStoFHEWPrecompute(scale1)
|
|
|
+
|
|
|
+
|
|
|
+ cTemp1 = cc.EvalCKKStoFHEW(cPoly, slots)
|
|
|
+
|
|
|
+ print(f"\nFHEW decryption with plaintext modulus {pLWE1}: ", end="")
|
|
|
+ for i in range(len(cTemp1)):
|
|
|
+ result = ccLWE.Decrypt(privateKeyFHEW, cTemp1[i], pLWE1)
|
|
|
+ print(result, end=" ")
|
|
|
+ print("\n")
|
|
|
+
|
|
|
+
|
|
|
+ cTemp = cc.EvalFHEWtoCKKS(ctxtsLWE2, slots, slots, pLWE2, 0, pLWE2)
|
|
|
+
|
|
|
+ print(f"\n---Input x2: {x2} encrypted under p = {pLWE2} and Q = {ctxtsLWE2[0].GetModulus()} ---\n")
|
|
|
+ print(f"round( 0.5 * (x2 + rot(x2,2) )^2 ): {x2Int}\n")
|
|
|
+
|
|
|
+
|
|
|
+ cPoly = cc.EvalAdd(cTemp, cc.EvalRotate(cTemp, 2))
|
|
|
+ cPoly = cc.EvalMult(cc.EvalMult(cPoly, cPoly), 0.25)
|
|
|
+
|
|
|
+
|
|
|
+ cc.EvalCKKStoFHEWPrecompute(scale2)
|
|
|
+
|
|
|
+
|
|
|
+ cTemp2 = cc.EvalCKKStoFHEW(cPoly, slots)
|
|
|
+
|
|
|
+ print(f"\nFHEW decryption with plaintext modulus {pLWE2}: ", end="")
|
|
|
+ for i in range(len(cTemp2)):
|
|
|
+ result = ccLWE.Decrypt(privateKeyFHEW, cTemp2[i], pLWE2)
|
|
|
+ print(result, end=" ")
|
|
|
+ print("\n")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def ComparisonViaSchemeSwitching():
|
|
|
+ print("\n-----ComparisonViaSchemeSwitching-----\n")
|
|
|
+ print("Output precision is only wrt the operations in CKKS after switching back.\n")
|
|
|
+
|
|
|
+
|
|
|
+ scTech = FIXEDAUTO
|
|
|
+ multDepth = 17
|
|
|
+ if scTech == FLEXIBLEAUTOEXT:
|
|
|
+ multDepth += 1
|
|
|
+
|
|
|
+ scaleModSize = 50
|
|
|
+ firstModSize = 60
|
|
|
+ ringDim = 8192
|
|
|
+ sl = HEStd_NotSet
|
|
|
+ slBin = TOY
|
|
|
+ logQ_ccLWE = 25
|
|
|
+ slots = 16
|
|
|
+ batchSize = slots
|
|
|
+
|
|
|
+ parameters = CCParamsCKKSRNS()
|
|
|
+ parameters.SetMultiplicativeDepth(multDepth)
|
|
|
+ parameters.SetScalingModSize(scaleModSize)
|
|
|
+ parameters.SetFirstModSize(firstModSize)
|
|
|
+ parameters.SetScalingTechnique(scTech)
|
|
|
+ parameters.SetSecurityLevel(sl)
|
|
|
+ parameters.SetRingDim(ringDim)
|
|
|
+ parameters.SetBatchSize(batchSize)
|
|
|
+ parameters.SetSecretKeyDist(UNIFORM_TERNARY)
|
|
|
+ parameters.SetKeySwitchTechnique(HYBRID)
|
|
|
+ parameters.SetNumLargeDigits(3)
|
|
|
+
|
|
|
+ cc = GenCryptoContext(parameters)
|
|
|
+
|
|
|
+
|
|
|
+ cc.Enable(PKE)
|
|
|
+ cc.Enable(KEYSWITCH)
|
|
|
+ cc.Enable(LEVELEDSHE)
|
|
|
+ cc.Enable(ADVANCEDSHE)
|
|
|
+ cc.Enable(SCHEMESWITCH)
|
|
|
+
|
|
|
+ print(f"CKKS scheme is using ring dimension {cc.GetRingDimension()},\n and number of slots {slots}\n and supports a multiplicative depth of {multDepth}\n")
|
|
|
+
|
|
|
+
|
|
|
+ keys = cc.KeyGen()
|
|
|
+
|
|
|
+
|
|
|
+ FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, False, logQ_ccLWE, False, slots)
|
|
|
+
|
|
|
+ ccLWE = FHEWparams[0]
|
|
|
+ privateKeyFHEW = FHEWparams[1]
|
|
|
+ ccLWE.BTKeyGen(privateKeyFHEW)
|
|
|
+
|
|
|
+ cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW)
|
|
|
+
|
|
|
+ print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
|
|
|
+
|
|
|
+
|
|
|
+ pLWE1 = ccLWE.GetMaxPlaintextSpace()
|
|
|
+ modulus_LWE = 1 << logQ_ccLWE
|
|
|
+ beta = ccLWE.GetBeta()
|
|
|
+ pLWE2 = modulus_LWE // (2 * beta)
|
|
|
+
|
|
|
+ scaleSignFHEW = 1
|
|
|
+ init_level = 0
|
|
|
+ if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
|
|
|
+ init_level = 1
|
|
|
+
|
|
|
+ cc.EvalCompareSwitchPrecompute(pLWE2, init_level, scaleSignFHEW)
|
|
|
+
|
|
|
+
|
|
|
+ x1 = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0]
|
|
|
+ x2 = [5.25] * slots
|
|
|
+
|
|
|
+ ptxt1 = cc.MakeCKKSPackedPlaintext(x1, 1, 0, None, slots)
|
|
|
+ ptxt2 = cc.MakeCKKSPackedPlaintext(x2, 1, 0, None, slots)
|
|
|
+
|
|
|
+ c1 = cc.Encrypt(keys.publicKey, ptxt1)
|
|
|
+ c2 = cc.Encrypt(keys.publicKey, ptxt2)
|
|
|
+
|
|
|
+ cDiff = cc.EvalSub(c1, c2)
|
|
|
+
|
|
|
+
|
|
|
+ pDiff = cc.Decrypt(keys.secretKey, cDiff)
|
|
|
+ pDiff.SetLength(slots)
|
|
|
+
|
|
|
+ print("Difference of inputs: ", end="")
|
|
|
+ for i in range(slots):
|
|
|
+ print(pDiff.GetRealPackedValue()[i], end=" ")
|
|
|
+
|
|
|
+ eps = 0.0001
|
|
|
+ print("\nExpected sign result from CKKS: ", end="")
|
|
|
+ for i in range(slots):
|
|
|
+ print(int(round(pDiff.GetRealPackedValue()[i] / eps) * eps < 0), end=" ")
|
|
|
+ print()
|
|
|
+
|
|
|
+ LWECiphertexts = cc.EvalCKKStoFHEW(cDiff, slots)
|
|
|
+
|
|
|
+ print("\nFHEW decryption with plaintext modulus ", pLWE2, ": ", end="")
|
|
|
+ for i in range(len(LWECiphertexts)):
|
|
|
+ plainLWE = ccLWE.Decrypt(privateKeyFHEW, LWECiphertexts[i], pLWE2)
|
|
|
+ print(plainLWE, end=" ")
|
|
|
+
|
|
|
+ print("\nExpected sign result in FHEW with plaintext modulus ", pLWE2, " and scale ", scaleSignFHEW, ": ", end="")
|
|
|
+ for i in range(slots):
|
|
|
+ print((int(round(pDiff.GetRealPackedValue()[i] * scaleSignFHEW)) % pLWE2 - pLWE2 / 2.0 >= 0), end=" ")
|
|
|
+ print()
|
|
|
+
|
|
|
+ print("Obtained sign result in FHEW with plaintext modulus ", pLWE2, " and scale ", scaleSignFHEW, ": ", end="")
|
|
|
+ LWESign = [None] * len(LWECiphertexts)
|
|
|
+ for i in range(len(LWECiphertexts)):
|
|
|
+ LWESign[i] = ccLWE.EvalSign(LWECiphertexts[i])
|
|
|
+ plainLWE = ccLWE.Decrypt(privateKeyFHEW, LWESign[i], 2)
|
|
|
+ print(plainLWE, end=" ")
|
|
|
+ print()
|
|
|
+
|
|
|
+
|
|
|
+ cResult = cc.EvalCompareSchemeSwitching(c1, c2, slots, 0, scaleSignFHEW)
|
|
|
+ plaintextDec3 = cc.Decrypt(keys.secretKey, cResult)
|
|
|
+ plaintextDec3.SetLength(slots)
|
|
|
+ print(f"Decrypted swutched result: {plaintextDec3}\n")
|
|
|
+
|
|
|
+
|
|
|
+def ArgminViaSchemeSwitching():
|
|
|
+ print("\n-----ArgminViaSchemeSwitching-----\n")
|
|
|
+ print("Output precision is only wrt the operations in CKKS after switching back\n")
|
|
|
+
|
|
|
+
|
|
|
+ scaleModSize = 50
|
|
|
+ firstModSize = 60
|
|
|
+ ringDim = 8192
|
|
|
+ sl = HEStd_NotSet
|
|
|
+ slBin = TOY
|
|
|
+ logQ_ccLWE = 25
|
|
|
+ arbFunc = False
|
|
|
+ oneHot = True
|
|
|
+
|
|
|
+ slots = 16
|
|
|
+ batchSize = slots
|
|
|
+ numValues = 16
|
|
|
+ scTech = FIXEDMANUAL
|
|
|
+ multDepth = 9 + 3 + 1 + int(log2(numValues))
|
|
|
+ if scTech == FLEXIBLEAUTOEXT:
|
|
|
+ multDepth += 1
|
|
|
+
|
|
|
+ parameters = CCParamsCKKSRNS()
|
|
|
+ parameters.SetMultiplicativeDepth(multDepth)
|
|
|
+ parameters.SetScalingModSize(scaleModSize)
|
|
|
+ parameters.SetFirstModSize(firstModSize)
|
|
|
+ parameters.SetScalingTechnique(scTech)
|
|
|
+ parameters.SetSecurityLevel(sl)
|
|
|
+ parameters.SetRingDim(ringDim)
|
|
|
+ parameters.SetBatchSize(batchSize)
|
|
|
+
|
|
|
+ cc = GenCryptoContext(parameters)
|
|
|
+
|
|
|
+
|
|
|
+ cc.Enable(PKE)
|
|
|
+ cc.Enable(KEYSWITCH)
|
|
|
+ cc.Enable(LEVELEDSHE)
|
|
|
+ cc.Enable(ADVANCEDSHE)
|
|
|
+ cc.Enable(SCHEMESWITCH)
|
|
|
+
|
|
|
+ print("CKKS scheme is using ring dimension ", cc.GetRingDimension())
|
|
|
+ print(", and number of slots ", slots, ", and supports a depth of ", multDepth, "\n")
|
|
|
+
|
|
|
+
|
|
|
+ keys = cc.KeyGen()
|
|
|
+
|
|
|
+
|
|
|
+ FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, False, slots)
|
|
|
+ ccLWE = FHEWparams[0]
|
|
|
+ privateKeyFHEW = FHEWparams[1]
|
|
|
+
|
|
|
+ cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW, numValues, oneHot)
|
|
|
+
|
|
|
+ print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
|
|
|
+
|
|
|
+
|
|
|
+ scaleSign = 512
|
|
|
+ modulus_LWE = 1 << logQ_ccLWE
|
|
|
+ beta = ccLWE.GetBeta()
|
|
|
+ pLWE = modulus_LWE // (2 * beta)
|
|
|
+
|
|
|
+ init_level = 0
|
|
|
+ if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
|
|
|
+ init_level = 1
|
|
|
+ cc.EvalCompareSwitchPrecompute(pLWE, init_level, scaleSign)
|
|
|
+
|
|
|
+
|
|
|
+ x1 = [-1.125, -1.12, 5.0, 6.0, -1.0, 2.0, 8.0, -1.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.25, 15.30]
|
|
|
+
|
|
|
+ print("Expected minimum value ", min(x1), " at location ", x1.index(min(x1)))
|
|
|
+ print("Expected maximum value ", max(x1), " at location ", x1.index(max(x1)))
|
|
|
+
|
|
|
+ ptxt1 = cc.MakeCKKSPackedPlaintext(x1)
|
|
|
+
|
|
|
+ c1 = cc.Encrypt(keys.publicKey, ptxt1)
|
|
|
+
|
|
|
+
|
|
|
+ result = cc.EvalMinSchemeSwitching(c1, keys.publicKey, numValues, slots, oneHot)
|
|
|
+
|
|
|
+ ptxtMin = cc.Decrypt(keys.secretKey, result[0])
|
|
|
+ ptxtMin.SetLength(1)
|
|
|
+ print("Minimum value: ", ptxtMin)
|
|
|
+
|
|
|
+ ptxtMin = cc.Decrypt(keys.secretKey, result[1])
|
|
|
+ if oneHot:
|
|
|
+ ptxtMin.SetLength(numValues)
|
|
|
+ print("Argmin indicator vector: ", ptxtMin)
|
|
|
+ else:
|
|
|
+ ptxtMin.SetLength(1)
|
|
|
+ print("Argmin: ", ptxtMin)
|
|
|
+
|
|
|
+ result = cc.EvalMaxSchemeSwitching(c1, keys.publicKey, numValues, slots, oneHot)
|
|
|
+
|
|
|
+ ptxtMax = cc.Decrypt(keys.secretKey, result[0])
|
|
|
+ ptxtMax.SetLength(1)
|
|
|
+ print("Maximum value: ", ptxtMax)
|
|
|
+
|
|
|
+ ptxtMax = cc.Decrypt(keys.secretKey, result[1])
|
|
|
+ if oneHot:
|
|
|
+ ptxtMax.SetLength(numValues)
|
|
|
+ print("Argmax indicator vector: ", ptxtMax)
|
|
|
+ else:
|
|
|
+ ptxtMax.SetLength(1)
|
|
|
+ print("Argmax: ", ptxtMax)
|
|
|
+
|
|
|
+def ArgminViaSchemeSwitchingAlt():
|
|
|
+ print("\n-----ArgminViaSchemeSwitchingAlt-----\n")
|
|
|
+ print("Output precision is only wrt the operations in CKKS after switching back\n")
|
|
|
+
|
|
|
+
|
|
|
+ scaleModSize = 50
|
|
|
+ firstModSize = 60
|
|
|
+ ringDim = 8192
|
|
|
+ sl = HEStd_NotSet
|
|
|
+ slBin = TOY
|
|
|
+ logQ_ccLWE = 25
|
|
|
+ arbFunc = False
|
|
|
+ oneHot = True
|
|
|
+ alt = True
|
|
|
+
|
|
|
+ slots = 16
|
|
|
+ batchSize = slots
|
|
|
+ numValues = 16
|
|
|
+ scTech = FIXEDAUTO
|
|
|
+ multDepth = 9 + 3 + 1 + int(log2(numValues))
|
|
|
+
|
|
|
+ parameters = CCParamsCKKSRNS()
|
|
|
+ parameters.SetMultiplicativeDepth(multDepth)
|
|
|
+ parameters.SetScalingModSize(scaleModSize)
|
|
|
+ parameters.SetFirstModSize(firstModSize)
|
|
|
+ parameters.SetScalingTechnique(scTech)
|
|
|
+ parameters.SetSecurityLevel(sl)
|
|
|
+ parameters.SetRingDim(ringDim)
|
|
|
+ parameters.SetBatchSize(batchSize)
|
|
|
+
|
|
|
+ cc = GenCryptoContext(parameters)
|
|
|
+
|
|
|
+ cc.Enable(PKE)
|
|
|
+ cc.Enable(KEYSWITCH)
|
|
|
+ cc.Enable(LEVELEDSHE)
|
|
|
+ cc.Enable(ADVANCEDSHE)
|
|
|
+ cc.Enable(SCHEMESWITCH)
|
|
|
+
|
|
|
+ print(f"CKKS scheme is using ring dimension {cc.GetRingDimension()},")
|
|
|
+ print(f"number of slots {slots}, and supports a multiplicative depth of {multDepth}\n")
|
|
|
+
|
|
|
+ keys = cc.KeyGen()
|
|
|
+
|
|
|
+
|
|
|
+ FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, False, slots)
|
|
|
+ ccLWE = FHEWparams[0]
|
|
|
+ privateKeyFHEW = FHEWparams[1]
|
|
|
+
|
|
|
+ cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW, numValues, oneHot, alt)
|
|
|
+
|
|
|
+ print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
|
|
|
+
|
|
|
+ scaleSign = 512
|
|
|
+ modulus_LWE = 1 << logQ_ccLWE
|
|
|
+ beta = ccLWE.GetBeta()
|
|
|
+ pLWE = modulus_LWE // (2 * beta)
|
|
|
+
|
|
|
+ init_level = 0
|
|
|
+ if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
|
|
|
+ init_level = 1
|
|
|
+ cc.EvalCompareSwitchPrecompute(pLWE, init_level, scaleSign)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ x1 = [-1.125, -1.12, 5.0, 6.0, -1.0, 2.0, 8.0, -1.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.25, 15.30]
|
|
|
+
|
|
|
+ print("Expected minimum value ", min(x1), " at location ", x1.index(min(x1)))
|
|
|
+ print("Expected maximum value ", max(x1), " at location ", x1.index(max(x1)))
|
|
|
+
|
|
|
+
|
|
|
+ ptxt1 = cc.MakeCKKSPackedPlaintext(x1)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ c1 = cc.Encrypt(keys.publicKey, ptxt1)
|
|
|
+
|
|
|
+
|
|
|
+ result = cc.EvalMinSchemeSwitchingAlt(c1, keys.publicKey, numValues, slots, oneHot)
|
|
|
+
|
|
|
+ ptxtMin = cc.Decrypt(keys.secretKey, result[0])
|
|
|
+ ptxtMin.SetLength(1)
|
|
|
+ print("Minimum value: ", ptxtMin)
|
|
|
+
|
|
|
+ ptxtMin = cc.Decrypt(keys.secretKey, result[1])
|
|
|
+ if oneHot:
|
|
|
+ ptxtMin.SetLength(numValues)
|
|
|
+ print("Argmin indicator vector: ", ptxtMin)
|
|
|
+ else:
|
|
|
+ ptxtMin.SetLength(1)
|
|
|
+ print("Argmin: ", ptxtMin)
|
|
|
+
|
|
|
+ result = cc.EvalMaxSchemeSwitchingAlt(c1, keys.publicKey, numValues, slots, oneHot)
|
|
|
+
|
|
|
+ ptxtMax = cc.Decrypt(keys.secretKey, result[0])
|
|
|
+ ptxtMax.SetLength(1)
|
|
|
+ print("Maximum value: ", ptxtMax)
|
|
|
+
|
|
|
+ ptxtMax = cc.Decrypt(keys.secretKey, result[1])
|
|
|
+ if oneHot:
|
|
|
+ ptxtMax.SetLength(numValues)
|
|
|
+ print("Argmax indicator vector: ", ptxtMax)
|
|
|
+ else:
|
|
|
+ ptxtMax.SetLength(1)
|
|
|
+ print("Argmax: ", ptxtMax)
|
|
|
+
|
|
|
+def ArgminViaSchemeSwitchingUnit():
|
|
|
+ print("\n-----ArgminViaSchemeSwitchingUnit-----\n")
|
|
|
+ print("Output precision is only wrt the operations in CKKS after switching back\n")
|
|
|
+
|
|
|
+
|
|
|
+ scaleModSize = 50
|
|
|
+ firstModSize = 60
|
|
|
+ ringDim = 8192
|
|
|
+ sl = HEStd_NotSet
|
|
|
+ slBin = TOY
|
|
|
+ logQ_ccLWE = 25
|
|
|
+ arbFunc = False
|
|
|
+ oneHot = True
|
|
|
+
|
|
|
+ slots = 32
|
|
|
+ batchSize = slots
|
|
|
+ numValues = 32
|
|
|
+ scTech = FLEXIBLEAUTOEXT
|
|
|
+ multDepth = 9 + 3 + 1 + int(log2(numValues))
|
|
|
+ if scTech == FLEXIBLEAUTOEXT:
|
|
|
+ multDepth += 1
|
|
|
+
|
|
|
+ parameters = CCParamsCKKSRNS()
|
|
|
+ parameters.SetMultiplicativeDepth(multDepth)
|
|
|
+ parameters.SetScalingModSize(scaleModSize)
|
|
|
+ parameters.SetFirstModSize(firstModSize)
|
|
|
+ parameters.SetScalingTechnique(scTech)
|
|
|
+ parameters.SetSecurityLevel(sl)
|
|
|
+ parameters.SetRingDim(ringDim)
|
|
|
+ parameters.SetBatchSize(batchSize)
|
|
|
+
|
|
|
+ cc = GenCryptoContext(parameters)
|
|
|
+
|
|
|
+
|
|
|
+ cc.Enable(PKE)
|
|
|
+ cc.Enable(KEYSWITCH)
|
|
|
+ cc.Enable(LEVELEDSHE)
|
|
|
+ cc.Enable(ADVANCEDSHE)
|
|
|
+ cc.Enable(SCHEMESWITCH)
|
|
|
+ cc.Enable(FHE)
|
|
|
+
|
|
|
+ print(f"CKKS scheme is using ring dimension {cc.GetRingDimension()},")
|
|
|
+ print(f"number of slots {slots}, and supports a multiplicative depth of {multDepth}\n")
|
|
|
+
|
|
|
+
|
|
|
+ keys = cc.KeyGen()
|
|
|
+
|
|
|
+
|
|
|
+ FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, False, slots)
|
|
|
+
|
|
|
+ ccLWE = FHEWparams[0]
|
|
|
+ privateKeyFHEW = FHEWparams[1]
|
|
|
+
|
|
|
+ cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW, numValues, oneHot)
|
|
|
+
|
|
|
+ print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
|
|
|
+
|
|
|
+ init_level = 0
|
|
|
+
|
|
|
+ if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
|
|
|
+ init_level = 1
|
|
|
+
|
|
|
+
|
|
|
+ cc.EvalCompareSwitchPrecompute(1, init_level, 1)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ x1 = [-1.125, -1.12, 5.0, 6.0, -1.0, 2.0, 8.0, -1.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.25, 15.30]
|
|
|
+ if len(x1) < slots:
|
|
|
+ x1.extend([0] * (slots - len(x1)))
|
|
|
+ print("Input: ", x1)
|
|
|
+
|
|
|
+ p = 1 << (firstModSize - scaleModSize - 1)
|
|
|
+ x1 = [elem / (2 * p) for elem in x1]
|
|
|
+
|
|
|
+ print("Input scaled: ", x1)
|
|
|
+ print("Expected minimum value ", min(x1), " at location ", x1.index(min(x1)))
|
|
|
+ print("Expected maximum value ", max(x1), " at location ", x1.index(max(x1)))
|
|
|
+
|
|
|
+
|
|
|
+ ptxt1 = cc.MakeCKKSPackedPlaintext(x1)
|
|
|
+
|
|
|
+
|
|
|
+ c1 = cc.Encrypt(keys.publicKey, ptxt1)
|
|
|
+
|
|
|
+
|
|
|
+ result = cc.EvalMinSchemeSwitching(c1, keys.publicKey, numValues, slots, oneHot)
|
|
|
+
|
|
|
+ ptxtMin = cc.Decrypt(keys.secretKey, result[0])
|
|
|
+ ptxtMin.SetLength(1)
|
|
|
+ print("Minimum value: ", ptxtMin)
|
|
|
+
|
|
|
+ ptxtMin = cc.Decrypt(keys.secretKey, result[1])
|
|
|
+ if oneHot:
|
|
|
+ ptxtMin.SetLength(numValues)
|
|
|
+ print("Argmin indicator vector: ", ptxtMin)
|
|
|
+ else:
|
|
|
+ ptxtMin.SetLength(1)
|
|
|
+ print("Argmin: ", ptxtMin)
|
|
|
+
|
|
|
+ result = cc.EvalMaxSchemeSwitching(c1, keys.publicKey, numValues, slots, oneHot)
|
|
|
+
|
|
|
+ ptxtMax = cc.Decrypt(keys.secretKey, result[0])
|
|
|
+ ptxtMax.SetLength(1)
|
|
|
+ print("Maximum value: ", ptxtMax)
|
|
|
+
|
|
|
+ ptxtMax = cc.Decrypt(keys.secretKey, result[1])
|
|
|
+ if oneHot:
|
|
|
+ ptxtMax.SetLength(numValues)
|
|
|
+ print("Argmax indicator vector: ", ptxtMax)
|
|
|
+ else:
|
|
|
+ ptxtMax.SetLength(1)
|
|
|
+ print("Argmax: ", ptxtMax)
|
|
|
+
|
|
|
+def ArgminViaSchemeSwitchingAltUnit():
|
|
|
+ print("\n-----ArgminViaSchemeSwitchingAltUnit-----\n")
|
|
|
+ print("Output precision is only wrt the operations in CKKS after switching back\n")
|
|
|
+
|
|
|
+
|
|
|
+ scaleModSize = 50
|
|
|
+ firstModSize = 60
|
|
|
+ ringDim = 8192
|
|
|
+ sl = HEStd_NotSet
|
|
|
+ slBin = TOY
|
|
|
+ logQ_ccLWE = 25
|
|
|
+ arbFunc = False
|
|
|
+ oneHot = True
|
|
|
+ alt = True
|
|
|
+
|
|
|
+ slots = 32
|
|
|
+ batchSize = slots
|
|
|
+ numValues = 32
|
|
|
+ scTech = FLEXIBLEAUTOEXT
|
|
|
+ multDepth = 9 + 3 + 1 + int(log2(numValues))
|
|
|
+ if scTech == FLEXIBLEAUTOEXT:
|
|
|
+ multDepth += 1
|
|
|
+
|
|
|
+ parameters = CCParamsCKKSRNS()
|
|
|
+ parameters.SetMultiplicativeDepth(multDepth)
|
|
|
+ parameters.SetScalingModSize(scaleModSize)
|
|
|
+ parameters.SetFirstModSize(firstModSize)
|
|
|
+ parameters.SetScalingTechnique(scTech)
|
|
|
+ parameters.SetSecurityLevel(sl)
|
|
|
+ parameters.SetRingDim(ringDim)
|
|
|
+ parameters.SetBatchSize(batchSize)
|
|
|
+
|
|
|
+ cc = GenCryptoContext(parameters)
|
|
|
+
|
|
|
+
|
|
|
+ cc.Enable(PKE)
|
|
|
+ cc.Enable(KEYSWITCH)
|
|
|
+ cc.Enable(LEVELEDSHE)
|
|
|
+ cc.Enable(ADVANCEDSHE)
|
|
|
+ cc.Enable(SCHEMESWITCH)
|
|
|
+ cc.Enable(FHE)
|
|
|
+
|
|
|
+ print(f"CKKS scheme is using ring dimension {cc.GetRingDimension()},")
|
|
|
+ print(f"number of slots {slots}, and supports a multiplicative depth of {multDepth}\n")
|
|
|
+
|
|
|
+
|
|
|
+ keys = cc.KeyGen()
|
|
|
+
|
|
|
+
|
|
|
+ FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, False, slots)
|
|
|
+
|
|
|
+ ccLWE = FHEWparams[0]
|
|
|
+ privateKeyFHEW = FHEWparams[1]
|
|
|
+
|
|
|
+ cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW, numValues, oneHot, alt)
|
|
|
+
|
|
|
+ print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
|
|
|
+
|
|
|
+ init_level = 0
|
|
|
+
|
|
|
+ if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
|
|
|
+ init_level = 1
|
|
|
+
|
|
|
+ cc.EvalCompareSwitchPrecompute(1, init_level, 1)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ x1 = [-1.125, -1.12, 5.0, 6.0, -1.0, 2.0, 8.0, -1.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.25, 15.30]
|
|
|
+ if len(x1) < slots:
|
|
|
+ zeros = [0] * (slots - len(x1))
|
|
|
+ x1.extend(zeros)
|
|
|
+ print("Input: ", x1)
|
|
|
+
|
|
|
+ p = 1 << (firstModSize - scaleModSize - 1)
|
|
|
+ x1 = [elem / (2 * p) for elem in x1]
|
|
|
+
|
|
|
+ print("Input scaled: ", x1)
|
|
|
+ print("Expected minimum value ", min(x1), " at location ", x1.index(min(x1)))
|
|
|
+ print("Expected maximum value ", max(x1), " at location ", x1.index(max(x1)))
|
|
|
+
|
|
|
+
|
|
|
+ ptxt1 = cc.MakeCKKSPackedPlaintext(x1)
|
|
|
+
|
|
|
+
|
|
|
+ c1 = cc.Encrypt(keys.publicKey, ptxt1)
|
|
|
+
|
|
|
+
|
|
|
+ result = cc.EvalMinSchemeSwitchingAlt(c1, keys.publicKey, numValues, slots, oneHot)
|
|
|
+
|
|
|
+ ptxtMin = cc.Decrypt(keys.secretKey, result[0])
|
|
|
+ ptxtMin.SetLength(1)
|
|
|
+ print("Minimum value: ", ptxtMin)
|
|
|
+
|
|
|
+ ptxtMin = cc.Decrypt(keys.secretKey, result[1])
|
|
|
+ if oneHot:
|
|
|
+ ptxtMin.SetLength(numValues)
|
|
|
+ print("Argmin indicator vector: ", ptxtMin)
|
|
|
+ else:
|
|
|
+ ptxtMin.SetLength(1)
|
|
|
+ print("Argmin: ", ptxtMin)
|
|
|
+
|
|
|
+ result = cc.EvalMaxSchemeSwitchingAlt(c1, keys.publicKey, numValues, slots, oneHot)
|
|
|
+
|
|
|
+ ptxtMax = cc.Decrypt(keys.secretKey, result[0])
|
|
|
+ ptxtMax.SetLength(1)
|
|
|
+ print("Maximum value: ", ptxtMax)
|
|
|
+
|
|
|
+ ptxtMax = cc.Decrypt(keys.secretKey, result[1])
|
|
|
+ if oneHot:
|
|
|
+ ptxtMax.SetLength(numValues)
|
|
|
+ print("Argmax indicator vector: ", ptxtMax)
|
|
|
+ else:
|
|
|
+ ptxtMax.SetLength(1)
|
|
|
+ print("Argmax: ", ptxtMax)
|
|
|
+
|
|
|
+
|
|
|
+def ReduceRotation(index, slots):
|
|
|
+ islots = int(slots)
|
|
|
+
|
|
|
+
|
|
|
+ if (slots & (slots - 1)) == 0:
|
|
|
+ n = int(log2(slots))
|
|
|
+ if index >= 0:
|
|
|
+ return index - ((index >> n) << n)
|
|
|
+ return index + islots + ((int(abs(index)) >> n) << n)
|
|
|
+ return (islots + index % islots) % islots
|
|
|
+
|
|
|
+def RotateInt(a, index):
|
|
|
+ slots = len(a)
|
|
|
+
|
|
|
+ result = [0]*slots
|
|
|
+
|
|
|
+ if index < 0 or index > slots:
|
|
|
+ index = ReduceRotation(index, slots)
|
|
|
+
|
|
|
+ if index == 0:
|
|
|
+ result = a.copy()
|
|
|
+ else:
|
|
|
+
|
|
|
+ for i in range(0, slots - index):
|
|
|
+ result[i] = a[i + index]
|
|
|
+ for i in range(slots - index, slots):
|
|
|
+ result[i] = a[i + index - slots]
|
|
|
+
|
|
|
+ return result
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ main()
|