blockcipher.py: removed unused error classes and exception import
[python-cryptoplus.git] / src / CryptoPlus / Cipher / blockcipher.py
blob84eaebbfaff2c40887842e27a97e1dc3743ca775
1 # =============================================================================
2 # Copyright (c) 2008 Christophe Oosterlynck (christophe.oosterlynck@gmail.com)
3 # Philippe Teuwen (philippe.teuwen@nxp.com)
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 # THE SOFTWARE.
22 # =============================================================================
23 from ..Util import util
24 from array import array
25 from ..Util.padding import Padding
27 MODE_ECB = 1
28 MODE_CBC = 2
29 MODE_CFB = 3
30 MODE_OFB = 5
31 MODE_CTR = 6
32 MODE_XTS = 7
33 MODE_CMAC = 8
35 class BlockCipher():
36 """ Base class for all blockciphers
37 """
39 key_error_message = "Wrong key size" #should be overwritten in child classes
41 def __init__(self,key,mode,IV,counter,cipher_module,args={}):
42 # Cipher classes inheriting from this one take care of:
43 # self.blocksize
44 # self.cipher
45 self.key = key
46 self.mode = mode
47 self.cache = ''
48 self.ed = None
50 if 'keylen_valid' in dir(self): #wrappers for pycrypto functions don't have this function
51 if not self.keylen_valid(key) and type(key) is not tuple:
52 raise ValueError(self.key_error_message)
54 if mode <> MODE_XTS:
55 self.cipher = cipher_module(self.key,**args)
56 if mode == MODE_ECB:
57 self.chain = ECB(self.cipher, self.blocksize)
58 elif mode == MODE_CBC:
59 if IV == None:
60 raise Exception,"Provide an IV!"
61 if len(IV) <> self.blocksize:
62 raise Exception,"the IV length should be %i bytes"%self.blocksize
63 self.chain = CBC(self.cipher, self.blocksize,IV)
64 elif mode == MODE_CFB:
65 if IV == None:
66 raise Exception,"Provide an IV!"
67 if len(IV) <> self.blocksize:
68 raise Exception,"the IV length should be %i bytes"%self.blocksize
69 self.chain = CFB(self.cipher, self.blocksize,IV)
70 elif mode == MODE_OFB:
71 if IV == None:
72 raise Exception,"Provide an IV!"
73 if len(IV) <> self.blocksize:
74 raise ValueError("the IV length should be %i bytes"%self.blocksize)
75 self.chain = OFB(self.cipher, self.blocksize,IV)
76 elif mode == MODE_CTR:
77 if (counter == None) or not callable(counter):
78 raise Exception,"Supply a valid counter object for the CTR mode"
79 self.chain = CTR(self.cipher,self.blocksize,counter)
80 elif mode == MODE_XTS:
81 if self.blocksize <> 16:
82 raise Exception,'XTS only works with blockcipher that have a 128-bit blocksize'
83 if not(type(key) == tuple and len(key) == 2):
84 raise Exception,'Supply two keys as a tuple when using XTS'
85 if 'keylen_valid' in dir(self): #wrappers for pycrypto functions don't have this function
86 if not self.keylen_valid(key[0]) or not self.keylen_valid(key[1]):
87 raise ValueError(self.key_error_message)
88 self.cipher = cipher_module(self.key[0],**args)
89 self.cipher2 = cipher_module(self.key[1],**args)
90 self.chain = XTS(self.cipher, self.cipher2)
91 elif mode == MODE_CMAC:
92 if self.blocksize not in (8,16):
93 raise Exception,'CMAC only works with blockcipher that have a 64 or 128-bit blocksize'
94 self.chain = CMAC(self.cipher,self.blocksize)
95 else:
96 raise Exception,"Unknown chaining mode!"
98 def encrypt(self,plaintext,n=''):
99 """Encrypt some plaintext
101 plaintext = a string of binary data
102 n = the 'tweak' value when the chaining mode is XTS
104 The encrypt function will encrypt the supplied plaintext.
105 The behavior varies slightly depending on the chaining mode.
107 ECB, CBC:
108 ---------
109 When the supplied plaintext is not a multiple of the blocksize
110 of the cipher, then the remaining plaintext will be cached.
111 The next time the encrypt function is called with some plaintext,
112 the new plaintext will be concatenated to the cache and then
113 cache+plaintext will be encrypted.
115 CFB, OFB, CTR:
116 --------------
117 When the chaining mode allows the cipher to act as a stream cipher,
118 the encrypt function will always encrypt all of the supplied
119 plaintext immediately. No cache will be kept.
121 XTS:
122 ----
123 Because the handling of the last two blocks is linked,
124 it needs the whole block of plaintext to be supplied at once.
125 Every encrypt function called on a XTS cipher will output
126 an encrypted block based on the current supplied plaintext block.
128 CMAC:
129 -----
130 Everytime the function is called, the hash from the input data is calculated.
131 No finalizing needed.
132 The hashlength is equal to block size of the used block cipher.
134 #self.ed = 'e' if chain is encrypting, 'd' if decrypting,
135 # None if nothing happened with the chain yet
136 #assert self.ed in ('e',None)
137 # makes sure you don't encrypt with a cipher that has started decrypting
138 self.ed = 'e'
139 if self.mode == MODE_XTS:
140 # data sequence number (or 'tweak') has to be provided when in XTS mode
141 return self.chain.update(plaintext,'e',n)
142 else:
143 return self.chain.update(plaintext,'e')
145 def decrypt(self,ciphertext,n=''):
146 """Decrypt some ciphertext
148 ciphertext = a string of binary data
149 n = the 'tweak' value when the chaining mode is XTS
151 The decrypt function will decrypt the supplied ciphertext.
152 The behavior varies slightly depending on the chaining mode.
154 ECB, CBC:
155 ---------
156 When the supplied ciphertext is not a multiple of the blocksize
157 of the cipher, then the remaining ciphertext will be cached.
158 The next time the decrypt function is called with some ciphertext,
159 the new ciphertext will be concatenated to the cache and then
160 cache+ciphertext will be decrypted.
162 CFB, OFB, CTR:
163 --------------
164 When the chaining mode allows the cipher to act as a stream cipher,
165 the decrypt function will always decrypt all of the supplied
166 ciphertext immediately. No cache will be kept.
168 XTS:
169 ----
170 Because the handling of the last two blocks is linked,
171 it needs the whole block of ciphertext to be supplied at once.
172 Every decrypt function called on a XTS cipher will output
173 a decrypted block based on the current supplied ciphertext block.
175 CMAC:
176 -----
177 Mode not supported for decryption as this does not make sense.
179 #self.ed = 'e' if chain is encrypting, 'd' if decrypting,
180 # None if nothing happened with the chain yet
181 #assert self.ed in ('d',None)
182 # makes sure you don't decrypt with a cipher that has started encrypting
183 self.ed = 'd'
184 if self.mode == MODE_XTS:
185 # data sequence number (or 'tweak') has to be provided when in XTS mode
186 return self.chain.update(ciphertext,'d',n)
187 else:
188 return self.chain.update(ciphertext,'d')
190 def final(self,padding='PKCS7'):
191 # TODO: after calling final, reset the IV? so the cipher is as good as new?
192 """Finalizes the encryption by padding the cache
194 padding = padding function provided as an argument. Possible padding functions:
195 - 'zerosPadding'
196 - 'bitPadding'
197 - 'PKCS7' (default)
198 - 'ANSI_X923'
199 - 'ISO_10126'
201 While a cipher object is in encryption mode, the final function will pad the remaining cache and encrypt it.
202 If the cipher has been used for decryption, the final function won't do antyhing. You have to manually unpad if necessary or
203 construct a Padder yourself en use its unpad function.
205 After finalization, the chain can still be used but the IV, counter etc aren't reset but just continu as they were after the last step (finalization step).
207 assert self.mode not in (MODE_XTS, MODE_CMAC) # finalizing (=padding) doesn't make sense when in XTS or CMAC mode
208 if self.ed == 'e':
209 # when the chain is in encryption mode, finalizing will pad the cache and encrypt this last block
210 padder = Padding(self.blocksize)
211 if self.mode in (MODE_OFB,MODE_CFB,MODE_CTR):
212 dummy = '0'*(self.blocksize - self.chain.keystream.buffer_info()[1]) # a dummy string that will be used to get a valid padding
213 else: #ECB, CBC
214 dummy = self.chain.cache
215 return self.chain.update(padder.pad(dummy,padding)[len(dummy):],'e') # pad the cache and then only supply the padding to the update function
216 else:
217 # final function doesn't make sense when decrypting => padding should be removed manually
218 pass
220 class ECB:
221 """ECB chaining mode
223 def __init__(self, codebook, blocksize):
224 self.cache = ''
225 self.codebook = codebook
226 self.blocksize = blocksize
228 def update(self, data, ed):
229 """Processes the given ciphertext/plaintext
231 Inputs:
232 data: raw string of any length
233 ed: 'e' for encryption, 'd' for decryption
234 Output:
235 processed raw string block(s), if any
237 When the supplied data is not a multiple of the blocksize
238 of the cipher, then the remaining input data will be cached.
239 The next time the update function is called with some data,
240 the new data will be concatenated to the cache and then
241 cache+data will be processed and full blocks will be outputted.
243 output_blocks = []
244 self.cache += data
245 if len(self.cache) < self.blocksize:
246 return ''
247 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
248 #the only difference between encryption/decryption in the chain is the cipher block
249 if ed == 'e':
250 output_blocks.append(self.codebook.encrypt( self.cache[i:i + self.blocksize] ))
251 else:
252 output_blocks.append(self.codebook.decrypt( self.cache[i:i + self.blocksize] ))
253 self.cache = self.cache[i+self.blocksize:]
254 return ''.join(output_blocks)
256 class CBC:
257 """CBC chaining mode
259 def __init__(self, codebook, blocksize, IV):
260 self.IV = IV
261 self.cache = ''
262 self.codebook = codebook
263 self.blocksize = blocksize
265 def update(self, data, ed):
266 """Processes the given ciphertext/plaintext
268 Inputs:
269 data: raw string of any length
270 ed: 'e' for encryption, 'd' for decryption
271 Output:
272 processed raw string block(s), if any
274 When the supplied data is not a multiple of the blocksize
275 of the cipher, then the remaining input data will be cached.
276 The next time the update function is called with some data,
277 the new data will be concatenated to the cache and then
278 cache+data will be processed and full blocks will be outputted.
280 if ed == 'e':
281 encrypted_blocks = ''
282 self.cache += data
283 if len(self.cache) < self.blocksize:
284 return ''
285 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
286 self.IV = self.codebook.encrypt(util.xorstring(self.cache[i:i+self.blocksize],self.IV))
287 encrypted_blocks += self.IV
288 self.cache = self.cache[i+self.blocksize:]
289 return encrypted_blocks
290 else:
291 decrypted_blocks = ''
292 self.cache += data
293 if len(self.cache) < self.blocksize:
294 return ''
295 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
296 plaintext = util.xorstring(self.IV,self.codebook.decrypt(self.cache[i:i + self.blocksize]))
297 self.IV = self.cache[i:i + self.blocksize]
298 decrypted_blocks+=plaintext
299 self.cache = self.cache[i+self.blocksize:]
300 return decrypted_blocks
302 class CFB:
303 """CFB Chaining Mode
305 Can be accessed as a stream cipher.
308 def __init__(self, codebook, blocksize, IV):
309 self.codebook = codebook
310 self.IV = IV
311 self.blocksize = blocksize
312 self.keystream = []
313 def update(self, data, ed):
314 """Processes the given ciphertext/plaintext
316 Inputs:
317 data: raw string of any multiple of bytes
318 ed: 'e' for encryption, 'd' for decryption
319 Output:
320 processed raw string
322 The encrypt/decrypt functions will always process all of the supplied
323 input data immediately. No cache will be kept.
325 output = list(data)
327 for i in xrange(len(data)):
328 if ed =='e':
329 if len(self.keystream) == 0:
330 block = self.codebook.encrypt(self.IV)
331 self.keystream = list(block)
332 self.IV = ''
333 output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0)))
334 self.IV += output[i] # the IV for the next block in the chain is being built byte per byte as the ciphertext flows in
335 else:
336 if len(self.keystream) == 0:
337 block = self.codebook.encrypt(self.IV)
338 self.keystream = list(block)
339 self.IV = ''
340 self.IV += output[i]
341 output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0)))
342 return ''.join(output)
344 class OFB:
345 """OFB Chaining Mode
347 Can be accessed as a stream cipher.
349 def __init__(self, codebook, blocksize, IV):
350 self.codebook = codebook
351 self.IV = IV
352 self.blocksize = blocksize
353 self.keystream = []
354 def update(self, data, ed):
355 """Processes the given ciphertext/plaintext
357 Inputs:
358 data: raw string of any multiple of bytes
359 ed: 'e' for encryption, 'd' for decryption
360 Output:
361 processed raw string
363 The encrypt/decrypt functions will always process all of the supplied
364 input data immediately. No cache will be kept.
366 #no difference between encryption and decryption mode
367 n = len(data)
368 blocksize = self.blocksize
369 output = list(data)
371 for i in xrange(n):
372 if len(self.keystream) == 0: #encrypt a new counter block when the current keystream is fully used
373 self.IV = self.codebook.encrypt(self.IV)
374 self.keystream = list(self.IV)
375 output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0))) #as long as an encrypted counter value is available, the output is just "input XOR keystream"
376 return ''.join(output)
378 class CTR:
379 """CTR Chaining Mode
381 Can be accessed as a stream cipher.
383 # initial counter value can be choosen, decryption always starts from beginning
384 # -> you can start from anywhere yourself: just feed the cipher encoded blocks and feed a counter with the corresponding value
385 def __init__(self, codebook, blocksize, counter):
386 self.codebook = codebook
387 self.counter = counter
388 self.blocksize = blocksize
389 self.keystream = [] #holds the output of the current encrypted counter value
391 def update(self, data, ed):
392 """Processes the given ciphertext/plaintext
394 Inputs:
395 data: raw string of any multiple of bytes
396 ed: 'e' for encryption, 'd' for decryption
397 Output:
398 processed raw string
400 The encrypt/decrypt functions will always process all of the supplied
401 input data immediately. No cache will be kept.
403 # no need for the encryption/decryption distinction: both are the same
404 n = len(data)
405 blocksize = self.blocksize
407 output = list(data)
408 for i in xrange(n):
409 if len(self.keystream) == 0: #encrypt a new counter block when the current keystream is fully used
410 block = self.codebook.encrypt(self.counter())
411 self.keystream = list(block)
412 output[i] = chr(ord(output[i])^ord(self.keystream.pop(0))) #as long as an encrypted counter value is available, the output is just "input XOR keystream"
413 return ''.join(output)
415 class XTS:
416 """XTS Chaining Mode
418 # TODO: allow other blocksizes besides 16bytes?
419 def __init__(self,codebook1, codebook2):
420 self.cache = ''
421 self.codebook1 = codebook1
422 self.codebook2 = codebook2
424 def update(self, data, ed,tweak=''):
425 # supply n as a raw string
426 # tweak = data sequence number
427 """Perform a XTS encrypt/decrypt operation.
429 Because the handling of the last two blocks is linked,
430 it needs the whole block of ciphertext to be supplied at once.
431 Every decrypt function called on a XTS cipher will output
432 a decrypted block based on the current supplied ciphertext block.
434 output = ''
435 assert len(data) > 15, "At least one block of 128 bits needs to be supplied"
436 assert len(data) < 128*pow(2,20)
438 # initializing T
439 # e_k2_n = E_K2(tweak)
440 e_k2_n = self.codebook2.encrypt(tweak+ '\x00' * (16-len(tweak)))[::-1]
441 self.T = util.string2number(e_k2_n)
444 while i < ((len(data) // 16)-1): #Decrypt all the blocks but one last full block and opt one last partial block
445 # C = E_K1(P xor T) xor T
446 output += self.__xts_step(ed,data[i*16:(i+1)*16],self.T)
447 # T = E_K2(n) mul (a pow i)
448 self.__T_update()
449 i+=1
451 # Check if the data supplied is a multiple of 16 bytes -> one last full block and we're done
452 if len(data[i*16:]) == 16:
453 # C = E_K1(P xor T) xor T
454 output += self.__xts_step(ed,data[i*16:(i+1)*16],self.T)
455 # T = E_K2(n) mul (a pow i)
456 self.__T_update()
457 else:
458 T_temp = [self.T]
459 self.__T_update()
460 T_temp.append(self.T)
461 if ed=='d':
462 # Permutation of the last two indexes
463 T_temp.reverse()
464 # Decrypt/Encrypt the last two blocks when data is not a multiple of 16 bytes
465 Cm1 = data[i*16:(i+1)*16]
466 Cm = data[(i+1)*16:]
467 PP = self.__xts_step(ed,Cm1,T_temp[0])
468 Cp = PP[len(Cm):]
469 Pm = PP[:len(Cm)]
470 CC = Cm+Cp
471 Pm1 = self.__xts_step(ed,CC,T_temp[1])
472 output += Pm1 + Pm
473 return output
475 def __xts_step(self,ed,tocrypt,T):
476 T_string = util.number2string_N(T,16)[::-1]
477 # C = E_K1(P xor T) xor T
478 if ed == 'd':
479 return util.xorstring(T_string, self.codebook1.decrypt(util.xorstring(T_string, tocrypt)))
480 else:
481 return util.xorstring(T_string, self.codebook1.encrypt(util.xorstring(T_string, tocrypt)))
483 def __T_update(self):
484 # Used for calculating T for a certain step using the T value from the previous step
485 self.T = self.T << 1
486 # if (Cout)
487 if self.T >> (8*16):
488 #T[0] ^= GF_128_FDBK;
489 self.T = self.T ^ 0x100000000000000000000000000000087L
492 class CMAC:
493 """CMAC chaining mode
495 Supports every cipher with a blocksize available
496 in the list CMAC.supported_blocksizes.
497 The hashlength is equal to block size of the used block cipher.
499 # TODO: move to hash module?
500 # TODO: change update behaviour to .update() and .digest() as for all hash modules?
501 # -> other hash functions in pycrypto: calling update, concatenates current input with previous input and hashes everything
502 __Rb_dictionary = {64:0x000000000000001b,128:0x00000000000000000000000000000087}
503 supported_blocksizes = __Rb_dictionary.keys()
504 def __init__(self,codebook,blocksize):
505 # Purpose of init: calculate Lu & Lu2
506 #blocksize (in bytes): to select the Rb constant in the dictionary
507 #Rb as a dictionary: adding support for other blocksizes is easy
508 self.cache=''
509 self.blocksize = blocksize
510 self.codebook = codebook
512 #Rb_dictionary: holds values for Rb for different blocksizes
513 # values for 64 and 128 bits found here: http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
514 # explanation from: http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
515 # Rb is a representation of a certain irreducible binary polynomial of degree b, namely,
516 # the lexicographically first among all such polynomials with the minimum possible number of
517 # nonzero terms. If this polynomial is expressed as ub+cb-1ub-1+...+c2u2+c1u+c0, where the
518 # coefficients cb-1, cb-2, ..., c2, c1, c0 are either 0 or 1, then Rb is the bit string cb-1cb-2...c2c1c0.
520 self.Rb = self.__Rb_dictionary[blocksize*8]
522 mask1 = int(('\xff'*blocksize).encode('hex'),16)
523 mask2 = int(('\x80' + '\x00'*(blocksize-1) ).encode('hex'),16)
525 L = int(self.codebook.encrypt('\x00'*blocksize).encode('hex'),16)
527 if L & mask2:
528 Lu = ((L << 1) & mask1) ^ self.Rb
529 else:
530 Lu = L << 1
531 Lu = Lu & mask1
533 if Lu & mask2:
534 Lu2 = ((Lu << 1) & mask1)^ self.Rb
535 else:
536 Lu2 = Lu << 1
537 Lu2 = Lu2 & mask1
539 self.Lu =util.number2string_N(Lu,self.blocksize)
540 self.Lu2=util.number2string_N(Lu2,self.blocksize)
542 def update(self, data, ed):
543 """Processes the given ciphertext/plaintext
545 Inputs:
546 data: raw string of any length
547 ed: 'e' for encryption, 'd' for decryption
548 Output:
549 hashed data as raw string
551 This is not really an update function:
552 Everytime the function is called, the hash from the input data is calculated.
553 No finalizing needed.
555 assert ed == 'e'
556 blocksize = self.blocksize
558 m = (len(data)+blocksize-1)/blocksize #m = amount of datablocks
559 y = '\x00'*blocksize
561 for i in range(1,m):
562 y = self.codebook.encrypt( util.xorstring(data[(i-1)*blocksize:(i)*blocksize],y) )
564 if len(data[(i)*blocksize:])==blocksize:
565 X = util.xorstring(util.xorstring(data[(i)*blocksize:],y),self.Lu)
566 else:
567 tmp = data[(i)*blocksize:] + '\x80' + '\x00'*(blocksize - len(data[(i)*blocksize:])-1)
568 X = util.xorstring(util.xorstring(tmp,y),self.Lu2)
570 T = self.codebook.encrypt(X)
571 return T