blockcipher.py: updated docstring of final()
[python-cryptoplus.git] / src / CryptoPlus / Cipher / blockcipher.py
blobf337eb7fcbbcfdb9d4f0b015ea420306f98ce784
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 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,segment_size,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 IV == None:
55 self.IV = '\x00'*16
56 else:
57 self.IV = IV
59 if mode <> MODE_XTS:
60 self.cipher = cipher_module(self.key,**args)
61 if mode == MODE_ECB:
62 self.chain = ECB(self.cipher, self.blocksize)
63 elif mode == MODE_CBC:
64 if len(self.IV) <> self.blocksize:
65 raise Exception,"the IV length should be %i bytes"%self.blocksize
66 self.chain = CBC(self.cipher, self.blocksize,self.IV)
67 elif mode == MODE_CFB:
68 if len(self.IV) <> self.blocksize:
69 raise Exception,"the IV length should be %i bytes"%self.blocksize
70 if segment_size > self.blocksize*8 or segment_size%8 <> 0:
71 # current CFB implementation doesn't support bit level acces => segment_size should be multiple of bytes
72 raise ValueError,"segment size should be a multiple of 8 bits between 1 and %i"%(self.blocksize*8)
73 self.chain = CFB(self.cipher, self.blocksize,self.IV,segment_size)
74 elif mode == MODE_OFB:
75 if len(self.IV) <> self.blocksize:
76 raise ValueError("the IV length should be %i bytes"%self.blocksize)
77 self.chain = OFB(self.cipher, self.blocksize,self.IV)
78 elif mode == MODE_CTR:
79 if (counter == None) or not callable(counter):
80 raise Exception,"Supply a valid counter object for the CTR mode"
81 self.chain = CTR(self.cipher,self.blocksize,counter)
82 elif mode == MODE_XTS:
83 if self.blocksize <> 16:
84 raise Exception,'XTS only works with blockcipher that have a 128-bit blocksize'
85 if not(type(key) == tuple and len(key) == 2):
86 raise Exception,'Supply two keys as a tuple when using XTS'
87 if 'keylen_valid' in dir(self): #wrappers for pycrypto functions don't have this function
88 if not self.keylen_valid(key[0]) or not self.keylen_valid(key[1]):
89 raise ValueError(self.key_error_message)
90 self.cipher = cipher_module(self.key[0],**args)
91 self.cipher2 = cipher_module(self.key[1],**args)
92 self.chain = XTS(self.cipher, self.cipher2)
93 elif mode == MODE_CMAC:
94 if self.blocksize not in (8,16):
95 raise Exception,'CMAC only works with blockcipher that have a 64 or 128-bit blocksize'
96 self.chain = CMAC(self.cipher,self.blocksize)
97 else:
98 raise Exception,"Unknown chaining mode!"
100 def encrypt(self,plaintext,n=''):
101 """Encrypt some plaintext
103 plaintext = a string of binary data
104 n = the 'tweak' value when the chaining mode is XTS
106 The encrypt function will encrypt the supplied plaintext.
107 The behavior varies slightly depending on the chaining mode.
109 ECB, CBC:
110 ---------
111 When the supplied plaintext is not a multiple of the blocksize
112 of the cipher, then the remaining plaintext will be cached.
113 The next time the encrypt function is called with some plaintext,
114 the new plaintext will be concatenated to the cache and then
115 cache+plaintext will be encrypted.
117 CFB, OFB, CTR:
118 --------------
119 When the chaining mode allows the cipher to act as a stream cipher,
120 the encrypt function will always encrypt all of the supplied
121 plaintext immediately. No cache will be kept.
123 XTS:
124 ----
125 Because the handling of the last two blocks is linked,
126 it needs the whole block of plaintext to be supplied at once.
127 Every encrypt function called on a XTS cipher will output
128 an encrypted block based on the current supplied plaintext block.
130 CMAC:
131 -----
132 Everytime the function is called, the hash from the input data is calculated.
133 No finalizing needed.
134 The hashlength is equal to block size of the used block cipher.
136 #self.ed = 'e' if chain is encrypting, 'd' if decrypting,
137 # None if nothing happened with the chain yet
138 #assert self.ed in ('e',None)
139 # makes sure you don't encrypt with a cipher that has started decrypting
140 self.ed = 'e'
141 if self.mode == MODE_XTS:
142 # data sequence number (or 'tweak') has to be provided when in XTS mode
143 return self.chain.update(plaintext,'e',n)
144 else:
145 return self.chain.update(plaintext,'e')
147 def decrypt(self,ciphertext,n=''):
148 """Decrypt some ciphertext
150 ciphertext = a string of binary data
151 n = the 'tweak' value when the chaining mode is XTS
153 The decrypt function will decrypt the supplied ciphertext.
154 The behavior varies slightly depending on the chaining mode.
156 ECB, CBC:
157 ---------
158 When the supplied ciphertext is not a multiple of the blocksize
159 of the cipher, then the remaining ciphertext will be cached.
160 The next time the decrypt function is called with some ciphertext,
161 the new ciphertext will be concatenated to the cache and then
162 cache+ciphertext will be decrypted.
164 CFB, OFB, CTR:
165 --------------
166 When the chaining mode allows the cipher to act as a stream cipher,
167 the decrypt function will always decrypt all of the supplied
168 ciphertext immediately. No cache will be kept.
170 XTS:
171 ----
172 Because the handling of the last two blocks is linked,
173 it needs the whole block of ciphertext to be supplied at once.
174 Every decrypt function called on a XTS cipher will output
175 a decrypted block based on the current supplied ciphertext block.
177 CMAC:
178 -----
179 Mode not supported for decryption as this does not make sense.
181 #self.ed = 'e' if chain is encrypting, 'd' if decrypting,
182 # None if nothing happened with the chain yet
183 #assert self.ed in ('d',None)
184 # makes sure you don't decrypt with a cipher that has started encrypting
185 self.ed = 'd'
186 if self.mode == MODE_XTS:
187 # data sequence number (or 'tweak') has to be provided when in XTS mode
188 return self.chain.update(ciphertext,'d',n)
189 else:
190 return self.chain.update(ciphertext,'d')
192 def final(self,padfct=padding.PKCS7):
193 # TODO: after calling final, reset the IV? so the cipher is as good as new?
194 """Finalizes the encryption by padding the cache
196 padfct = padding function
197 import from CryptoPlus.Util.padding
199 For ECB, CBC: the remaining bytes in the cache will be padded and
200 encrypted.
201 For OFB,CFB, CTR: an encrypted padding will be returned, making the
202 total outputed bytes since construction of the cipher
203 a multiple of the blocksize of that cipher.
205 If the cipher has been used for decryption, the final function won't do
206 antyhing. You have to manually unpad if necessary.
208 After finalization, the chain can still be used but the IV, counter etc
209 aren't reset but just continu as they were after the last step (finalization step).
211 assert self.mode not in (MODE_XTS, MODE_CMAC) # finalizing (=padding) doesn't make sense when in XTS or CMAC mode
212 if self.ed == 'e':
213 # when the chain is in encryption mode, finalizing will pad the cache and encrypt this last block
214 if self.mode in (MODE_OFB,MODE_CFB,MODE_CTR):
215 dummy = '0'*(self.blocksize - self.chain.keystream.buffer_info()[1]) # a dummy string that will be used to get a valid padding
216 else: #ECB, CBC
217 dummy = self.chain.cache
218 return self.chain.update(padfct(dummy,padding.PAD,self.blocksize)[len(dummy):],'e') # pad the cache and then only supply the padding to the update function
219 else:
220 # final function doesn't make sense when decrypting => padding should be removed manually
221 pass
223 class ECB:
224 """ECB chaining mode
226 def __init__(self, codebook, blocksize):
227 self.cache = ''
228 self.codebook = codebook
229 self.blocksize = blocksize
231 def update(self, data, ed):
232 """Processes the given ciphertext/plaintext
234 Inputs:
235 data: raw string of any length
236 ed: 'e' for encryption, 'd' for decryption
237 Output:
238 processed raw string block(s), if any
240 When the supplied data is not a multiple of the blocksize
241 of the cipher, then the remaining input data will be cached.
242 The next time the update function is called with some data,
243 the new data will be concatenated to the cache and then
244 cache+data will be processed and full blocks will be outputted.
246 output_blocks = []
247 self.cache += data
248 if len(self.cache) < self.blocksize:
249 return ''
250 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
251 #the only difference between encryption/decryption in the chain is the cipher block
252 if ed == 'e':
253 output_blocks.append(self.codebook.encrypt( self.cache[i:i + self.blocksize] ))
254 else:
255 output_blocks.append(self.codebook.decrypt( self.cache[i:i + self.blocksize] ))
256 self.cache = self.cache[i+self.blocksize:]
257 return ''.join(output_blocks)
259 class CBC:
260 """CBC chaining mode
262 def __init__(self, codebook, blocksize, IV):
263 self.IV = IV
264 self.cache = ''
265 self.codebook = codebook
266 self.blocksize = blocksize
268 def update(self, data, ed):
269 """Processes the given ciphertext/plaintext
271 Inputs:
272 data: raw string of any length
273 ed: 'e' for encryption, 'd' for decryption
274 Output:
275 processed raw string block(s), if any
277 When the supplied data is not a multiple of the blocksize
278 of the cipher, then the remaining input data will be cached.
279 The next time the update function is called with some data,
280 the new data will be concatenated to the cache and then
281 cache+data will be processed and full blocks will be outputted.
283 if ed == 'e':
284 encrypted_blocks = ''
285 self.cache += data
286 if len(self.cache) < self.blocksize:
287 return ''
288 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
289 self.IV = self.codebook.encrypt(util.xorstring(self.cache[i:i+self.blocksize],self.IV))
290 encrypted_blocks += self.IV
291 self.cache = self.cache[i+self.blocksize:]
292 return encrypted_blocks
293 else:
294 decrypted_blocks = ''
295 self.cache += data
296 if len(self.cache) < self.blocksize:
297 return ''
298 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
299 plaintext = util.xorstring(self.IV,self.codebook.decrypt(self.cache[i:i + self.blocksize]))
300 self.IV = self.cache[i:i + self.blocksize]
301 decrypted_blocks+=plaintext
302 self.cache = self.cache[i+self.blocksize:]
303 return decrypted_blocks
305 class CFB:
306 # TODO: bit access instead of only byte level access
307 """CFB Chaining Mode
309 Can be accessed as a stream cipher.
312 def __init__(self, codebook, blocksize, IV,segment_size):
313 self.codebook = codebook
314 self.IV = IV
315 self.blocksize = blocksize
316 self.segment_size = segment_size/8
317 self.keystream = []
319 def update(self, data, ed):
320 """Processes the given ciphertext/plaintext
322 Inputs:
323 data: raw string of any multiple of bytes
324 ed: 'e' for encryption, 'd' for decryption
325 Output:
326 processed raw string
328 The encrypt/decrypt functions will always process all of the supplied
329 input data immediately. No cache will be kept.
331 output = list(data)
333 for i in xrange(len(data)):
334 if ed =='e':
335 if len(self.keystream) == 0:
336 block = self.codebook.encrypt(self.IV)
337 self.keystream = list(block)[:self.segment_size] # keystream consists of the s MSB's
338 self.IV = self.IV[self.segment_size:] # keeping (b-s) LSB's
339 output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0)))
340 self.IV += output[i] # the IV for the next block in the chain is being built byte per byte as the ciphertext flows in
341 else:
342 if len(self.keystream) == 0:
343 block = self.codebook.encrypt(self.IV)
344 self.keystream = list(block)[:self.segment_size]
345 self.IV = self.IV[self.segment_size:]
346 self.IV += output[i]
347 output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0)))
348 return ''.join(output)
350 class OFB:
351 """OFB Chaining Mode
353 Can be accessed as a stream cipher.
355 def __init__(self, codebook, blocksize, IV):
356 self.codebook = codebook
357 self.IV = IV
358 self.blocksize = blocksize
359 self.keystream = []
360 def update(self, data, ed):
361 """Processes the given ciphertext/plaintext
363 Inputs:
364 data: raw string of any multiple of bytes
365 ed: 'e' for encryption, 'd' for decryption
366 Output:
367 processed raw string
369 The encrypt/decrypt functions will always process all of the supplied
370 input data immediately. No cache will be kept.
372 #no difference between encryption and decryption mode
373 n = len(data)
374 blocksize = self.blocksize
375 output = list(data)
377 for i in xrange(n):
378 if len(self.keystream) == 0: #encrypt a new counter block when the current keystream is fully used
379 self.IV = self.codebook.encrypt(self.IV)
380 self.keystream = list(self.IV)
381 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"
382 return ''.join(output)
384 class CTR:
385 """CTR Chaining Mode
387 Can be accessed as a stream cipher.
389 # initial counter value can be choosen, decryption always starts from beginning
390 # -> you can start from anywhere yourself: just feed the cipher encoded blocks and feed a counter with the corresponding value
391 def __init__(self, codebook, blocksize, counter):
392 self.codebook = codebook
393 self.counter = counter
394 self.blocksize = blocksize
395 self.keystream = [] #holds the output of the current encrypted counter value
397 def update(self, data, ed):
398 """Processes the given ciphertext/plaintext
400 Inputs:
401 data: raw string of any multiple of bytes
402 ed: 'e' for encryption, 'd' for decryption
403 Output:
404 processed raw string
406 The encrypt/decrypt functions will always process all of the supplied
407 input data immediately. No cache will be kept.
409 # no need for the encryption/decryption distinction: both are the same
410 n = len(data)
411 blocksize = self.blocksize
413 output = list(data)
414 for i in xrange(n):
415 if len(self.keystream) == 0: #encrypt a new counter block when the current keystream is fully used
416 block = self.codebook.encrypt(self.counter())
417 self.keystream = list(block)
418 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"
419 return ''.join(output)
421 class XTS:
422 """XTS Chaining Mode
424 # TODO: allow other blocksizes besides 16bytes?
425 def __init__(self,codebook1, codebook2):
426 self.cache = ''
427 self.codebook1 = codebook1
428 self.codebook2 = codebook2
430 def update(self, data, ed,tweak=''):
431 # supply n as a raw string
432 # tweak = data sequence number
433 """Perform a XTS encrypt/decrypt operation.
435 Because the handling of the last two blocks is linked,
436 it needs the whole block of ciphertext to be supplied at once.
437 Every decrypt function called on a XTS cipher will output
438 a decrypted block based on the current supplied ciphertext block.
440 output = ''
441 assert len(data) > 15, "At least one block of 128 bits needs to be supplied"
442 assert len(data) < 128*pow(2,20)
444 # initializing T
445 # e_k2_n = E_K2(tweak)
446 e_k2_n = self.codebook2.encrypt(tweak+ '\x00' * (16-len(tweak)))[::-1]
447 self.T = util.string2number(e_k2_n)
450 while i < ((len(data) // 16)-1): #Decrypt all the blocks but one last full block and opt one last partial block
451 # C = E_K1(P xor T) xor T
452 output += self.__xts_step(ed,data[i*16:(i+1)*16],self.T)
453 # T = E_K2(n) mul (a pow i)
454 self.__T_update()
455 i+=1
457 # Check if the data supplied is a multiple of 16 bytes -> one last full block and we're done
458 if len(data[i*16:]) == 16:
459 # C = E_K1(P xor T) xor T
460 output += self.__xts_step(ed,data[i*16:(i+1)*16],self.T)
461 # T = E_K2(n) mul (a pow i)
462 self.__T_update()
463 else:
464 T_temp = [self.T]
465 self.__T_update()
466 T_temp.append(self.T)
467 if ed=='d':
468 # Permutation of the last two indexes
469 T_temp.reverse()
470 # Decrypt/Encrypt the last two blocks when data is not a multiple of 16 bytes
471 Cm1 = data[i*16:(i+1)*16]
472 Cm = data[(i+1)*16:]
473 PP = self.__xts_step(ed,Cm1,T_temp[0])
474 Cp = PP[len(Cm):]
475 Pm = PP[:len(Cm)]
476 CC = Cm+Cp
477 Pm1 = self.__xts_step(ed,CC,T_temp[1])
478 output += Pm1 + Pm
479 return output
481 def __xts_step(self,ed,tocrypt,T):
482 T_string = util.number2string_N(T,16)[::-1]
483 # C = E_K1(P xor T) xor T
484 if ed == 'd':
485 return util.xorstring(T_string, self.codebook1.decrypt(util.xorstring(T_string, tocrypt)))
486 else:
487 return util.xorstring(T_string, self.codebook1.encrypt(util.xorstring(T_string, tocrypt)))
489 def __T_update(self):
490 # Used for calculating T for a certain step using the T value from the previous step
491 self.T = self.T << 1
492 # if (Cout)
493 if self.T >> (8*16):
494 #T[0] ^= GF_128_FDBK;
495 self.T = self.T ^ 0x100000000000000000000000000000087L
498 class CMAC:
499 """CMAC chaining mode
501 Supports every cipher with a blocksize available
502 in the list CMAC.supported_blocksizes.
503 The hashlength is equal to block size of the used block cipher.
505 # TODO: move to hash module?
506 # TODO: change update behaviour to .update() and .digest() as for all hash modules?
507 # -> other hash functions in pycrypto: calling update, concatenates current input with previous input and hashes everything
508 __Rb_dictionary = {64:0x000000000000001b,128:0x00000000000000000000000000000087}
509 supported_blocksizes = __Rb_dictionary.keys()
510 def __init__(self,codebook,blocksize):
511 # Purpose of init: calculate Lu & Lu2
512 #blocksize (in bytes): to select the Rb constant in the dictionary
513 #Rb as a dictionary: adding support for other blocksizes is easy
514 self.cache=''
515 self.blocksize = blocksize
516 self.codebook = codebook
518 #Rb_dictionary: holds values for Rb for different blocksizes
519 # values for 64 and 128 bits found here: http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
520 # explanation from: http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
521 # Rb is a representation of a certain irreducible binary polynomial of degree b, namely,
522 # the lexicographically first among all such polynomials with the minimum possible number of
523 # nonzero terms. If this polynomial is expressed as ub+cb-1ub-1+...+c2u2+c1u+c0, where the
524 # coefficients cb-1, cb-2, ..., c2, c1, c0 are either 0 or 1, then Rb is the bit string cb-1cb-2...c2c1c0.
526 self.Rb = self.__Rb_dictionary[blocksize*8]
528 mask1 = int(('\xff'*blocksize).encode('hex'),16)
529 mask2 = int(('\x80' + '\x00'*(blocksize-1) ).encode('hex'),16)
531 L = int(self.codebook.encrypt('\x00'*blocksize).encode('hex'),16)
533 if L & mask2:
534 Lu = ((L << 1) & mask1) ^ self.Rb
535 else:
536 Lu = L << 1
537 Lu = Lu & mask1
539 if Lu & mask2:
540 Lu2 = ((Lu << 1) & mask1)^ self.Rb
541 else:
542 Lu2 = Lu << 1
543 Lu2 = Lu2 & mask1
545 self.Lu =util.number2string_N(Lu,self.blocksize)
546 self.Lu2=util.number2string_N(Lu2,self.blocksize)
548 def update(self, data, ed):
549 """Processes the given ciphertext/plaintext
551 Inputs:
552 data: raw string of any length
553 ed: 'e' for encryption, 'd' for decryption
554 Output:
555 hashed data as raw string
557 This is not really an update function:
558 Everytime the function is called, the hash from the input data is calculated.
559 No finalizing needed.
561 assert ed == 'e'
562 blocksize = self.blocksize
564 m = (len(data)+blocksize-1)/blocksize #m = amount of datablocks
565 y = '\x00'*blocksize
567 for i in range(1,m):
568 y = self.codebook.encrypt( util.xorstring(data[(i-1)*blocksize:(i)*blocksize],y) )
570 if len(data[(i)*blocksize:])==blocksize:
571 X = util.xorstring(util.xorstring(data[(i)*blocksize:],y),self.Lu)
572 else:
573 tmp = data[(i)*blocksize:] + '\x80' + '\x00'*(blocksize - len(data[(i)*blocksize:])-1)
574 X = util.xorstring(util.xorstring(tmp,y),self.Lu2)
576 T = self.codebook.encrypt(X)
577 return T