# -*- coding: utf-8 -*-
# Code de Swenson pour la cryptanalyse linéaire de "easy1"
from easy1 import *
import random
def grab(x, pos):
return (x >> pos) & 1
def xor(x, aa):
return reduce(lambda i,j: i.__xor__(j), [grab(x,a) for a in aa])
def linex(p,u): # comprendre l'origine de cette expression
return xor(p, [6,7,8,9,10]) ^ xor(u, [8,9])
#random.seed(12345)
numplaintexts = 1800
key = mux([0x12]*6)
e = easy1(key,3)
plaintext = []
ciphertext = []
for i in range(numplaintexts):
r = long(random.randint(0,2**36))
plaintext.append(r)
c = e.encrypt_block(r)
ciphertext.append(c)
maxdev = -1
maxk = -1
koffset = 6
ssize = 2**6 # ???
count = [0]*ssize
for k1 in range(ssize):
k = k1 << koffset
for j in range(len(plaintext)):
pt = plaintext[j]
ct = ciphertext[j]
v = apbox(ct)
v = demux(v)
v = mix(v,k)
u = mux([asbox(v[i]) for i in range(6)])
if linex(pt,u) != 0: count[k1] += 1
if abs(count[k1] - len(plaintext)/2) >= maxdev:
maxdev = abs(count[k1] - len(plaintext)/2)
maxk = k
#print k1, count[k1]
def binary(x):
if x:
y = binary(x>>1)+str(x&1)
if not y: return '0'
else: return y
else: return ''
print "guess: ",
print (binary(maxk >> koffset)).rjust(6, '0'),
print maxk >> koffset,
print " deviation: ",
print maxdev/float(len(plaintext))
print "real: "
print (binary((apbox(key) >> koffset) & 0x3f)).rjust(6, '0'),
print (apbox(key) >> koffset) & 0x3f