-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathmanytimepad.py
83 lines (60 loc) · 2.14 KB
/
manytimepad.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
82
83
from helpers import truncate, truncate3, xor
from copy import deepcopy
from random import shuffle
from scipy import stats
import numpy
def within_range(x):
return ord('A') <= x <= ord('Z') or ord('a') <= x <= ord('z')
# Given the cipher and key in bytes
# Return the deciphered message as a string
# if a byte of the key represents a null-value (0)
# display "_" as a space holder
def decode(cipher, key):
r = ''
c, k = truncate(cipher, key)
for i, j in zip(c, k):
if j == 0:
r+="_"
continue
r += chr(i ^ j)
return r
# Expects four series of bytes representing
# a partially built key and three ciphers
# Mutates the key in place given info from ciphers
def build_key(key, c1, c2, c3):
xm12, xm13, xm23 = xor(c1, c2), xor(c1, c3), xor(c2, c3)
for i in range(0, len(c1)):
if key[i] != 0:
continue
if c1[i] == c2[i] or c1[i] == c3[i] or c2[i] == c3[i]:
continue
m12, m13, m23 = xm12[i], xm13[i], xm23[i]
if within_range(m13) and within_range(m23):
key[i] = ord(" ") ^ c3[i]
elif within_range(m12) and within_range(m23):
key[i] = ord(" ") ^ c2[i]
elif within_range(m12) and within_range(m13):
key[i] = ord(" ") ^ c1[i]
# Expects a list stream ciphers in bytes
# generated by the same key, Returns the key in bytes
# Option: iterations=50
# number of keys generated for frequency analysis
# to generate final key
def find_key(streamciphers, iterations=50):
ciphers = deepcopy(streamciphers)
n = len(ciphers)
# key size of longest cipher
ksize = len(max(ciphers, key=len))
possiblekeys = []
for _ in range(iterations):
shuffle(ciphers)
k = bytearray(ksize)
for a in range(n - 2):
for b in range(a + 1, n - 1):
for c in range(b + 1, n):
x, y, z = truncate3(ciphers[a], ciphers[b], ciphers[c])
build_key(k, x, y, z)
possiblekeys.append(k)
# finalize key using frequency analysis
key_array = stats.mode(numpy.array(possiblekeys))[0][0]
return bytes(list(key_array))