mode constants are only in blockcipher
[python-cryptoplus.git] / src / Cipher / pypresent.py
blob186c13aca4c0c7c9a5bb81e91e39a282adb1f29d
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 8
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 #3. Salt
74 #rawKey[15:19] ^ i
75 temp = (int(key,16) >> 15)
76 temp = temp ^ i
77 key = ( int(key,16) & (pow(2,15)-1) ) + (temp << 15)
78 key = ("%x" % key).zfill(80/4)
79 return roundkeys
81 def generateRoundkeys128(key,rounds):
82 """Generate the roundkeys for a 128 bit key
84 Give a 128bit hex string as input and get a list of roundkeys in return"""
85 roundkeys = []
86 for i in range(1,rounds+1): # (K0 ... K32)
87 roundkeys.append(("%x" % (int(key,16) >>64)).zfill(64/4))
88 #1. Shift
89 key = ("%x" % ( ((int(key,16) & (pow(2,67)-1)) << 61) + (int(key,16) >> 67))).zfill(128/4)
90 #2. SBox
91 key = SBox[int(key[0],16)]+SBox[int(key[1],16)]+key[2:]
92 #3. Salt
93 #rawKey[15:19] ^ i
94 temp = (int(key,16) >> 62)
95 temp = temp ^ (i%32)
96 key = ( int(key,16) & (pow(2,62)-1) ) + (temp << 62)
97 key = ("%x" % key).zfill(128/4)
98 return roundkeys
100 def addRoundKey(state,roundkey):
101 return ( "%x" % ( int(state,16) ^ int(roundkey,16) ) ).zfill(16)
103 def sBoxLayer(state):
104 """SBox function for encryption
106 Takes a hex string as input and will output a hex string"""
107 output =''
108 for i in range(len(state)):
109 output += SBox[int(state[i],16)]
110 return output
112 def sBoxLayer_dec(state):
113 """Inverse SBox function for decryption
115 Takes a hex string as input and will output a hex string"""
116 output =''
117 for i in range(len(state)):
118 output += hex( SBox.index(state[i]) )[2:]
119 return output
121 def pLayer(state):
122 """Permutation layer for encryption
124 Takes a 64bit hex string as input and will output a 64bit hex string"""
125 output = ''
126 state_bin = bin(int(state,16)).zfill(64)[::-1][0:64]
127 for i in range(64):
128 output += state_bin[PBox.index(i)]
129 return ("%x" % int(output[::-1],2)).zfill(16)
131 def pLayer_dec(state):
132 """Permutation layer for decryption
134 Takes a 64bit hex string as input and will output a 64bit hex string"""
135 output = ''
136 state_bin = bin(int(state,16)).zfill(64)[::-1][0:64]
137 for i in range(64):
138 output += state_bin[PBox[i]]
139 return ("%x" % int(output[::-1],2)).zfill(16)
141 def bin(a):
142 """Convert an integer to a bin string (1 char represents 1 bit)"""
143 #http://wiki.python.org/moin/BitManipulation
144 s=''
145 t={'0':'000','1':'001','2':'010','3':'011','4':'100','5':'101','6':'110','7':'111'}
146 for c in oct(a).rstrip('L')[1:]:
147 s+=t[c]
148 return s