Difference between revisions of "Present python implementation"
Jump to navigation
Jump to search
m (Present python implementatin moved to Present python implementation: typo) |
m (deleted comments from during development) |
||
| (6 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
| + | This is a development done by Christophe Oosterlynck under my supervision during his thesis work & internship at NXP. |
||
| − | what should be working (only tested with 1 or 2 test vectors yet): |
||
| + | |||
| + | The code is available [http://repo.or.cz/w/python-cryptoplus.git?a=blob;f=src/CryptoPlus/Cipher/pypresent.py;hb=HEAD here] |
||
| + | |||
| + | Features: |
||
* calculating round keys |
* calculating round keys |
||
* encrypting a block |
* encrypting a block |
||
| + | * decrypting a block |
||
| − | {{#fileanchor: pyserpent.py}} |
||
| + | * supports amount of rounds different from the standard amount of 32 |
||
| − | <source lang=python> |
||
| + | ** tested with 32, 64, 128 and 65534 rounds |
||
| − | class Present: |
||
| + | ** PRESENT reference implementation supports amount of rounds up to 65534 |
||
| − | |||
| − | 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]) |
||
| − | #print "roundkey" |
||
| − | #print state |
||
| − | state = sBoxLayer(state) |
||
| − | #print "sbox" |
||
| − | #print state |
||
| − | state = pLayer(state) |
||
| − | #print "pLayer" |
||
| − | #print state |
||
| − | cipher = addRoundKey(state,self.roundkeys[31]) |
||
| − | |||
| − | return cipher |
||
| − | |||
| − | |||
| − | 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, |
||
| − | 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) |
||
| − | #print "shift" |
||
| − | #print key |
||
| − | #2. SBox |
||
| − | #rawKey[76:79] = S(rawKey[76:79]) |
||
| − | key = S(key[0])+key[1:20] |
||
| − | #print "sbox" |
||
| − | #print key |
||
| − | #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 |
||
| − | #print "salt" |
||
| − | #print 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) |
||
| − | print "shift" |
||
| − | print key |
||
| − | #2. SBox |
||
| − | key = S(key[0])+S(key[1])+key[2:] |
||
| − | print "sbox" |
||
| − | print key |
||
| − | #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 |
||
| − | 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): |
||
| − | return ( "%x" % ( int(state,16) ^ int(roundkey,16) ) ).zfill(16) |
||
| − | |||
| − | def sBoxLayer(state): |
||
| − | output ='' |
||
| − | for i in range(len(state)): |
||
| − | output += S(state[i]) |
||
| − | 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) |
||
| − | |||
| − | 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> |
||
| − | Download code: [{{#filelink: pyserpent.py}} pyserpent.py] |
||
Latest revision as of 01:00, 16 October 2008
This is a development done by Christophe Oosterlynck under my supervision during his thesis work & internship at NXP.
The code is available here
Features:
- calculating round keys
- encrypting a block
- decrypting a block
- supports amount of rounds different from the standard amount of 32
- tested with 32, 64, 128 and 65534 rounds
- PRESENT reference implementation supports amount of rounds up to 65534