Des in python
Sun, Jun 14, 2020
4-minute read
A python program for DES
#!/usr/bin/env python3
# coding: utf-8
# Final Program
# Name: Somesh Bhandarkar
BookInitPermOrder = [58,50,42,34,26,18,10,2,
60,52,44,36,28,20,12,4,
62,54,46,38,30,22,14,6,
64,56,48,40,32,24,16,8,
57,49,41,33,25,17,9,1,
59,51,43,35,27,19,11,3,
61,53,45,37,29,21,13,5,
63,55,47,39,31,23,15,7]
BookInvInitPermOrder = [40,8,48,16,56,24,64,32,
39,7,47,15,55,23,63,31,
38,6,46,14,54,22,62,30,
37,5,45,13,53,21,61,29,
36,4,44,12,52,20,60,28,
35,3,43,11,51,19,59,27,
34,2,42,10,50,18,58,26,
33,1,41,9,49,17,57,25]
PC1 = [57,49,41,33,25,17,9,1,58,50,42,34,26,18,10,2,59,51,43,35,27,19,11,3,60,52,44,36,63,55,47,39,31,23,15,
7,62,54,46,38,30,22,14,6,61,53,45,37,29,21,13,5,28,20,12,4]
PC2 = [14,17,11,24,1,5,3,28,15,6,21,10,23,19,12,4,26,8,16,7,27,20,13,2, 41,52,31,37,47,55,30,40,51,45,33,48,
44,49,39,56,34,53,46,42,50,36,29,32]
E_TABLE = [32,1,2,3,4,5,4,5,6,7,8,9,8,9,10,11,12,13,12,13,14,15,16,17,
16,17,18,19,20,21,20,21,22,23,24,25,24,25,26,27,28,29,28,29,30,31,32,1]
P = [16,7,20,21,29,12,28,17,1,15,23,26,5,18,31,10,2,8,24,14,32,27,3,9,19,13,30,6,22,11,4,25]
def byteseq2binstr(byteseq):
bitslist2 = [bin(int(b))[2:].zfill(8) for b in byteseq]
allbitsstr = ''.join(bitslist2)
return allbitsstr
def after_PC1(input_key_64bit, PC1):
key_56bit = []
key_56bit += [input_key_64bit[index-1] for index in PC1]
key_56bit = ''.join(key_56bit)
return key_56bit
#key_56 = after_PC1(demo_key, PC1)
def two_halves(key_56bit):
left_half, right_half = key_56bit[:28], key_56bit[28:]
return left_half, right_half
def des_keygen(C_inp, D_inp, roundindex):
# Implement Figure 6
C_shifted = C_inp[roundindex:] + C_inp[:roundindex]
D_shifted = D_inp[roundindex:] + D_inp[:roundindex]
key_48bit = []
key_56bit_local = C_shifted + D_shifted
key_48bit += [key_56bit_local[index-1] for index in PC2]
key48 = ''.join(key_48bit)
C_out = C_shifted
D_out = D_shifted
#print(list(key48))
return key48, C_out, D_out
def des_key_generation(input_key_64bit):
subkey = []
permuted_choice_1 = after_PC1(input_key_64bit, PC1)
C_inp, D_inp = two_halves(permuted_choice_1)
left_shift_index = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
for round in range(0,16):
round_key, C_out, D_out = des_keygen(C_inp, D_inp, left_shift_index[round])
C_inp = C_out
D_inp = D_out
subkey.append(round_key)
return subkey
def Permutation(bitstr, permorderlist):
permedbitstr = None
InitPermOrder = [x-1 for x in permorderlist]
inputbitslistperm = [bitstr[b] for b in InitPermOrder]
permedbitstr = ''.join(inputbitslistperm)
return permedbitstr
def Expansion(inputbitstr32, e_table):
outputbitstr48 = []
outputbitstr48 = [inputbitstr32[index-1] for index in e_table]
outputbitstr48 = ''.join(outputbitstr48)
return outputbitstr48
#bits32 = "11110000101010101111000010101010"
#out_bits48 = Expansion(bits32, E_TABLE)
#print (out_bits48)
def permutation_function(sbox_value, P):
outputbitstr32 = []
outputbitstr32 = [sbox_value[index-1] for index in P]
outputbitstr32 = ''.join(outputbitstr32)
return outputbitstr32
def XORbits(bitstr1,bitstr2):
xor_result = ""
outstr = ""
for index in range(len(bitstr1)):
if bitstr1[index] == bitstr2[index]:
xor_result += "0"
else:
xor_result += "1"
#print("XOR:", xor_result)
#xor_result = outstr
return xor_result
#bits1 = '1100'
#bits2 = '1010'
#print (XORbits(bits1,bits2))
SBOX = [
# Box-1
[
[14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7],
[0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8],
[4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0],
[15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13]
],
# Box-2
[
[15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10],
[3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5],
[0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15],
[13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9]
],
# Box-3
[
[10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8],
[13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1],
[13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7],
[1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12]
],
# Box-4
[
[7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15],
[13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9],
[10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4],
[3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14]
],
# Box-5
[
[2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9],
[14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6],
[4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14],
[11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3]
],
# Box-6
[
[12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11],
[10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8],
[9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6],
[4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13]
],
# Box-7
[
[4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1],
[13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6],
[1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2],
[6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12]
],
# Box-8
[
[13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7],
[1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2],
[7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8],
[2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11]
]
]
# Let's define a table for quick conversion of sbox decimals to 4 bit binary
DECtoBIN4 = {0: '0000',
1: '0001',
2: '0010',
3: '0011',
4: '0100',
5: '0101',
6: '0110',
7: '0111',
8: '1000',
9: '1001',
10: '1010',
11: '1011',
12: '1100',
13: '1101',
14: '1110',
15: '1111'}
#print(DECtoBIN4[12])
def pre_sbox_lookup(xor_result):
blocklist=[xor_result[i:i+6] for i in range(0,len(xor_result),6)]
return blocklist
def sbox_lookup(input6bitstr, sboxindex):
row = int(input6bitstr[0] + input6bitstr[-1],base=2)
col = int(input6bitstr[1:5],base=2)
sbox_value = SBOX[int(sboxindex)][row][col]
return DECtoBIN4[sbox_value]
def des_round(LE_inp32, RE_inp32, key48):
LE_out32 = RE_inp32
RE_tmp = functionF(RE_inp32,key48)
RE_out32 = XORbits(LE_inp32, RE_tmp)
return LE_out32, RE_out32
def functionF(bitstr32, keybitstr48):
outbitstr32 = ''
result_sbox_lookup = ''
after_sbox_lookup = []
result_outbitstr32 = []
sbox_bits = ''
expanded_right_48bit = Expansion(bitstr32, E_TABLE)
xor_result = XORbits(expanded_right_48bit, keybitstr48)
xor_result_6bits = pre_sbox_lookup(xor_result)
for i,j in zip(range(0,len(xor_result),6),range(0,8)):
sbox_bits = sbox_bits + sbox_lookup(xor_result[i:i+6],j)
result_outbitstr32 = permutation_function(sbox_bits, P)
outbitstr32 = ''.join(result_outbitstr32)
return outbitstr32
def des_enc(inputblock, num_rounds, inputkey64):
key_64bit = byteseq2binstr(inputkey64)
keylist = des_key_generation(key_64bit)
input_64bit = byteseq2binstr(inputblock)
inputblock = Permutation(input_64bit,BookInitPermOrder)
LE_init = inputblock[:32]
RE_init = inputblock[32:]
for i in range(0,num_rounds):
LE_init, RE_init = des_round(LE_init, RE_init,keylist[i])
cipherRevblock = RE_init + LE_init
cipher_block = Permutation(cipherRevblock, BookInvInitPermOrder)
cipherblock = bytes([int(cipher_block[i:i+8],base =2) for i in range(0,len(cipher_block),8)])
return cipherblock
def des_enc_test(input_fname, inputkey64, num_rounds, output_fname):
finp = open(input_fname, 'rb')
inpbyteseq = finp.read()
finp.close()
cipherblocks=[]
inpbyteseq=inpbyteseq+(b'\x20'*(8-(len(inpbyteseq)%8))) if len(inpbyteseq)%8 !=0 else inpbyteseq
blocklist=[inpbyteseq[i:i+8] for i in range(0,len(inpbyteseq),8)]
cipherblocks = [des_enc(i,num_rounds,inputkey64) for i in blocklist]
cipherbyteseq = b''.join(cipherblocks)
fout = open(output_fname, 'wb')
fout.write(cipherbyteseq)
fout.close()
def des_dec(inputblock, num_rounds, inputkey64):
key_64bit = byteseq2binstr(inputkey64)
keylist = des_key_generation(key_64bit)
input_64bit = byteseq2binstr(inputblock)
inputblock = Permutation(input_64bit,BookInitPermOrder)
LE_init = inputblock[:32]
RE_init = inputblock[32:]
for i in range(0,num_rounds):
LE_init, RE_init = des_round(LE_init, RE_init,keylist[15 - i])
plainRevblock = RE_init + LE_init
plain_block = Permutation(plainRevblock, BookInvInitPermOrder)
plainblock = bytes([int(plain_block[i:i+8],base =2) for i in range(0,len(plain_block),8)])
return plainblock
def des_dec_test(input_fname, inputkey64, num_rounds, output_fname):
finp = open(input_fname, 'rb')
cipherbyteseq = finp.read()
finp.close()
blocklist=[cipherbyteseq[i:i+8] for i in range(0,len(cipherbyteseq),8)]
plainblocks = []
plainblocks = [des_dec(i,num_rounds,inputkey64) for i in blocklist]
plainbyteseq = b''.join(plainblocks)
fout = open(output_fname, 'wb')
fout.write(plainbyteseq)
fout.close()
#def main():
# inputblock = b'\x02\x46\x8a\xce\xec\xa8\x64\x20'
# key = b'\x0f\x15\x71\xc9\x47\xd9\xe8\x59'
# cipherblock = '\xda\x02\xce\x3a\x89\xec\xac\x3b'
# cipherblock = des_enc(inputblock, 16, key)
# print(cipherblock)
if __name__ == "__main__":
main()
def main():
Plaintext =b'\x02\x46\x8a\xce\xec\xa8\x64\x20'
Key = b'\x0f\x15\x71\xc9\x47\xd9\xe8\x59'#0f1571c947d9e859
Ciphertext = des_enc(Plaintext, 16, Key)
print(Ciphertext.hex())
Message = des_dec(Ciphertext, 16, Key)
print(Message.hex())
#inp="test.txt"
#inputkey64= b'\x0f\x15\x71\xc9\x47\xd9\xe8\x59'
#output="output_des.txt"
#des_enc_test(inp,inputkey64,16,output)
#inp="output_des.txt"
#output="sample1_des.txt"
#des_dec_test(inp,inputkey64,16,output)