Chaining Modes: docstrings & minor tuning
[python-cryptoplus.git] / src / CryptoPlus / Cipher / blockcipher.py
blob73153a0b2387552ec66d739163711b701fa4bcc1
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 import struct
26 from ..Util.padding import Padding
28 from exceptions import Exception
30 MODE_ECB = 1
31 MODE_CBC = 2
32 MODE_CFB = 3
33 MODE_OFB = 5
34 MODE_CTR = 6
35 MODE_XTS = 7
36 MODE_CMAC = 8
38 class Error(Exception):
39 """Base class for exceptions in this module."""
40 pass
42 class InputError(Error):
43 """Exception raised for errors in the input.
45 Attributes:
46 expression -- input expression in which the error occurred
47 message -- explanation of the error
48 """
50 def __init__(self, expression, message):
51 self.expression = expression
52 self.message = message
54 class BlockCipher():
55 """ Base class for all blockciphers
56 """
58 key_error_message = "Wrong key size" #should be overwritten in child classes
60 def __init__(self,key,mode,IV,counter,cipher_module,args={}):
61 # Cipher classes inheriting from this one take care of:
62 # self.blocksize
63 # self.cipher
64 self.key = key
65 self.mode = mode
66 self.cache = ''
67 self.ed = None
69 if 'keylen_valid' in dir(self): #wrappers for pycrypto functions don't have this function
70 if not self.keylen_valid(key) and type(key) is not tuple:
71 raise ValueError(self.key_error_message)
73 if mode <> MODE_XTS:
74 self.cipher = cipher_module(self.key,**args)
75 if mode == MODE_ECB:
76 self.chain = ECB(self.cipher, self.blocksize)
77 elif mode == MODE_CBC:
78 if IV == None:
79 raise Exception,"Provide an IV!"
80 if len(IV) <> self.blocksize:
81 raise Exception,"the IV length should be %i bytes"%self.blocksize
82 self.chain = CBC(self.cipher, self.blocksize,IV)
83 elif mode == MODE_CFB:
84 if IV == None:
85 raise Exception,"Provide an IV!"
86 if len(IV) <> self.blocksize:
87 raise Exception,"the IV length should be %i bytes"%self.blocksize
88 self.chain = CFB(self.cipher, self.blocksize,IV)
89 elif mode == MODE_OFB:
90 if IV == None:
91 raise Exception,"Provide an IV!"
92 if len(IV) <> self.blocksize:
93 raise ValueError("the IV length should be %i bytes"%self.blocksize)
94 self.chain = OFB(self.cipher, self.blocksize,IV)
95 elif mode == MODE_CTR:
96 if (counter == None) or not callable(counter):
97 raise Exception,"Supply a valid counter object for the CTR mode"
98 self.chain = CTR(self.cipher,self.blocksize,counter)
99 elif mode == MODE_XTS:
100 if self.blocksize <> 16:
101 raise Exception,'XTS only works with blockcipher that have a 128-bit blocksize'
102 if not(type(key) == tuple and len(key) == 2):
103 raise Exception,'Supply two keys as a tuple when using XTS'
104 if 'keylen_valid' in dir(self): #wrappers for pycrypto functions don't have this function
105 if not self.keylen_valid(key[0]) or not self.keylen_valid(key[1]):
106 raise ValueError(self.key_error_message)
107 self.cipher = cipher_module(self.key[0],**args)
108 self.cipher2 = cipher_module(self.key[1],**args)
109 self.chain = XTS(self.cipher, self.cipher2)
110 elif mode == MODE_CMAC:
111 if self.blocksize not in (8,16):
112 raise Exception,'CMAC only works with blockcipher that have a 64 or 128-bit blocksize'
113 self.chain = CMAC(self.cipher,self.blocksize)
114 else:
115 raise Exception,"Unknown chaining mode!"
117 def encrypt(self,plaintext,n=''):
118 """Encrypt some plaintext
120 plaintext = a string of binary data
121 n = the 'tweak' value when the chaining mode is XTS
123 The encrypt function will encrypt the supplied plaintext.
124 The behavior varies slightly depending on the chaining mode.
126 ECB, CBC:
127 ---------
128 When the supplied plaintext is not a multiple of the blocksize
129 of the cipher, then the remaining plaintext will be cached.
130 The next time the encrypt function is called with some plaintext,
131 the new plaintext will be concatenated to the cache and then
132 cache+plaintext will be encrypted.
134 CFB, OFB, CTR:
135 --------------
136 When the chaining mode allows the cipher to act as a stream cipher,
137 the encrypt function will always encrypt all of the supplied
138 plaintext immediately. No cache will be kept.
140 XTS:
141 ----
142 Because the handling of the last two blocks is linked,
143 it needs the whole block of plaintext to be supplied at once.
144 Every encrypt function called on a XTS cipher will output
145 an encrypted block based on the current supplied plaintext block.
147 CMAC:
148 -----
149 Everytime the function is called, the hash from the input data is calculated.
150 No finalizing needed.
151 The hashlength is equal to block size of the used block cipher.
153 #self.ed = 'e' if chain is encrypting, 'd' if decrypting,
154 # None if nothing happened with the chain yet
155 #assert self.ed in ('e',None)
156 # makes sure you don't encrypt with a cipher that has started decrypting
157 self.ed = 'e'
158 if self.mode == MODE_XTS:
159 # data sequence number (or 'tweak') has to be provided when in XTS mode
160 return self.chain.update(plaintext,'e',n)
161 else:
162 return self.chain.update(plaintext,'e')
164 def decrypt(self,ciphertext,n=''):
165 """Decrypt some ciphertext
167 ciphertext = a string of binary data
168 n = the 'tweak' value when the chaining mode is XTS
170 The decrypt function will decrypt the supplied ciphertext.
171 The behavior varies slightly depending on the chaining mode.
173 ECB, CBC:
174 ---------
175 When the supplied ciphertext is not a multiple of the blocksize
176 of the cipher, then the remaining ciphertext will be cached.
177 The next time the decrypt function is called with some ciphertext,
178 the new ciphertext will be concatenated to the cache and then
179 cache+ciphertext will be decrypted.
181 CFB, OFB, CTR:
182 --------------
183 When the chaining mode allows the cipher to act as a stream cipher,
184 the decrypt function will always decrypt all of the supplied
185 ciphertext immediately. No cache will be kept.
187 XTS:
188 ----
189 Because the handling of the last two blocks is linked,
190 it needs the whole block of ciphertext to be supplied at once.
191 Every decrypt function called on a XTS cipher will output
192 a decrypted block based on the current supplied ciphertext block.
194 CMAC:
195 -----
196 Mode not supported for decryption as this does not make sense.
198 #self.ed = 'e' if chain is encrypting, 'd' if decrypting,
199 # None if nothing happened with the chain yet
200 #assert self.ed in ('d',None)
201 # makes sure you don't decrypt with a cipher that has started encrypting
202 self.ed = 'd'
203 if self.mode == MODE_XTS:
204 # data sequence number (or 'tweak') has to be provided when in XTS mode
205 return self.chain.update(ciphertext,'d',n)
206 else:
207 return self.chain.update(ciphertext,'d')
209 def final(self,padding='PKCS7'):
210 # TODO: after calling final, reset the IV? so the cipher is as good as new?
211 """Finalizes the encryption by padding the cache
213 padding = padding function provided as an argument. Possible padding functions:
214 - 'zerosPadding'
215 - 'bitPadding'
216 - 'PKCS7' (default)
217 - 'ANSI_X923'
218 - 'ISO_10126'
220 While a cipher object is in encryption mode, the final function will pad the remaining cache and encrypt it.
221 If the cipher has been used for decryption, the final function won't do antyhing. You have to manually unpad if necessary or
222 construct a Padder yourself en use its unpad function.
224 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).
226 assert self.mode not in (MODE_XTS, MODE_CMAC) # finalizing (=padding) doesn't make sense when in XTS or CMAC mode
227 if self.ed == 'e':
228 # when the chain is in encryption mode, finalizing will pad the cache and encrypt this last block
229 padder = Padding(self.blocksize)
230 if self.mode in (MODE_OFB,MODE_CFB,MODE_CTR):
231 dummy = '0'*(self.blocksize - self.chain.keystream.buffer_info()[1]) # a dummy string that will be used to get a valid padding
232 else: #ECB, CBC
233 dummy = self.chain.cache
234 return self.chain.update(padder.pad(dummy,padding)[len(dummy):],'e') # pad the cache and then only supply the padding to the update function
235 else:
236 # final function doesn't make sense when decrypting => padding should be removed manually
237 pass
239 class ECB:
240 """ECB chaining mode
242 def __init__(self, codebook, blocksize):
243 self.cache = ''
244 self.codebook = codebook
245 self.blocksize = blocksize
247 def update(self, data, ed):
248 """Processes the given ciphertext/plaintext
250 Inputs:
251 data: raw string of any length
252 ed: 'e' for encryption, 'd' for decryption
253 Output:
254 processed raw string block(s), if any
256 When the supplied data is not a multiple of the blocksize
257 of the cipher, then the remaining input data will be cached.
258 The next time the update function is called with some data,
259 the new data will be concatenated to the cache and then
260 cache+data will be processed and full blocks will be outputted.
262 output_blocks = []
263 self.cache += data
264 if len(self.cache) < self.blocksize:
265 return ''
266 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
267 #the only difference between encryption/decryption in the chain is the cipher block
268 if ed == 'e':
269 output_blocks.append(self.codebook.encrypt( self.cache[i:i + self.blocksize] ))
270 else:
271 output_blocks.append(self.codebook.decrypt( self.cache[i:i + self.blocksize] ))
272 self.cache = self.cache[i+self.blocksize:]
273 return ''.join(output_blocks)
275 class CBC:
276 """CBC chaining mode
278 def __init__(self, codebook, blocksize, IV):
279 self.IV = IV
280 self.cache = ''
281 self.codebook = codebook
282 self.blocksize = blocksize
284 def update(self, data, ed):
285 """Processes the given ciphertext/plaintext
287 Inputs:
288 data: raw string of any length
289 ed: 'e' for encryption, 'd' for decryption
290 Output:
291 processed raw string block(s), if any
293 When the supplied data is not a multiple of the blocksize
294 of the cipher, then the remaining input data will be cached.
295 The next time the update function is called with some data,
296 the new data will be concatenated to the cache and then
297 cache+data will be processed and full blocks will be outputted.
299 if ed == 'e':
300 encrypted_blocks = ''
301 self.cache += data
302 if len(self.cache) < self.blocksize:
303 return ''
304 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
305 self.IV = self.codebook.encrypt(util.xorstring(self.cache[i:i+self.blocksize],self.IV))
306 encrypted_blocks += self.IV
307 self.cache = self.cache[i+self.blocksize:]
308 return encrypted_blocks
309 else:
310 decrypted_blocks = ''
311 self.cache += data
312 if len(self.cache) < self.blocksize:
313 return ''
314 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
315 plaintext = util.xorstring(self.IV,self.codebook.decrypt(self.cache[i:i + self.blocksize]))
316 self.IV = self.cache[i:i + self.blocksize]
317 decrypted_blocks+=plaintext
318 self.cache = self.cache[i+self.blocksize:]
319 return decrypted_blocks
321 class CFB:
322 """CFB Chaining Mode
324 Can be accessed as a stream cipher.
327 def __init__(self, codebook, blocksize, IV):
328 self.codebook = codebook
329 self.IV = IV
330 self.blocksize = blocksize
331 self.keystream =array('B', '')
332 def update(self, data, ed):
333 """Processes the given ciphertext/plaintext
335 Inputs:
336 data: raw string of any multiple of bytes
337 ed: 'e' for encryption, 'd' for decryption
338 Output:
339 processed raw string
341 The encrypt/decrypt functions will always process all of the supplied
342 input data immediately. No cache will be kept.
344 n = len(data)
345 blocksize = self.blocksize
346 output = array('B', data)
348 for i in xrange(n):
349 if ed =='e':
350 if self.keystream.buffer_info()[1] == 0:
351 block = self.codebook.encrypt(self.IV)
352 self.keystream = array('B', block)
353 self.IV = ''
354 output[i] ^= self.keystream.pop(0)
355 self.IV += chr(output[i]) # the IV for the next block in the chain is being built byte per byte as the ciphertext flows in
356 else:
357 if self.keystream.buffer_info()[1] == 0:
358 block = self.codebook.encrypt(self.IV)
359 self.keystream = array('B', block)
360 self.IV = ''
361 self.IV += chr(output[i])
362 output[i] ^= self.keystream.pop(0)
363 return output.tostring()
365 class OFB:
366 """OFB Chaining Mode
368 Can be accessed as a stream cipher.
370 def __init__(self, codebook, blocksize, IV):
371 self.codebook = codebook
372 self.IV = IV
373 self.blocksize = blocksize
374 self.keystream =array('B', '')
375 def update(self, data, ed):
376 """Processes the given ciphertext/plaintext
378 Inputs:
379 data: raw string of any multiple of bytes
380 ed: 'e' for encryption, 'd' for decryption
381 Output:
382 processed raw string
384 The encrypt/decrypt functions will always process all of the supplied
385 input data immediately. No cache will be kept.
387 #no difference between encryption and decryption mode
388 n = len(data)
389 blocksize = self.blocksize
390 output = array('B', data)
392 for i in xrange(n):
393 if self.keystream.buffer_info()[1] == 0: #encrypt a new counter block when the current keystream is fully used
394 self.IV = self.codebook.encrypt(self.IV)
395 self.keystream = array('B', self.IV)
396 output[i] ^= self.keystream.pop(0) #as long as an encrypted counter value is available, the output is just "input XOR keystream"
397 return output.tostring()
399 class CTR:
400 """CTR Chaining Mode
402 Can be accessed as a stream cipher.
404 # initial counter value can be choosen, decryption always starts from beginning
405 # -> you can start from anywhere yourself: just feed the cipher encoded blocks and feed a counter with the corresponding value
406 def __init__(self, codebook, blocksize, counter):
407 self.codebook = codebook
408 self.counter = counter
409 self.blocksize = blocksize
410 self.keystream =array('B', '') #holds the output of the current encrypted counter value
412 def update(self, data, ed):
413 """Processes the given ciphertext/plaintext
415 Inputs:
416 data: raw string of any multiple of bytes
417 ed: 'e' for encryption, 'd' for decryption
418 Output:
419 processed raw string
421 The encrypt/decrypt functions will always process all of the supplied
422 input data immediately. No cache will be kept.
424 # no need for the encryption/decryption distinction: both are the same
425 n = len(data)
426 blocksize = self.blocksize
428 output = array('B', data)
429 for i in xrange(n):
430 if self.keystream.buffer_info()[1] == 0: #encrypt a new counter block when the current keystream is fully used
431 block = self.codebook.encrypt(self.counter())
432 self.keystream = array('B', block)
433 output[i] ^= self.keystream.pop(0) #as long as an encrypted counter value is available, the output is just "input XOR keystream"
434 return output.tostring()
436 class XTS:
437 """XTS Chaining Mode
439 # TODO: allow other blocksizes besides 16bytes?
440 def __init__(self,codebook1, codebook2):
441 self.cache = ''
442 self.codebook1 = codebook1
443 self.codebook2 = codebook2
445 def update(self, data, ed,tweak=''):
446 # supply n as a raw string
447 # tweak = data sequence number
448 """Perform a XTS encrypt/decrypt operation.
450 Because the handling of the last two blocks is linked,
451 it needs the whole block of ciphertext to be supplied at once.
452 Every decrypt function called on a XTS cipher will output
453 a decrypted block based on the current supplied ciphertext block.
455 output = ''
456 assert len(data) > 15, "At least one block of 128 bits needs to be supplied"
457 assert len(data) < 128*pow(2,20)
459 # initializing T
460 # e_k2_n = E_K2(tweak)
461 e_k2_n = self.codebook2.encrypt(tweak+ '\x00' * (16-len(tweak)))[::-1]
462 self.T = util.string2number(e_k2_n)
465 while i < ((len(data) // 16)-1): #Decrypt all the blocks but one last full block and opt one last partial block
466 # C = E_K1(P xor T) xor T
467 output += self.__xts_step(ed,data[i*16:(i+1)*16],self.T)
468 # T = E_K2(n) mul (a pow i)
469 self.__T_update()
470 i+=1
472 # Check if the data supplied is a multiple of 16 bytes -> one last full block and we're done
473 if len(data[i*16:]) == 16:
474 # C = E_K1(P xor T) xor T
475 output += self.__xts_step(ed,data[i*16:(i+1)*16],self.T)
476 # T = E_K2(n) mul (a pow i)
477 self.__T_update()
478 else:
479 T_temp = [self.T]
480 self.__T_update()
481 T_temp.append(self.T)
482 if ed=='d':
483 # Permutation of the last two indexes
484 T_temp.reverse()
485 # Decrypt/Encrypt the last two blocks when data is not a multiple of 16 bytes
486 Cm1 = data[i*16:(i+1)*16]
487 Cm = data[(i+1)*16:]
488 PP = self.__xts_step(ed,Cm1,T_temp[0])
489 Cp = PP[len(Cm):]
490 Pm = PP[:len(Cm)]
491 CC = Cm+Cp
492 Pm1 = self.__xts_step(ed,CC,T_temp[1])
493 output += Pm1 + Pm
494 return output
496 def __xts_step(self,ed,tocrypt,T):
497 T_string = util.number2string_N(T,16)[::-1]
498 # C = E_K1(P xor T) xor T
499 if ed == 'd':
500 return util.xorstring(T_string, self.codebook1.decrypt(util.xorstring(T_string, tocrypt)))
501 else:
502 return util.xorstring(T_string, self.codebook1.encrypt(util.xorstring(T_string, tocrypt)))
504 def __T_update(self):
505 # Used for calculating T for a certain step using the T value from the previous step
506 self.T = self.T << 1
507 # if (Cout)
508 if self.T >> (8*16):
509 #T[0] ^= GF_128_FDBK;
510 self.T = self.T ^ 0x100000000000000000000000000000087L
513 class CMAC:
514 """CMAC chaining mode
516 Supports every cipher with a blocksize available
517 in the list CMAC.supported_blocksizes.
518 The hashlength is equal to block size of the used block cipher.
520 # TODO: move to hash module?
521 # TODO: change update behaviour to .update() and .digest() as for all hash modules?
522 # -> other hash functions in pycrypto: calling update, concatenates current input with previous input and hashes everything
523 __Rb_dictionary = {64:0x000000000000001b,128:0x00000000000000000000000000000087}
524 supported_blocksizes = __Rb_dictionary.keys()
525 def __init__(self,codebook,blocksize):
526 # Purpose of init: calculate Lu & Lu2
527 #blocksize (in bytes): to select the Rb constant in the dictionary
528 #Rb as a dictionary: adding support for other blocksizes is easy
529 self.cache=''
530 self.blocksize = blocksize
531 self.codebook = codebook
533 #Rb_dictionary: holds values for Rb for different blocksizes
534 # values for 64 and 128 bits found here: http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
535 # explanation from: http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
536 # Rb is a representation of a certain irreducible binary polynomial of degree b, namely,
537 # the lexicographically first among all such polynomials with the minimum possible number of
538 # nonzero terms. If this polynomial is expressed as ub+cb-1ub-1+...+c2u2+c1u+c0, where the
539 # coefficients cb-1, cb-2, ..., c2, c1, c0 are either 0 or 1, then Rb is the bit string cb-1cb-2...c2c1c0.
541 self.Rb = self.__Rb_dictionary[blocksize*8]
543 mask1 = int(('\xff'*blocksize).encode('hex'),16)
544 mask2 = int(('\x80' + '\x00'*(blocksize-1) ).encode('hex'),16)
546 L = int(self.codebook.encrypt('\x00'*blocksize).encode('hex'),16)
548 if L & mask2:
549 Lu = ((L << 1) & mask1) ^ self.Rb
550 else:
551 Lu = L << 1
552 Lu = Lu & mask1
554 if Lu & mask2:
555 Lu2 = ((Lu << 1) & mask1)^ self.Rb
556 else:
557 Lu2 = Lu << 1
558 Lu2 = Lu2 & mask1
560 self.Lu =util.number2string_N(Lu,self.blocksize)
561 self.Lu2=util.number2string_N(Lu2,self.blocksize)
563 def update(self, data, ed):
564 """Processes the given ciphertext/plaintext
566 Inputs:
567 data: raw string of any length
568 ed: 'e' for encryption, 'd' for decryption
569 Output:
570 hashed data as raw string
572 This is not really an update function:
573 Everytime the function is called, the hash from the input data is calculated.
574 No finalizing needed.
576 assert ed == 'e'
577 blocksize = self.blocksize
579 m = (len(data)+blocksize-1)/blocksize #m = amount of datablocks
580 y = '\x00'*blocksize
582 for i in range(1,m):
583 y = self.codebook.encrypt( util.xorstring(data[(i-1)*blocksize:(i)*blocksize],y) )
585 if len(data[(i)*blocksize:])==blocksize:
586 X = util.xorstring(util.xorstring(data[(i)*blocksize:],y),self.Lu)
587 else:
588 tmp = data[(i)*blocksize:] + '\x80' + '\x00'*(blocksize - len(data[(i)*blocksize:])-1)
589 X = util.xorstring(util.xorstring(tmp,y),self.Lu2)
591 T = self.codebook.encrypt(X)
592 return T