50 lines
1.6 KiB
Python
50 lines
1.6 KiB
Python
import numpy
|
|
from string import *
|
|
KEYSTREAM_SIZE = 1000
|
|
|
|
CHARACTER_FREQ = {
|
|
'a': 0.0651738, 'b': 0.0124248, 'c': 0.0217339, 'd': 0.0349835, 'e': 0.1041442, 'f': 0.0197881, 'g': 0.0158610,
|
|
'h': 0.0492888, 'i': 0.0558094, 'j': 0.0009033, 'k': 0.0050529, 'l': 0.0331490, 'm': 0.0202124, 'n': 0.0564513,
|
|
'o': 0.0596302, 'p': 0.0137645, 'q': 0.0008606, 'r': 0.0497563, 's': 0.0515760, 't': 0.0729357, 'u': 0.0225134,
|
|
'v': 0.0082903, 'w': 0.0171272, 'x': 0.0013692, 'y': 0.0145984, 'z': 0.0007836, ' ': 0.1918182
|
|
} # ','
|
|
|
|
with open("./file.enc", "rb") as f:
|
|
data = f.read()
|
|
|
|
lines = []
|
|
candidates_list = []
|
|
|
|
for i in range(0,len(data), KEYSTREAM_SIZE):
|
|
lines.append(data[i:i+KEYSTREAM_SIZE])
|
|
|
|
for byte_to_guess in range(KEYSTREAM_SIZE):
|
|
counters = numpy.zeros(256,dtype=float)
|
|
for guessed_byte in range(256):
|
|
for line in lines:
|
|
if chr(line[byte_to_guess] ^ guessed_byte) in printable:
|
|
counters[guessed_byte] += CHARACTER_FREQ.get(chr(line[byte_to_guess] ^ guessed_byte).lower(),0)
|
|
|
|
max_match = max(counters)
|
|
|
|
match_list = [(counters[i],i) for i in range(256)]
|
|
ordered_match_list=sorted(match_list, reverse=True)
|
|
|
|
candidates = []
|
|
#for pair in ordered_match_list:
|
|
# if pair[0] < max_match * .95:
|
|
# break
|
|
# candidates.append(pair)
|
|
|
|
candidates_list.append(ordered_match_list)
|
|
|
|
keystream = bytearray()
|
|
for x in candidates_list:
|
|
keystream += x[0][1].to_bytes(1,byteorder='big')
|
|
|
|
from Cryptodome.Util.strxor import strxor
|
|
|
|
for line in lines:
|
|
l = min(len(keystream),len(line))
|
|
print(strxor(line[:l],keystream[:l]))
|