-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbreak-easy1.py
108 lines (86 loc) · 3.02 KB
/
break-easy1.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
from easy1 import *
import differential_cryptanalysis_lib as dc_lib
from math import fabs, ceil
import random
# modify accordingly
def do_sbox(number):
return s[number]
# modify accordingly
def do_inv_sbox(number):
return s_inv[number]
# modify accordingly
def do_pbox(state):
return pbox(state)
def main():
NUM_P_C_PAIRS = 5000
SBOX_BITS = 6
NUM_SBOXES = 6
NUM_ROUNDS = 4
MIN_PROB = 0.008
MAX_BLOCKS_TO_BF = 4
dc_lib.initialize(NUM_P_C_PAIRS,
SBOX_BITS,
NUM_SBOXES,
NUM_ROUNDS,
MIN_PROB,
MAX_BLOCKS_TO_BF,
do_sbox,
do_inv_sbox,
do_pbox)
print('analizing cipher...')
# there is no need to do this each time
diff_characteristics = dc_lib.analize_cipher()
if len(diff_characteristics) == 0:
exit('no differential characteristic could be found!')
print('\nbest differential characteristics:')
# just for demonstration
for i in range(10):
try:
print(diff_characteristics[i])
except IndexError:
break
print('\nthe differential characteristic with the best probability will be used')
# you may choose anyone you like
diff_characteristic = diff_characteristics[0]
# this will be different with another cipher
key = random.getrandbits(18)
key = (key << 18) | key
# find which key bits we should obtain
key_to_find = 0
for block_num in diff_characteristic[2]:
k = key >> ((NUM_SBOXES - (block_num-1) - 1) * SBOX_BITS)
k = k & ((1 << SBOX_BITS) - 1)
key_to_find = (key_to_find << SBOX_BITS) | k
# generate the chosen-plaintexts and their ciphertexts
# the 'encrypt' function might be different for you
c_pairs = []
p_diff = diff_characteristic[1]
for p1 in range(NUM_P_C_PAIRS):
c1 = encrypt(key, p1, NUM_ROUNDS)
p2 = p1 ^ p_diff
c2 = encrypt(key, p2, NUM_ROUNDS)
c_pairs.append( [c1, c2] )
print('\nbreaking cipher...\n')
# obtain the hits given the ciphertexts pairs and the differential characteristic
hits = dc_lib.get_hits(c_pairs, diff_characteristic)
# get the key with the most hits
maxResult, maxIdx = 0, 0
for rIdx, result in enumerate(hits):
if result > maxResult:
maxResult = result
maxIdx = rIdx
if maxIdx == key_to_find:
print('Success!')
bits_found = '{:b}'.format(maxIdx).zfill(len(diff_characteristic[2])*SBOX_BITS)
bits_found = [bits_found[i:i+SBOX_BITS] for i in range(0, len(bits_found), SBOX_BITS)]
blocks_num = list(diff_characteristic[2].keys())
zipped = list(zip(blocks_num, bits_found))
print('\nobtained key bits:')
for num_block, bits in zipped:
print('block {:d}: {}'.format(num_block, bits))
else:
print('Failure')
if __name__ == "__main__":
main()