Fork of the official github repository of the framework Leaky-LWE-Estimator, a Sage Toolkit to attack and estimate the hardness of LWE with Side Information. https://github.com/lducas/leaky-LWE-Estimator
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

exploiting_SCA_attack.sage 7.8KB

  1. #!/usr/bin/sage -python
  2. # -*- coding: latin-1 -*-
  3. load("../framework/instance_gen.sage")
  4. for params in ['CCS1']:
  5. logging("Set of parameters: " + params)
  6. if params == 'challenge':
  7. n = 296
  8. m = n + 4
  9. q = 2**12
  10. frodo_distribution = []
  11. D_s = {-1: RR(1 / 3), 0: RR(1 / 3), 1: RR(1 / 3)}
  12. elif params == 'NIST1':
  13. # NIST1 FRODOKEM-640
  14. n = 640
  15. m = 640
  16. q = 2**15
  17. frodo_distribution = [9288, 8720, 7216, 5264, 3384,
  18. 1918, 958, 422, 164, 56, 17, 4, 1]
  19. D_s = get_distribution_from_table(frodo_distribution, 2 ** 16)
  20. load("Frodo_Single_data/simulation_distribution_NIST1.sage")
  21. load("Frodo_Single_data/aposteriori_distribution_NIST1.sage")
  22. elif params == 'NIST2':
  23. # NIST2 FRODOKEM-976
  24. n = 976
  25. m = 976
  26. q = 65536
  27. frodo_distribution = [11278, 10277, 7774, 4882, 2545, 1101,
  28. 396, 118, 29, 6, 1]
  29. D_s = get_distribution_from_table(frodo_distribution, 2 ** 16)
  30. load("Frodo_Single_data/simulation_distribution_NIST2.sage")
  31. load("Frodo_Single_data/aposteriori_distribution_NIST2.sage")
  32. elif params == 'CCS1':
  33. n = 352
  34. m = 352
  35. q = 2 ** 11
  36. frodo_distribution = [22528, 15616, 5120, 768]
  37. D_s = get_distribution_from_table(frodo_distribution, 2 ** 16)
  38. load("Frodo_Single_data/simulation_distribution_CCS1.sage")
  39. load("Frodo_Single_data/aposteriori_distribution_CCS1.sage")
  40. elif params == 'CCS2':
  41. n = 592
  42. m = 592
  43. q = 2 ** 12
  44. frodo_distribution = [25120, 15840, 3968, 384, 16]
  45. D_s = get_distribution_from_table(frodo_distribution, 2 ** 16)
  46. load("Frodo_Single_data/simulation_distribution_CCS2.sage")
  47. load("Frodo_Single_data/aposteriori_distribution_CCS2.sage")
  48. elif params == 'CCS3':
  49. n = 752
  50. m = 752
  51. q = 2 ** 15
  52. frodo_distribution = [19296, 14704, 6496, 1664, 240, 16]
  53. D_s = get_distribution_from_table(frodo_distribution, 2 ** 16)
  54. load("Frodo_Single_data/simulation_distribution_CCS3.sage")
  55. load("Frodo_Single_data/aposteriori_distribution_CCS3.sage")
  56. elif params == 'CCS4':
  57. n = 864
  58. m = 864
  59. q = 2 ** 15
  60. frodo_distribution = [19304, 14700, 6490, 1659, 245, 21, 1]
  61. D_s = get_distribution_from_table(frodo_distribution, 2 ** 16)
  62. load("Frodo_Single_data/simulation_distribution_CCS4.sage")
  63. load("Frodo_Single_data/aposteriori_distribution_CCS4.sage")
  64. """ Original Security """
  65. A, b, dbdd = initialize_from_LWE_instance(DBDD_predict_diag,
  66. n,
  67. q, m, D_s, D_s, verbosity=0)
  68. dbdd.integrate_q_vectors(q, indices=range(n, n + m))
  69. (beta, _) = dbdd.estimate_attack()
  70. logging("Attack without hints: %3.2f bikz" % beta, style="HEADER")
  71. """ Refined Side channel attack """
  72. def simu_measured(secret):
  73. """
  74. This fonction simulates the information gained by
  75. Bos et al attack. The simulation is based on a
  76. distribution obtained with a large amount of data
  77. for Bos et al suite (in Matlab).
  78. :secret: an integer being the secret value
  79. :measurement: an integer that represents the output
  80. of Bos et al attack.
  81. """
  82. secret = recenter(secret)
  83. distrib_of_guesses = renormalize_dist(Dguess[secret])
  84. measurement = draw_from_distribution(distrib_of_guesses)
  85. return measurement
  86. def ordered_indices(sorted_guesses, measured):
  87. """
  88. Necessary for the bruteforce attack, this function
  89. sorts the indices of the coefficients
  90. of the secret with decreasing likelihood.
  91. :sorted_guess: the best guesses in order of likelihood
  92. :measured: the measurement for each coefficient
  93. :orderered_coefficients: the indices of the coefficients
  94. ordered according to Probability[secret[i] = measured[i]]
  95. """
  96. orderered_coefficients = []
  97. for x in sorted_guesses:
  98. for i in range(len(measured)):
  99. meas = measured[i]
  100. if meas == x:
  101. orderered_coefficients += [i]
  102. return orderered_coefficients
  103. def estimate_SCA(report_every, dbdd, measured, max_guesses):
  104. """
  105. This function evaluates the security loss after Bos et al attack
  106. :report_every: an integer that give the frequency of
  107. logging (None for no logging)
  108. :dbdd: instance of the class DBDD
  109. :measured: table representing the (simulated) information
  110. given by Bos et al attack
  111. :max_guesses: integer for upperbounding the number of guesses
  112. """
  113. Id = identity_matrix(n + m)
  114. for i in range(n):
  115. v = vec(Id[i])
  116. if report_every is not None and ((i % report_every == 0) or (i == n - 1)) :
  117. verbose = 2
  118. else:
  119. verbose = 0
  120. dbdd.verbosity = verbose
  121. if verbose == 2:
  122. logging("[...%d]" % report_every, newline=False)
  123. if variance_aposteriori[measured[i]] is not None and variance_aposteriori[measured[i]] != 0:
  124. dbdd.integrate_approx_hint(v,
  125. center_aposteriori[measured[i]],
  126. variance_aposteriori[measured[i]],
  127. aposteriori=True, estimate=verbose)
  128. elif variance_aposteriori[measured[i]] is not None and variance_aposteriori[measured[i]] == 0 :
  129. dbdd.integrate_perfect_hint(v, center_aposteriori[measured[i]],
  130. estimate=verbose)
  131. if report_every is not None:
  132. dbdd.integrate_q_vectors(q, indices=range(n, n + m), report_every=report_every)
  133. else:
  134. dbdd.integrate_q_vectors(q, indices=range(n, n + m))
  135. (beta, _) = dbdd.estimate_attack()
  136. if report_every is not None:
  137. logging(" Hybrid attack estimation ", style="HEADER")
  138. sorted_guesses = sorted(proba_best_guess_correct.items(),
  139. key=lambda kv: - kv[1])
  140. sorted_guesses = [sorted_guesses[i][0] for i in range(len(sorted_guesses))
  141. if sorted_guesses[i][1] != 1.]
  142. proba_success = 1.
  143. dbdd.verbosity = 0
  144. guesses = 0
  145. j = 0
  146. for i in ordered_indices(sorted_guesses, measured):
  147. j += 1
  148. if (guesses <= max_guesses):
  149. v = vec(Id[i])
  150. if dbdd.integrate_perfect_hint(v, _):
  151. guesses += 1
  152. proba_success *= proba_best_guess_correct[measured[i]]
  153. if report_every is not None and (j % report_every == 0):
  154. logging("[...%d]" % report_every, newline=False)
  155. dbdd.integrate_q_vectors(q, indices=range(n, n + m))
  156. logging("dim=%3d \t delta=%.6f \t beta=%3.2f \t guesses=%4d" %
  157. (dbdd.dim(), dbdd.delta, dbdd.beta, guesses),
  158. style="VALUE", newline=False)
  159. logging("Proba success = %s" % proba_success, style="VALUE",
  160. newline=True)
  161. dbdd.attack()
  162. return beta, dbdd.beta, proba_success
  163. """ Example
  164. Uncomment the following to get the detailed computation
  165. """
  166. A, b, dbdd = initialize_from_LWE_instance(DBDD,
  167. n,
  168. q, m, D_s, D_s, verbosity=2)
  169. measured = [simu_measured(dbdd.u[0, i]) for i in range(n)]
  170. estimate_SCA(50, dbdd, measured, 200)