Difference between revisions of "Present python implementation"

From YobiWiki
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):
+
def __init__(self,key):
self.key = key.encode('hex')
+
self.key = key.encode('hex')
if len(self.key) == 80/4:
+
if len(self.key) == 80/4:
self.roundkeys = generateRoundkeys80(self.key)
+
self.roundkeys = generateRoundkeys80(self.key)
elif len(self.key) == 128/4:
+
elif len(self.key) == 128/4:
self.roundkeys = generateRoundkeys128(self.key)
+
self.roundkeys = generateRoundkeys128(self.key)
else:
+
else:
  +
pass
pass
 
   
def encrypt(self,block):
+
def encrypt(self,block):
state = block.encode('hex')
+
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 = sBoxLayer(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,
+
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,
+
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]
+
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'
+
# input: hex string ex. 'ffff'
roundkeys = []
+
roundkeys = []
for i in range(1,33): # (K0 ... K32)
+
for i in range(1,33): # (K0 ... K32)
# rawKey[0:63]
+
# rawKey[0:63]
roundkeys.append(("%x" % (int(key,16) >>16 )).zfill(64/4))
+
roundkeys.append(("%x" % (int(key,16) >>16 )).zfill(64/4))
#1. Shift
+
#1. Shift
#rawKey[19:(len(rawKey)-1)]+rawKey[0:18]
+
#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)
+
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'
+
# input: hex string ex. 'ffff'
roundkeys = []
+
roundkeys = []
for i in range(1,33): # (K0 ... K32)
+
for i in range(1,33): # (K0 ... K32)
roundkeys.append(("%x" % (int(key,16) >>64)).zfill(64/4))
+
roundkeys.append(("%x" % (int(key,16) >>64)).zfill(64/4))
#1. Shift
+
#1. Shift
key = ("%x" % ( ((int(key,16) & (pow(2,67)-1)) << 61) + (int(key,16) >> 67))).zfill(128/4)
+
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)
+
return ( "%x" % ( int(state,16) ^ int(roundkey,16) ) ).zfill(16)
   
 
def sBoxLayer(state):
 
def sBoxLayer(state):
output =''
+
output =''
for i in range(len(state)):
+
for i in range(len(state)):
output += S(state[i])
+
output += SBox[int(state[i],16)]
return output
+
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 = ''
+
output = ''
state_bin = bin(int(state,16)).zfill(64)[::-1][0:64]
+
state_bin = bin(int(state,16)).zfill(64)[::-1][0:64]
for i in range(64):
+
for i in range(64):
output += state_bin[PBox.index(i)]
+
output += state_bin[PBox.index(i)]
return "%x" % int(output[::-1],2)
+
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
+
#int to bin
#http://wiki.python.org/moin/BitManipulation
+
#http://wiki.python.org/moin/BitManipulation
s=''
+
s=''
t={'0':'000','1':'001','2':'010','3':'011','4':'100','5':'101','6':'110','7':'111'}
+
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:]:
+
for c in oct(a).rstrip('L')[1:]:
s+=t[c]
+
s+=t[c]
return s
+
return s
 
</source>
 
</source>
 
Download code: [{{#filelink: pypresent.py}} pypresent.py]
 
Download code: [{{#filelink: pypresent.py}} pypresent.py]

Revision as of 12: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]