iterative-ckks-bootstrapping.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. from openfhe import *
  2. import math
  3. import random
  4. def main():
  5. iterative_bootstrap_example()
  6. def calculate_approximation_error(result,expected_result):
  7. if len(result) != len(expected_result):
  8. raise Exception("Cannot compare vectors with different numbers of elements")
  9. # using the infinity norm
  10. # error is abs of the difference of real parts
  11. max_error = max([abs(el1.real - el2.real) for (el1, el2) in zip(result, expected_result)])
  12. # return absolute value of log base2 of the error
  13. return abs(math.log(max_error,2))
  14. def iterative_bootstrap_example():
  15. # Step 1: Set CryptoContext
  16. parameters = CCParamsCKKSRNS()
  17. secret_key_dist = SecretKeyDist.UNIFORM_TERNARY
  18. parameters.SetSecretKeyDist(secret_key_dist)
  19. parameters.SetSecurityLevel(SecurityLevel.HEStd_NotSet)
  20. parameters.SetRingDim(1 << 12)
  21. if get_native_int()==128:
  22. rescale_tech = ScalingTechnique.FIXEDAUTO
  23. dcrt_bits = 78
  24. first_mod = 89
  25. else:
  26. rescale_tech = ScalingTechnique.FLEXIBLEAUTO
  27. dcrt_bits = 59
  28. first_mod = 60
  29. parameters.SetScalingModSize(dcrt_bits)
  30. parameters.SetScalingTechnique(rescale_tech)
  31. parameters.SetFirstModSize(first_mod)
  32. # Here, we specify the number of iterations to run bootstrapping.
  33. # Note that we currently only support 1 or 2 iterations.
  34. # Two iterations should give us approximately double the precision of one iteration.
  35. num_iterations = 2
  36. level_budget = [3, 3]
  37. bsgs_dim = [0,0]
  38. levels_available_after_bootstrap = 10
  39. depth = levels_available_after_bootstrap = 10 + FHECKKSRNS.GetBootstrapDepth(level_budget, secret_key_dist) + (num_iterations - 1)
  40. parameters.SetMultiplicativeDepth(depth)
  41. # Generate crypto context
  42. cryptocontext = GenCryptoContext(parameters)
  43. # Enable features that you wish to use. Note, we must enable FHE to use bootstrapping.
  44. cryptocontext.Enable(PKESchemeFeature.PKE)
  45. cryptocontext.Enable(PKESchemeFeature.KEYSWITCH)
  46. cryptocontext.Enable(PKESchemeFeature.LEVELEDSHE)
  47. cryptocontext.Enable(PKESchemeFeature.ADVANCEDSHE)
  48. cryptocontext.Enable(PKESchemeFeature.FHE)
  49. ring_dim = cryptocontext.GetRingDimension()
  50. print(f"CKKS is using ring dimension {ring_dim}\n\n")
  51. # Step 2: Precomputations for bootstrapping
  52. # We use a sparse packing
  53. num_slots = 8
  54. cryptocontext.EvalBootstrapSetup(level_budget, bsgs_dim, num_slots)
  55. # Step 3: Key generation
  56. key_pair = cryptocontext.KeyGen()
  57. cryptocontext.EvalMultKeyGen(key_pair.secretKey)
  58. # Generate bootstrapping keys.
  59. cryptocontext.EvalBootstrapKeyGen(key_pair.secretKey, num_slots)
  60. # Step 4: Encoding and encryption of inputs
  61. # Generate random input
  62. x = [random.uniform(0, 1) for i in range(num_slots)]
  63. """ Encoding as plaintexts
  64. We specify the number of slots as num_slots to achieve a performance improvement.
  65. We use the other default values of depth 1, levels 0, and no params.
  66. Alternatively, you can also set batch size as a parameter in the CryptoContext as follows:
  67. parameters.SetBatchSize(num_slots);
  68. Here, we assume all ciphertexts in the cryptoContext will have num_slots slots.
  69. We start with a depleted ciphertext that has used up all of its levels."""
  70. ptxt = cryptocontext.MakeCKKSPackedPlaintext(x, 1, depth -1,None,num_slots)
  71. ptxt.SetLength(num_slots)
  72. print(f"Input: {ptxt}")
  73. # Encrypt the encoded vectors
  74. ciph = cryptocontext.Encrypt(key_pair.publicKey, ptxt)
  75. # Step 5: Measure the precision of a single bootstrapping operation.
  76. ciphertext_after = cryptocontext.EvalBootstrap(ciph)
  77. result = cryptocontext.Decrypt(ciphertext_after,key_pair.secretKey)
  78. result.SetLength(num_slots)
  79. precision = calculate_approximation_error(result.GetCKKSPackedValue(),ptxt.GetCKKSPackedValue())
  80. print(f"Bootstrapping precision after 1 iteration: {precision} bits\n")
  81. # Set the precision equal to empirically measured value after many test runs.
  82. precision = 17
  83. print(f"Precision input to algorithm: {precision}\n")
  84. # Step 6: Run bootstrapping with multiple iterations
  85. ciphertext_two_iterations = cryptocontext.EvalBootstrap(ciph,num_iterations,precision)
  86. result_two_iterations = cryptocontext.Decrypt(ciphertext_two_iterations,key_pair.secretKey)
  87. result_two_iterations.SetLength(num_slots)
  88. actual_result = result_two_iterations.GetCKKSPackedValue()
  89. print(f"Output after two interations of bootstrapping: {actual_result}\n")
  90. precision_multiple_iterations = calculate_approximation_error(actual_result,ptxt.GetCKKSPackedValue())
  91. print(f"Bootstrapping precision after 2 iterations: {precision_multiple_iterations} bits\n")
  92. print(f"Number of levels remaining after 2 bootstrappings: {depth - ciphertext_two_iterations.GetLevel()}\n")
  93. if __name__ == "__main__":
  94. main()