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 символов.

  1. from math import factorial as fac
  2. from math import ceil, erf, sqrt, exp
  3. def build_Gaussian_law(sigma, t):
  4. D = {}
  5. for i in range(0, t + 1):
  6. D[i] = exp(-i ** 2 / (2 * sigma ** 2))
  7. D[-i] = D[i]
  8. normalization = sum([D[i] for i in D])
  9. for i in D:
  10. D[i] = D[i] / normalization
  11. assert abs(sum([D[i] for i in range(-t, t + 1)]) - 1.) <= 10 ** -10
  12. return D
  13. def gaussian_center_weight(sigma, t):
  14. """ Weight of the gaussian of std deviation s, on the interval [-t, t]
  15. :param x: (float)
  16. :param y: (float)
  17. :returns: erf( t / (sigma*sqrt 2) )
  18. """
  19. return erf(t / (sigma * sqrt(2.)))
  20. def binomial(x, y):
  21. """ Binomial coefficient
  22. :param x: (integer)
  23. :param y: (integer)
  24. :returns: y choose x
  25. """
  26. try:
  27. binom = fac(x) // fac(y) // fac(x - y)
  28. except ValueError:
  29. binom = 0
  30. return binom
  31. def centered_binomial_pdf(k, x):
  32. """ Probability density function of the centered binomial law of param k at x
  33. :param k: (integer)
  34. :param x: (integer)
  35. :returns: p_k(x)
  36. """
  37. return binomial(2 * k, x + k) / 2.**(2 * k)
  38. def build_centered_binomial_law(k):
  39. """ Construct the binomial law as a dictionnary
  40. :param k: (integer)
  41. :param x: (integer)
  42. :returns: A dictionnary {x:p_k(x) for x in {-k..k}}
  43. """
  44. D = {}
  45. for i in range(-k, k + 1):
  46. D[i] = centered_binomial_pdf(k, i)
  47. return D
  48. def build_uniform_law(p):
  49. """ Construct the binomial law as a dictionnary
  50. :param k: (integer)
  51. :param x: (integer)
  52. :returns: A dictionnary {x:p_k(x) for x in {-k..k}}
  53. """
  54. D = {}
  55. for i in range(p):
  56. D[i - p / 2] = 1. / p
  57. return D
  58. def mod_switch(x, q, rq):
  59. """ Modulus switching (rounding to a different discretization of the Torus)
  60. :param x: value to round (integer)
  61. :param q: input modulus (integer)
  62. :param rq: output modulus (integer)
  63. """
  64. return int(round(1. * rq * x / q) % rq)
  65. def mod_centered(x, q):
  66. """ reduction mod q, centered (ie represented in -q/2 .. q/2)
  67. :param x: value to round (integer)
  68. :param q: input modulus (integer)
  69. """
  70. a = x % q
  71. if a < q / 2:
  72. return a
  73. return a - q
  74. def build_mod_switching_error_law(q, rq):
  75. """ Construct Error law: law of the difference
  76. introduced by switching from and back a uniform value mod q
  77. :param q: original modulus (integer)
  78. :param rq: intermediate modulus (integer)
  79. """
  80. D = {}
  81. V = {}
  82. for x in range(q):
  83. y = mod_switch(x, q, rq)
  84. z = mod_switch(y, rq, q)
  85. d = mod_centered(x - z, q)
  86. D[d] = D.get(d, 0) + 1. / q
  87. V[y] = V.get(y, 0) + 1
  88. return D
  89. def law_convolution(A, B):
  90. """ Construct the convolution of two laws
  91. (sum of independent variables from two input laws)
  92. :param A: first input law (dictionnary)
  93. :param B: second input law (dictionnary)
  94. """
  95. C = {}
  96. for a in A:
  97. for b in B:
  98. c = a + b
  99. C[c] = C.get(c, 0) + A[a] * B[b]
  100. return C
  101. def law_product(A, B):
  102. """ Construct the law of the product of independent
  103. variables from two input laws
  104. :param A: first input law (dictionnary)
  105. :param B: second input law (dictionnary)
  106. """
  107. C = {}
  108. for a in A:
  109. for b in B:
  110. c = a * b
  111. C[c] = C.get(c, 0) + A[a] * B[b]
  112. return C
  113. def clean_dist(A):
  114. """ Clean a distribution to accelerate furthe
  115. computation (drop element of the support
  116. with proba less than 2^-300)
  117. :param A: input law (dictionnary)
  118. """
  119. B = {}
  120. for (x, y) in A.items():
  121. if y > 2**(-300):
  122. B[x] = y
  123. return B
  124. def renormalize_dist(A):
  125. B = {}
  126. summ = sum([y for (x,y) in A.items()])
  127. for x in A:
  128. B[x] = A[x] / summ
  129. return B
  130. def iter_law_convolution(A, i):
  131. """ compute the -ith forld convolution of a distribution (using double-and-add)
  132. :param A: first input law (dictionnary)
  133. :param i: (integer)
  134. """
  135. D = {0: 1.0}
  136. i_bin = bin(i)[2:] # binary representation of n
  137. for ch in i_bin:
  138. D = law_convolution(D, D)
  139. D = clean_dist(D)
  140. if ch == '1':
  141. D = law_convolution(D, A)
  142. D = clean_dist(D)
  143. return D
  144. def tail_probability(D, t):
  145. '''
  146. Probability that an drawn from D is strictly greater than t in absolute value
  147. :param D: Law (Dictionnary)
  148. :param t: tail parameter (integer)
  149. '''
  150. s = 0
  151. ma = max(D.keys())
  152. if t >= ma:
  153. return 0
  154. # Summing in reverse for better numerical precision (assuming tails are decreasing)
  155. for i in reversed(range(int(ceil(t)), ma)):
  156. s += D.get(i, 0) + D.get(-i, 0)
  157. return s