1 # fully based on standard specifications: http://www.crypto.ruhr-uni-bochum.de/imperia/md/content/texte/publications/conferences/present_ches2007.pdf
2 # test vectors: http://www.crypto.ruhr-uni-bochum.de/imperia/md/content/texte/publications/conferences/slides/present_testvectors.zip
6 def __init__(self
,key
,rounds
=32):
7 """Generating roundkeys
9 When a Present class initialized, the roundkeys will be generated.
10 You can supply the key as a 128bit or 80bit rawstring.
13 self
.key
= key
.encode('hex')
14 if len(self
.key
) == 80/4:
15 self
.roundkeys
= generateRoundkeys80(self
.key
,self
.rounds
)
16 elif len(self
.key
) == 128/4:
17 self
.roundkeys
= generateRoundkeys128(self
.key
,self
.rounds
)
21 def encrypt(self
,block
):
22 """Encrypting 1 block (8 bytes)
24 Supply the plaintext block as a raw string and the raw
25 ciphertext will be returned.
27 state
= block
.encode('hex')
28 for i
in range (1,self
.rounds
):
29 state
= addRoundKey(state
,self
.roundkeys
[i
-1])
30 state
= sBoxLayer(state
)
32 cipher
= addRoundKey(state
,self
.roundkeys
[self
.rounds
-1])
33 return cipher
.decode('hex')
35 def decrypt(self
,block
):
36 """Decrypting 1 block (8 bytes)
38 Supply the ciphertext block as a raw string and the raw
39 plaintext will be returned.
41 state
= block
.encode('hex')
42 for i
in range (1,self
.rounds
):
43 state
= addRoundKey(state
,self
.roundkeys
[self
.rounds
-i
])
44 state
= pLayer_dec(state
)
45 state
= sBoxLayer_dec(state
)
46 decipher
= addRoundKey(state
,self
.roundkeys
[0])
47 return decipher
.decode('hex')
49 def get_block_size(self
):
52 # 0 1 2 3 4 5 6 7 8 9 a b c d e f
53 SBox
= ['c','5','6','b','9','0','a','d','3','e','f','8','4','7','1','2']
54 PBox
= [0,16,32,48,1,17,33,49,2,18,34,50,3,19,35,51,
55 4,20,36,52,5,21,37,53,6,22,38,54,7,23,39,55,
56 8,24,40,56,9,25,41,57,10,26,42,58,11,27,43,59,
57 12,28,44,60,13,29,45,61,14,30,46,62,15,31,47,63]
59 def generateRoundkeys80(key
,rounds
):
60 """Generate the roundkeys for a 80 bit key
62 Give a 80bit hex string as input and get a list of roundkeys in return"""
64 for i
in range(1,rounds
+1): # (K0 ... K32)
66 roundkeys
.append(("%x" % (int(key
,16) >>16 )).zfill(64/4))
68 #rawKey[19:(len(rawKey)-1)]+rawKey[0:18]
69 key
= ("%x" % ( ((int(key
,16) & (pow(2,19)-1)) << 61) + (int(key
,16) >> 19))).zfill(80/4)
71 #rawKey[76:79] = S(rawKey[76:79])
72 key
= SBox
[int(key
[0],16)]+key
[1:20]
75 temp
= (int(key
,16) >> 15)
77 key
= ( int(key
,16) & (pow(2,15)-1) ) + (temp
<< 15)
78 key
= ("%x" % key
).zfill(80/4)
81 def generateRoundkeys128(key
,rounds
):
82 """Generate the roundkeys for a 128 bit key
84 Give a 128bit hex string as input and get a list of roundkeys in return"""
86 for i
in range(1,rounds
+1): # (K0 ... K32)
87 roundkeys
.append(("%x" % (int(key
,16) >>64)).zfill(64/4))
89 key
= ("%x" % ( ((int(key
,16) & (pow(2,67)-1)) << 61) + (int(key
,16) >> 67))).zfill(128/4)
91 key
= SBox
[int(key
[0],16)]+SBox
[int(key
[1],16)]+key
[2:]
94 temp
= (int(key
,16) >> 62)
96 key
= ( int(key
,16) & (pow(2,62)-1) ) + (temp
<< 62)
97 key
= ("%x" % key
).zfill(128/4)
100 def addRoundKey(state
,roundkey
):
101 return ( "%x" % ( int(state
,16) ^
int(roundkey
,16) ) ).zfill(16)
103 def sBoxLayer(state
):
104 """SBox function for encryption
106 Takes a hex string as input and will output a hex string"""
108 for i
in range(len(state
)):
109 output
+= SBox
[int(state
[i
],16)]
112 def sBoxLayer_dec(state
):
113 """Inverse SBox function for decryption
115 Takes a hex string as input and will output a hex string"""
117 for i
in range(len(state
)):
118 output
+= hex( SBox
.index(state
[i
]) )[2:]
122 """Permutation layer for encryption
124 Takes a 64bit hex string as input and will output a 64bit hex string"""
126 state_bin
= bin(int(state
,16)).zfill(64)[::-1][0:64]
128 output
+= state_bin
[PBox
.index(i
)]
129 return ("%x" % int(output
[::-1],2)).zfill(16)
131 def pLayer_dec(state
):
132 """Permutation layer for decryption
134 Takes a 64bit hex string as input and will output a 64bit hex string"""
136 state_bin
= bin(int(state
,16)).zfill(64)[::-1][0:64]
138 output
+= state_bin
[PBox
[i
]]
139 return ("%x" % int(output
[::-1],2)).zfill(16)
142 """Convert an integer to a bin string (1 char represents 1 bit)"""
143 #http://wiki.python.org/moin/BitManipulation
145 t
={'0':'000','1':'001','2':'010','3':'011','4':'100','5':'101','6':'110','7':'111'}
146 for c
in oct(a
).rstrip('L')[1:]: