Skip to content

Commit 33af5db

Browse files
committed
SHA0 Collision
1 parent 652ecc8 commit 33af5db

File tree

7 files changed

+876
-21
lines changed

7 files changed

+876
-21
lines changed

DES/__init__.py

Whitespace-only changes.

DES/data_generator.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from des_variation import encrypt
2+
import random
3+
import sys
4+
5+
key = int(sys.argv[1])
6+
rounds = 8
7+
samples = 100000
8+
with open(str(key)+'_'+str(rounds)+'.txt','w') as f:
9+
for i in range(samples):
10+
msg = random.randint(0,(1<<63)-1)
11+
cipher = encrypt(msg, key, rounds = rounds)
12+
f.write("%d %d\n" % (msg,cipher))
13+

DES/des_variation.py

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,22 @@
44
import numpy as np
55

66
DES_ROUNDS = 16
7-
7+
permutation_bitlocation = [
8+
14,17,11,24, 1, 5, 3,28,
9+
15, 6,21,10,23,19,12, 4,
10+
26, 8,16, 7,27,20,13, 2,
11+
40,52,31,37,47,55,30,40,
12+
51,45,33,48,44,49,39,56,
13+
34,53,46,42,50,36,29,32
14+
]
15+
d_pemutation = [
16+
17,28,12,29,21,20, 7,16,
17+
1,15,23,26, 5,18,31,10,
18+
25, 4,11,22, 6,30,13,19,
19+
2, 8,24,14,32,27, 3, 9
20+
]
21+
s_table = [0xE,0x4,0xD,0x1,0x2,0xF,0xB,0x8,0x3,0xA,0x6,0xC,0x5,0x9,0x0,0x7]
22+
823
def rotatebitleft(b,cnt,bitlength):
924
r = ((b<<cnt) | (b>>(bitlength-cnt))) & ((1<<bitlength)-1)
1025
return r
@@ -20,19 +35,11 @@ def pbox(permutation,_in):
2035
# Key scheduler compression pbox
2136
# 56bits to 48bits then truncate to 32 bits
2237
def ks_compression_pbox(_in):
23-
permutation_bitlocation = [
24-
14,17,11,24, 1, 5, 3,28,
25-
15, 6,21,10,23,19,12, 4,
26-
26, 8,16, 7,27,20,13, 2,
27-
40,52,31,37,47,55,30,40,
28-
51,45,33,48,44,49,39,56,
29-
34,53,46,42,50,36,29,32
30-
]
3138
out_48 = pbox(permutation_bitlocation, _in)
3239
out_32 = out_48&((1<<32)-1)
3340
return out_32
3441

35-
def key_scheduler(key):
42+
def key_scheduler(key, rounds):
3643
# Assuming msb 8 bit to be parity bit
3744
# Ignoring high 8 parity bits
3845
cipherkey = key&((1<<56)-1)
@@ -42,7 +49,7 @@ def key_scheduler(key):
4249
ck_l = cipherkey>>CK_HALFSIZE
4350
ck_r = cipherkey&((1<<CK_HALFSIZE)-1)
4451
keys = []
45-
for r in range(DES_ROUNDS):
52+
for r in range(rounds):
4653
shamt = 2
4754
if r in onebitshiftround:
4855
shamt = 1
@@ -64,14 +71,6 @@ def sboxs(table, _in, splitinto):
6471
return _out
6572

6673
def des_round(data_l,data_r,rkey):
67-
d_pemutation = [
68-
17,28,12,29,21,20, 7,16,
69-
1,15,23,26, 5,18,31,10,
70-
25, 4,11,22, 6,30,13,19,
71-
2, 8,24,14,32,27, 3, 9
72-
]
73-
s_table = [0xE,0x4,0xD,0x1,0x2,0xF,0xB,0x8,0x3,0xA,0x6,0xC,0x5,0x9,0x0,0x7]
74-
7574
x_out = data_r^rkey
7675
s_out = sboxs(s_table, x_out, 8)
7776
out_p = pbox(d_pemutation, s_out)
@@ -88,8 +87,8 @@ def des(data,round_keys):
8887
cipher = (data_l<<DA_HALFSIZE) | data_r
8988
return cipher
9089

91-
def encrypt(data,key):
92-
round_keys = key_scheduler(key)
90+
def encrypt(data,key, rounds = DES_ROUNDS):
91+
round_keys = key_scheduler(key, rounds)
9392
cipher = des(data, round_keys)
9493
return cipher
9594

DES/des_variation.pyc

5.56 KB
Binary file not shown.

DES/linear_cryptanalysis.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
from des_variation import encrypt, pbox, permutation_bitlocation, d_pemutation, s_table
2+
import numpy as np
3+
import sys
4+
# bits = Bits to consider in 'number' for xor
5+
def getxor(number, bits):
6+
number = number&bits
7+
xor = bin(number).count('1')%2
8+
return xor
9+
10+
def get_linearapprox(sbox):
11+
BITSIZE = 4
12+
out = []
13+
for i in range(1<<BITSIZE):
14+
out.append(sbox[i])
15+
lineartable = []
16+
SIZE = 1<<BITSIZE
17+
for i in range(SIZE):
18+
row = []
19+
for j in range(SIZE):
20+
c = 0
21+
for sample_in,sample_out in enumerate(out):
22+
if (getxor(sample_in,i)^getxor(sample_out,j)) == 0:
23+
c+=1
24+
row.append(c)
25+
lineartable.append(row)
26+
lineartable = np.asarray(lineartable)
27+
lineartable_wb = lineartable - SIZE/2
28+
return lineartable_wb
29+
30+
def getbest_s_table_single(s_lineartable,_in):
31+
index = np.argmax(s_lineartable[_in])
32+
return (index,s_lineartable[_in][index]/16.0)
33+
34+
def getbest_s_table(s_lineartable,_in):
35+
_out = 0
36+
p1 = 1
37+
for i in range(8):
38+
_in_i = (_in>>(4*i))&0xF
39+
res = getbest_s_table_single(s_lineartable, _in_i)
40+
_out |= res[0]<<(4*i)
41+
p1 *= res[1]
42+
return _out,p1
43+
44+
def attack(fname, rounds):
45+
print "Trying to find key"
46+
s_lineartable = get_linearapprox(s_table)
47+
# init_mxbias = (2,14) # on pain_r
48+
49+
plaintextbits = 2 # Bits of plaintext to consider
50+
out_bits = 2
51+
kbits = 0
52+
53+
DA_HALFSIZE = 32
54+
cbits_l = out_bits>>DA_HALFSIZE
55+
cbits_r = out_bits&((1<<DA_HALFSIZE)-1)
56+
# Xor of plaintextbits in plaintext and out_bits in out of cround round and kbits of rkey is zero
57+
prob_l = 2.0 # only bias
58+
prob_r = 2.0 # only bias
59+
60+
for cround in range(rounds):
61+
ncbits_l = cbits_r
62+
afterstable,bias = getbest_s_table(s_lineartable,cbits_l)
63+
afterpermuation = pbox(d_pemutation, afterstable)
64+
ncbits_r = afterpermuation | cbits_l
65+
cbits_l,cbits_r = ncbits_l,ncbits_r
66+
prob_r = prob_r/2 * bias
67+
prob_r,prob_l = prob_l,prob_r
68+
print "Probablity Bias : %0.15f %0.15f" % (prob_l,prob_r)
69+
print "Probable bit flips %s %s" % (bin(cbits_l),bin(cbits_r))
70+
71+
72+
samples = []
73+
with open(fname,'r') as f:
74+
for line in f:
75+
samples.append([int(x) for x in line.split()])
76+
77+
bkey = None
78+
i = 0
79+
while i<(1<<64):
80+
good = False
81+
for sample in samples:
82+
cipher = encrypt(sample[0], i, rounds=8)
83+
if cipher == sample[1]:
84+
good = True
85+
break
86+
if good:
87+
bkey = i
88+
break
89+
i += 1
90+
if bkey is None:
91+
print "Unable to obtain key"
92+
assert False
93+
return bkey
94+
95+
def main():
96+
assert len(sys.argv)>1
97+
if sys.argv[1] == '--show-s_table':
98+
s_lineartable = get_linearapprox(s_table)
99+
print s_lineartable
100+
return
101+
fname = sys.argv[1]
102+
rounds = int(sys.argv[2])
103+
key = attack(fname, rounds)
104+
print "Key found as %d" % key
105+
106+
if __name__ == '__main__':
107+
main()
108+

0 commit comments

Comments
 (0)