Files
LiberPrayground/LP/KeySearch.py
2021-02-20 12:59:29 +01:00

114 lines
3.5 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
from utils import affine_decrypt
#########################################
# GuessVigenere : Shift values around with a given keylength
#########################################
class GuessVigenere(object):
def __init__(self, nums):
self.nums = nums
def guess(self, keylength, score_fn): # minimize score_fn
found = []
avg_score = 0
for offset in range(keylength):
bi = -1
bs = 9999999
for i in range(29):
shifted = [(x - i) % 29 for x in self.nums[offset::keylength]]
score = score_fn(shifted)
if score < bs:
bs = score
bi = i
avg_score += bs
found.append(bi)
return avg_score / keylength, found
#########################################
# GuessAffine : Find greatest common affine key
#########################################
class GuessAffine(object):
def __init__(self, nums):
self.nums = nums
def guess(self, keylength, score_fn): # minimize score_fn
found = []
avg_score = 0
for offset in range(keylength):
candidate = (None, None)
best = 9999999
for s in range(29):
for t in range(29):
shifted = [affine_decrypt(x, (s, t))
for x in self.nums[offset::keylength]]
score = score_fn(shifted)
if score < best:
best = score
candidate = (s, t)
avg_score += best
found.append(candidate)
return avg_score / keylength, found
#########################################
# GuessPattern : Find a key that is rotated ABC BCA CAB, or ABC CAB BCA
#########################################
class GuessPattern(object):
@staticmethod
def groups(nums, keylen, generator, offset=0):
for _ in range(offset):
next(generator)
ret = [[] for _ in range(keylen)]
for idx, value in zip(generator, nums):
ret[idx].append(value)
return ret
def shift_pattern(kl, shift=1): # shift by (more than) one, 012201120
for i in range(10000):
p = (i * shift) % kl
yield from range(p, kl)
yield from range(p)
def mirror_pattern_a(kl): # mirrored, 012210012210
for i in range(10000):
yield from range(kl)
yield from range(kl - 1, -1, -1)
def mirror_pattern_b(kl): # mirrored, 012101210
for i in range(10000):
yield from range(kl)
yield from range(kl - 2, 0, -1)
@staticmethod
def zip(nums, key, keylen, shift=1, offset=0):
gen = GuessPattern.shift_pattern(keylen, shift)
for _ in range(offset):
next(gen)
return [(n - key[k]) % 29 for n, k in zip(nums, gen)]
@staticmethod
def guess(parts, score_fn): # minimize score_fn
found = []
avg_score = 0
for nums in parts:
best = 9999999
candidate = 0
for i in range(29):
score = score_fn([(x - i) % 29 for x in nums])
if score < best:
best = score
candidate = i
avg_score += best
found.append(candidate)
return avg_score / len(parts), found
if __name__ == '__main__':
print(list(GuessPattern.shift_pattern(4, 3))[:20])