-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathknapsack_cipher.py
81 lines (72 loc) · 2.31 KB
/
knapsack_cipher.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import sys
sys.path.append("../..")
import os
import random
from MyCrypto.algorithms.exgcd import gcd, inverse
class Knapsack:
def __init__(self):
self._data = Knapsack._genKey()
def run(self, data, method='encrypt'):
if method == 'encrypt':
return Knapsack._encrypt(data, self._data['b'])
elif method == 'decrypt':
return Knapsack._decrypt(data, self._data['w'], self._data['invr'], self._data['q'])
def from_file(self, fn, method='encrypt'):
if method == 'encrypt':
insize, outsize = 8, 16
elif method == 'decrypt':
insize, outsize = 16, 8
fdir, out_fn = os.path.split(fn)
out_fn = 'output_' + out_fn
out_fn = os.path.join(fdir, out_fn)
output = open(out_fn, 'wb')
with open(fn, 'rb') as fin:
while True:
byte = fin.read(insize)
if not byte:
break
data = int.from_bytes(byte, byteorder='little')
output.write(self.run(data, method).to_bytes(outsize, byteorder='little'))
output.close()
@staticmethod
def _encrypt(m, b):
c = 0
for k in b[::-1]:
c += k * (m&1)
m >>= 1
assert m == 0
return c
@staticmethod
def _decrypt(c, w, invr, q):
c = (c*invr)%q
m = 0
for i, k in enumerate(w[::-1]):
if c >= k:
m ^= 1<<i
c -= k
assert c == 0
return m
@staticmethod
def _genKey(n=64):
s = 0
klist = list()
for i in range(n):
k = random.randint(s+2, 2*s+2)
s += k
klist.append(k)
q = random.randint(s+2, 2*s+2)*2+1
r = q
while gcd(r, q) != 1:
r = random.randint(2, q-1)
invr = inverse(r, q)
b = [(k*r)%q for k in klist]
return {'w': klist, 'b': b, 'q': q, 'r': r, 'invr': invr}
if __name__ == '__main__':
ks = Knapsack()
data = 0b10110001100111001110
code = ks.run(data, method='encrypt')
print(hex(data))
print(hex(code))
print(hex(ks.run(code, method='decrypt')))
ks.from_file('../testdata/text.txt', method='encrypt')
ks.from_file('../testdata/output_text.txt', method='decrypt')