Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
jvdsn
GitHub Repository: jvdsn/crypto-attacks
Path: blob/master/attacks/knapsack/low_density.py
2589 views
1
import os
2
import sys
3
from math import ceil
4
from math import log2
5
from math import sqrt
6
7
from sage.all import QQ
8
from sage.all import matrix
9
10
path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(os.path.abspath(__file__)))))
11
if sys.path[1] != path:
12
sys.path.insert(1, path)
13
14
from shared.lattice import shortest_vectors
15
16
17
def attack(a, s):
18
"""
19
Tries to find e_i values such that sum(e_i * a_i) = s.
20
This attack only works if the density of the a_i values is < 0.9048.
21
More information: Coster M. J. et al., "Improved low-density subset sum algorithms"
22
:param a: the a_i values
23
:param s: the s value
24
:return: the e_i values, or None if the e_i values were not found
25
"""
26
n = len(a)
27
d = n / log2(max(a))
28
N = ceil(1 / 2 * sqrt(n))
29
assert d < 0.9408, f"Density should be less than 0.9408 but was {d}."
30
31
L = matrix(QQ, n + 1, n + 1)
32
for i in range(n):
33
L[i, i] = 1
34
L[i, n] = N * a[i]
35
36
L[n] = [1 / 2] * n + [N * s]
37
38
for v in shortest_vectors(L):
39
s_ = 0
40
e = []
41
for i in range(n):
42
ei = 1 - (v[i] + 1 / 2)
43
if ei != 0 and ei != 1:
44
break
45
46
ei = int(ei)
47
s_ += ei * a[i]
48
e.append(ei)
49
50
if s_ == s:
51
return e
52
53