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 fpylll import *
  2. from math import log
  3. from copy import copy
  4. load("../framework/proba_utils.sage")
  5. load("../framework/utils.sage")
  6. load("../framework/geometry.sage")
  7. load("../framework/DBDD_generic.sage")
  8. def cannonical_direction_only(fn):
  9. def decorated(self, *args, **kwargs):
  10. if not is_cannonical_direction(args[0]):
  11. raise InvalidHint(
  12. "Input hint vector must have a cannonical direction")
  13. return fn(self, *args, **kwargs)
  14. return decorated
  15. class DBDD_predict_diag(DBDD_generic):
  16. """
  17. This class defines all the elements defining a DBDD instance in a diagonal
  18. prediction mode
  19. """
  20. def __init__(self, B, S, mu, u=None, verbosity=1, **kwargs):
  21. """constructor that builds a DBDD instance from a lattice, mean, sigma
  22. and a target
  23. ;min_dim: Number of coordinates to find to consider the problem solved
  24. :B: Basis of the lattice
  25. :S: The Covariance matrix (Sigma) of the uSVP solution
  26. :mu: The expectation of the uSVP solution
  27. :u: The unique vector to be found (optinal, for verification purposes)
  28. :fp_type: Floating point type to use in FPLLL ("d, ld, dd, qd, mpfrX")
  29. """
  30. self.verbosity = verbosity
  31. if not is_diagonal(S):
  32. raise ValueError("given Σ not diagonal")
  33. self.S = np.array([RR(S[i, i]) for i in range(S.nrows())])
  34. self.PP = 0 * self.S # Span of the projections so far (orthonormal)
  35. # Orthogonal span of the intersection so far so far (orthonormal)
  36. self.PI = 0 * self.S
  37. self.PI[-1] = 1
  38. self.u = u
  39. self.u_original = u
  40. self._dim = S.nrows()
  41. self.projections = 0
  42. self.Bvol = kwargs.get('Bvol', logdet(B))
  43. self.save = {"save": None}
  44. self.can_constraints = S.nrows() * [1]
  45. self.can_constraints[-1] = None
  46. self.estimate_attack(silent=True)
  47. def dim(self):
  48. return self._dim
  49. def S_diag(self):
  50. return copy(self.S)
  51. def volumes(self):
  52. Bvol = self.Bvol
  53. Svol = sum([log(abs(x)) for x in (self.S + self.PP + self.PI)])
  54. dvol = Bvol - Svol / 2.
  55. return (Bvol, Svol, dvol)
  56. @cannonical_direction_only
  57. @hint_integration_wrapper(force=True)
  58. def integrate_perfect_hint(self, V, l):
  59. i, vi = cannonical_param(V)
  60. self.can_constraints[i] = None
  61. if self.PI[i]:
  62. raise RejectedHint("Redundant hint, Rejected.")
  63. if self.PP[i]:
  64. raise InvalidHint("This direction has been projected out.")
  65. assert(vi)
  66. self.PI[i] = 1
  67. self.S[i] = 0
  68. self.Bvol += log(vi)
  69. self._dim -= 1
  70. @cannonical_direction_only
  71. @hint_integration_wrapper(force=True)
  72. def integrate_modular_hint(self, V, l, k, smooth=True):
  73. i, vi = cannonical_param(V)
  74. f = (k / vi).numerator()
  75. self.can_constraints[i] = lcm(f, self.can_constraints[i])
  76. # vs = vi * self.S[i]
  77. den = vi**2 * self.S[i]
  78. if den == 0:
  79. raise RejectedHint("Redundant hint, Rejected.")
  80. if self.PP[i]:
  81. raise InvalidHint("This direction has been projected out.")
  82. if not smooth:
  83. raise NotImplementedError()
  84. self.Bvol += log(k)
  85. @cannonical_direction_only
  86. @hint_integration_wrapper(force=True)
  87. def integrate_approx_hint(self, V, l, variance, aposteriori=False):
  88. if variance < 0:
  89. raise InvalidHint("variance must be non-negative !")
  90. if variance == 0:
  91. raise InvalidHint("variance=0 : must use perfect hint !")
  92. i, vi = cannonical_param(V)
  93. vs = vi * self.S[i]
  94. if self.PP[i]:
  95. raise InvalidHint("This direction has been projected out.")
  96. if not aposteriori:
  97. d = vs * vi
  98. self.S[i] -= (1 / (variance + d) * vs) * vs
  99. else:
  100. if not vs:
  101. raise RejectedHint("0-Eigenvector of Σ forbidden,")
  102. den = vi**2
  103. self.S[i] = variance / den
  104. @hint_integration_wrapper()
  105. def integrate_approx_hint_fulldim(self, center, covariance, aposteriori=False):
  106. # Using http://www.cs.columbia.edu/~liulp/pdf/linear_normal_dist.pdf
  107. # with A = Id
  108. if not is_diagonal(covariance):
  109. raise ValueError("given covariance not diagonal")
  110. if not aposteriori:
  111. d = len(self.S) - 1
  112. for i in range(d):
  113. if covariance[i, i] == 0:
  114. raise InvalidHint("Covariances not full dimensional")
  115. for i in range(d):
  116. self.S[i] -= self.S[i]**2 / (self.S[i] + covariance[i, i])
  117. # F = (self.S + block4(covariance, zero.T, zero, vec([1]))).inverse()
  118. # F[-1,-1] = 0
  119. # self.S -= self.S * F * self.S
  120. else:
  121. raise NotImplementedError()
  122. @cannonical_direction_only
  123. @hint_integration_wrapper(force=False)
  124. def integrate_short_vector_hint(self, V):
  125. i, vi = cannonical_param(V)
  126. vi -= vi * self.PP[i]
  127. den = vi**2
  128. if den == 0:
  129. raise InvalidHint("Redundant hint,")
  130. viPI = vi * self.PI[i]
  131. if viPI**2:
  132. raise InvalidHint("Not in Span(Λ),")
  133. if vi % self.can_constraints[i]:
  134. raise InvalidHint("Not in Λ,")
  135. self.projections += 1
  136. self.Bvol -= log(RR(den)) / 2.
  137. self._dim -= 1
  138. self.PP[i] = 1
  139. self.S[i] = 0
  140. def attack(self):
  141. self.logging("Can't run the attack in simulation.", style="WARNING")
  142. return None