removed leftover from debugging code
[python-cryptoplus.git] / src / Cipher / pypresent.py
blob968a121925787f63bca3286f5994f216654beb0c
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
4 class Present:
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.
11 """
12 self.rounds = rounds
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)
18 else:
19 pass
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.
26 """
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)
31 state = pLayer(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.
40 """
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):
50 return 16
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"""
63 roundkeys = []
64 for i in range(1,rounds+1): # (K0 ... K32)
65 # rawKey[0:63]
66 roundkeys.append(("%x" % (int(key,16) >>16 )).zfill(64/4))
67 #1. Shift
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)
70 #2. SBox
71 #rawKey[76:79] = S(rawKey[76:79])
72 key = SBox[int(key[0],16)]+key[1:20]
73 #print "sbox"
74 #print key
75 #3. Salt
76 #rawKey[15:19] ^ i
77 temp = (int(key,16) >> 15)
78 temp = (temp ^ i )
79 key = ( int(key,16) & (pow(2,15)-1) ) + (temp << 15)
80 key = ("%x" % key).zfill(80/4)
81 return roundkeys
83 def generateRoundkeys128(key,rounds):
84 """Generate the roundkeys for a 128 bit key
86 Give a 80bit hex string as input and get a list of roundkeys in return"""
87 roundkeys = []
88 for i in range(1,rounds+1): # (K0 ... K32)
89 roundkeys.append(("%x" % (int(key,16) >>64)).zfill(64/4))
90 #1. Shift
91 key = ("%x" % ( ((int(key,16) & (pow(2,67)-1)) << 61) + (int(key,16) >> 67))).zfill(128/4)
92 #2. SBox
93 key = SBox[int(key[0],16)]+SBox[int(key[1],16)]+key[2:]
94 #3. Salt
95 #rawKey[15:19] ^ i
96 temp = (int(key,16) >> 62) & (pow(2,5)-1) # rawKey[15:19]
97 temp = temp ^ i
98 key = ( int(key,16) & (pow(2,62)-1) ) + (temp << 62) + ( (int(key,16) >> 67) <<67 )
99 key = "%x" % key
100 return roundkeys
102 def addRoundKey(state,roundkey):
103 return ( "%x" % ( int(state,16) ^ int(roundkey,16) ) ).zfill(16)
105 def sBoxLayer(state):
106 """SBox function for encryption
108 Takes a hex string as input and will output a hex string"""
109 output =''
110 for i in range(len(state)):
111 output += SBox[int(state[i],16)]
112 return output
114 def sBoxLayer_dec(state):
115 """Inverse SBox function for decryption
117 Takes a hex string as input and will output a hex string"""
118 output =''
119 for i in range(len(state)):
120 output += hex( SBox.index(state[i]) )[2:]
121 return output
123 def pLayer(state):
124 """Permutation layer for encryption
126 Takes a 64bit hex string as input and will output a 64bit hex string"""
127 output = ''
128 state_bin = bin(int(state,16)).zfill(64)[::-1][0:64]
129 for i in range(64):
130 output += state_bin[PBox.index(i)]
131 return ("%x" % int(output[::-1],2)).zfill(16)
133 def pLayer_dec(state):
134 """Permutation layer for decryption
136 Takes a 64bit hex string as input and will output a 64bit hex string"""
137 output = ''
138 state_bin = bin(int(state,16)).zfill(64)[::-1][0:64]
139 for i in range(64):
140 output += state_bin[PBox[i]]
141 return ("%x" % int(output[::-1],2)).zfill(16)
143 def bin(a):
144 """Convert an integer to a bin string (1 char represents 1 bit)"""
145 #http://wiki.python.org/moin/BitManipulation
146 s=''
147 t={'0':'000','1':'001','2':'010','3':'011','4':'100','5':'101','6':'110','7':'111'}
148 for c in oct(a).rstrip('L')[1:]:
149 s+=t[c]
150 return s