Difference between revisions of "Present python implementation"
Jump to navigation
Jump to search
m |
m |
||
Line 4: | Line 4: | ||
{{#fileanchor: pypresent.py}} |
{{#fileanchor: pypresent.py}} |
||
<source lang=python> |
<source lang=python> |
||
+ | # fully based on standard specifications: http://www.crypto.ruhr-uni-bochum.de/imperia/md/content/texte/publications/conferences/present_ches2007.pdf |
||
+ | # test vectors: http://www.crypto.ruhr-uni-bochum.de/imperia/md/content/texte/publications/conferences/slides/present_testvectors.zip |
||
+ | |||
class Present: |
class Present: |
||
− | + | def __init__(self,key): |
|
− | + | self.key = key.encode('hex') |
|
− | + | if len(self.key) == 80/4: |
|
− | + | self.roundkeys = generateRoundkeys80(self.key) |
|
− | + | elif len(self.key) == 128/4: |
|
− | + | self.roundkeys = generateRoundkeys128(self.key) |
|
− | + | else: |
|
+ | pass |
||
− | pass |
||
− | + | def encrypt(self,block): |
|
− | + | state = block.encode('hex') |
|
+ | for i in range (1,32): |
||
+ | state = addRoundKey(state,self.roundkeys[i-1]) |
||
+ | state = sBoxLayer(state) |
||
+ | state = pLayer(state) |
||
+ | cipher = addRoundKey(state,self.roundkeys[31]) |
||
+ | return cipher |
||
+ | |||
− | for i in range (1,32): |
||
+ | def decrypt(self,block): |
||
− | state = addRoundKey(state,self.roundkeys[i-1]) |
||
+ | state = block.encode('hex') |
||
− | #print "roundkey" |
||
+ | for i in range (1,32): |
||
− | #print state |
||
− | + | state = addRoundKey(state,self.roundkeys[32-i]) |
|
+ | state = pLayer_dec(state) |
||
− | #print "sbox" |
||
+ | state = sBoxLayer_dec(state) |
||
− | #print state |
||
+ | decipher = addRoundKey(state,self.roundkeys[0]) |
||
− | state = pLayer(state) |
||
+ | return decipher |
||
− | #print "pLayer" |
||
− | #print state |
||
− | cipher = addRoundKey(state,self.roundkeys[31]) |
||
+ | def get_block_size(self): |
||
− | return cipher |
||
+ | return 16 |
||
+ | # 0 1 2 3 4 5 6 7 8 9 a b c d e f |
||
− | |||
+ | SBox = ['c','5','6','b','9','0','a','d','3','e','f','8','4','7','1','2'] |
||
− | def decrypt(self,block): |
||
− | pass |
||
− | |||
− | def get_block_size(self): |
||
− | return 16 |
||
− | |||
− | SBox = ('c','5','6','b','9','0','a','d','3','e','f','8','4','7','1','2') |
||
PBox = [0,16,32,48,1,17,33,49,2,18,34,50,3,19,35,51, |
PBox = [0,16,32,48,1,17,33,49,2,18,34,50,3,19,35,51, |
||
− | + | 4,20,36,52,5,21,37,53,6,22,38,54,7,23,39,55, |
|
− | + | 8,24,40,56,9,25,41,57,10,26,42,58,11,27,43,59, |
|
− | + | 12,28,44,60,13,29,45,61,14,30,46,62,15,31,47,63] |
|
def generateRoundkeys80(key): |
def generateRoundkeys80(key): |
||
− | + | # input: hex string ex. 'ffff' |
|
− | + | roundkeys = [] |
|
− | + | for i in range(1,33): # (K0 ... K32) |
|
− | + | # rawKey[0:63] |
|
− | + | roundkeys.append(("%x" % (int(key,16) >>16 )).zfill(64/4)) |
|
− | + | #1. Shift |
|
− | + | #rawKey[19:(len(rawKey)-1)]+rawKey[0:18] |
|
− | + | key = ("%x" % ( ((int(key,16) & (pow(2,19)-1)) << 61) + (int(key,16) >> 19))).zfill(80/4) |
|
+ | #2. SBox |
||
− | #print "shift" |
||
+ | #rawKey[76:79] = S(rawKey[76:79]) |
||
− | #print key |
||
+ | key = S(key[0])+key[1:20] |
||
− | #2. SBox |
||
+ | #3. Salt |
||
− | #rawKey[76:79] = S(rawKey[76:79]) |
||
+ | #rawKey[15:19] ^ i |
||
− | key = S(key[0])+key[1:20] |
||
+ | temp = (int(key,16) >> 15) & (pow(2,5)-1) # rawKey[15:19] |
||
− | #print "sbox" |
||
+ | temp = temp ^ i |
||
− | #print key |
||
+ | key = ( int(key,16) & (pow(2,15)-1) ) + (temp << 15) + ( (int(key,16) >> 20) <<20 ) |
||
− | #3. Salt |
||
+ | key = "%x" % key |
||
− | #rawKey[15:19] ^ i |
||
+ | return roundkeys |
||
− | temp = (int(key,16) >> 15) & (pow(2,5)-1) # rawKey[15:19] |
||
− | temp = temp ^ i |
||
− | key = ( int(key,16) & (pow(2,15)-1) ) + (temp << 15) + ( (int(key,16) >> 20) <<20 ) |
||
− | key = "%x" % key |
||
− | #print "salt" |
||
− | #print key |
||
− | return roundkeys |
||
def generateRoundkeys128(key): |
def generateRoundkeys128(key): |
||
− | + | # input: hex string ex. 'ffff' |
|
− | + | roundkeys = [] |
|
− | + | for i in range(1,33): # (K0 ... K32) |
|
− | + | roundkeys.append(("%x" % (int(key,16) >>64)).zfill(64/4)) |
|
− | + | #1. Shift |
|
− | + | key = ("%x" % ( ((int(key,16) & (pow(2,67)-1)) << 61) + (int(key,16) >> 67))).zfill(128/4) |
|
+ | #2. SBox |
||
− | print "shift" |
||
+ | key = S(key[0])+S(key[1])+key[2:] |
||
− | print key |
||
+ | #3. Salt |
||
− | #2. SBox |
||
+ | #rawKey[15:19] ^ i |
||
− | key = S(key[0])+S(key[1])+key[2:] |
||
+ | temp = (int(key,16) >> 62) & (pow(2,5)-1) # rawKey[15:19] |
||
− | print "sbox" |
||
+ | temp = temp ^ i |
||
− | print key |
||
+ | key = ( int(key,16) & (pow(2,62)-1) ) + (temp << 62) + ( (int(key,16) >> 67) <<67 ) |
||
− | #3. Salt |
||
+ | key = "%x" % key |
||
− | #rawKey[15:19] ^ i |
||
+ | return roundkeys |
||
− | temp = (int(key,16) >> 62) & (pow(2,5)-1) # rawKey[15:19] |
||
− | temp = temp ^ i |
||
− | key = ( int(key,16) & (pow(2,62)-1) ) + (temp << 62) + ( (int(key,16) >> 67) <<67 ) |
||
− | key = "%x" % key |
||
− | print "salt" |
||
− | print key |
||
− | return roundkeys |
||
− | |||
− | def S(toS): |
||
− | #apply 4bit Sbox to a hexstring |
||
− | final ='' |
||
− | for i in range (0,len(toS)): |
||
− | final += SBox[int(toS[i],16)] |
||
− | #return convertToBitstring(final,len(toS)*8)[::-1] |
||
− | return final |
||
def addRoundKey(state,roundkey): |
def addRoundKey(state,roundkey): |
||
− | + | return ( "%x" % ( int(state,16) ^ int(roundkey,16) ) ).zfill(16) |
|
def sBoxLayer(state): |
def sBoxLayer(state): |
||
− | + | output ='' |
|
− | + | for i in range(len(state)): |
|
− | + | output += SBox[int(state[i],16)] |
|
− | + | return output |
|
+ | |||
+ | def sBoxLayer_dec(state): |
||
+ | output ='' |
||
+ | for i in range(len(state)): |
||
+ | output += hex( SBox.index(state[i]) )[2:] |
||
+ | return output |
||
def pLayer(state): |
def pLayer(state): |
||
− | + | output = '' |
|
− | + | state_bin = bin(int(state,16)).zfill(64)[::-1][0:64] |
|
− | + | for i in range(64): |
|
− | + | output += state_bin[PBox.index(i)] |
|
− | + | return ("%x" % int(output[::-1],2)).zfill(16) |
|
+ | |||
+ | def pLayer_dec(state): |
||
+ | output = '' |
||
+ | state_bin = bin(int(state,16)).zfill(64)[::-1][0:64] |
||
+ | for i in range(64): |
||
+ | output += state_bin[PBox[i]] |
||
+ | return ("%x" % int(output[::-1],2)).zfill(16) |
||
def bin(a): |
def bin(a): |
||
− | + | #int to bin |
|
− | + | #http://wiki.python.org/moin/BitManipulation |
|
− | + | s='' |
|
− | + | t={'0':'000','1':'001','2':'010','3':'011','4':'100','5':'101','6':'110','7':'111'} |
|
− | + | for c in oct(a).rstrip('L')[1:]: |
|
− | + | s+=t[c] |
|
− | + | return s |
|
</source> |
</source> |
||
Download code: [{{#filelink: pypresent.py}} pypresent.py] |
Download code: [{{#filelink: pypresent.py}} pypresent.py] |
Revision as of 11:12, 4 October 2008
what should be working (only tested with 1 or 2 test vectors yet):
- calculating round keys
- encrypting a block
{{#fileanchor: pypresent.py}}
# fully based on standard specifications: http://www.crypto.ruhr-uni-bochum.de/imperia/md/content/texte/publications/conferences/present_ches2007.pdf
# test vectors: http://www.crypto.ruhr-uni-bochum.de/imperia/md/content/texte/publications/conferences/slides/present_testvectors.zip
class Present:
def __init__(self,key):
self.key = key.encode('hex')
if len(self.key) == 80/4:
self.roundkeys = generateRoundkeys80(self.key)
elif len(self.key) == 128/4:
self.roundkeys = generateRoundkeys128(self.key)
else:
pass
def encrypt(self,block):
state = block.encode('hex')
for i in range (1,32):
state = addRoundKey(state,self.roundkeys[i-1])
state = sBoxLayer(state)
state = pLayer(state)
cipher = addRoundKey(state,self.roundkeys[31])
return cipher
def decrypt(self,block):
state = block.encode('hex')
for i in range (1,32):
state = addRoundKey(state,self.roundkeys[32-i])
state = pLayer_dec(state)
state = sBoxLayer_dec(state)
decipher = addRoundKey(state,self.roundkeys[0])
return decipher
def get_block_size(self):
return 16
# 0 1 2 3 4 5 6 7 8 9 a b c d e f
SBox = ['c','5','6','b','9','0','a','d','3','e','f','8','4','7','1','2']
PBox = [0,16,32,48,1,17,33,49,2,18,34,50,3,19,35,51,
4,20,36,52,5,21,37,53,6,22,38,54,7,23,39,55,
8,24,40,56,9,25,41,57,10,26,42,58,11,27,43,59,
12,28,44,60,13,29,45,61,14,30,46,62,15,31,47,63]
def generateRoundkeys80(key):
# input: hex string ex. 'ffff'
roundkeys = []
for i in range(1,33): # (K0 ... K32)
# rawKey[0:63]
roundkeys.append(("%x" % (int(key,16) >>16 )).zfill(64/4))
#1. Shift
#rawKey[19:(len(rawKey)-1)]+rawKey[0:18]
key = ("%x" % ( ((int(key,16) & (pow(2,19)-1)) << 61) + (int(key,16) >> 19))).zfill(80/4)
#2. SBox
#rawKey[76:79] = S(rawKey[76:79])
key = S(key[0])+key[1:20]
#3. Salt
#rawKey[15:19] ^ i
temp = (int(key,16) >> 15) & (pow(2,5)-1) # rawKey[15:19]
temp = temp ^ i
key = ( int(key,16) & (pow(2,15)-1) ) + (temp << 15) + ( (int(key,16) >> 20) <<20 )
key = "%x" % key
return roundkeys
def generateRoundkeys128(key):
# input: hex string ex. 'ffff'
roundkeys = []
for i in range(1,33): # (K0 ... K32)
roundkeys.append(("%x" % (int(key,16) >>64)).zfill(64/4))
#1. Shift
key = ("%x" % ( ((int(key,16) & (pow(2,67)-1)) << 61) + (int(key,16) >> 67))).zfill(128/4)
#2. SBox
key = S(key[0])+S(key[1])+key[2:]
#3. Salt
#rawKey[15:19] ^ i
temp = (int(key,16) >> 62) & (pow(2,5)-1) # rawKey[15:19]
temp = temp ^ i
key = ( int(key,16) & (pow(2,62)-1) ) + (temp << 62) + ( (int(key,16) >> 67) <<67 )
key = "%x" % key
return roundkeys
def addRoundKey(state,roundkey):
return ( "%x" % ( int(state,16) ^ int(roundkey,16) ) ).zfill(16)
def sBoxLayer(state):
output =''
for i in range(len(state)):
output += SBox[int(state[i],16)]
return output
def sBoxLayer_dec(state):
output =''
for i in range(len(state)):
output += hex( SBox.index(state[i]) )[2:]
return output
def pLayer(state):
output = ''
state_bin = bin(int(state,16)).zfill(64)[::-1][0:64]
for i in range(64):
output += state_bin[PBox.index(i)]
return ("%x" % int(output[::-1],2)).zfill(16)
def pLayer_dec(state):
output = ''
state_bin = bin(int(state,16)).zfill(64)[::-1][0:64]
for i in range(64):
output += state_bin[PBox[i]]
return ("%x" % int(output[::-1],2)).zfill(16)
def bin(a):
#int to bin
#http://wiki.python.org/moin/BitManipulation
s=''
t={'0':'000','1':'001','2':'010','3':'011','4':'100','5':'101','6':'110','7':'111'}
for c in oct(a).rstrip('L')[1:]:
s+=t[c]
return s
Download code: [{{#filelink: pypresent.py}} pypresent.py]