Present python implementation

From YobiWiki
Jump to navigation Jump to search

what should be working (only tested with 1 or 2 test vectors yet):

  • calculating round keys
  • encrypting a block

{{#fileanchor: pyserpent.py}}

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])
			#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

Download code: [{{#filelink: pyserpent.py}} pyserpent.py]