No more arbitrary default value for segment_size in CFB mode (thanks Adam Laurie)
[python-cryptoplus.git] / src / CryptoPlus / Cipher / blockcipher.py
blobb7b10d91dd1af2b396a211ebec1cdf510849fcd8
1 # =============================================================================
2 # Copyright (c) 2008 Christophe Oosterlynck <christophe.oosterlynck_AT_gmail.com>
3 # & NXP ( Philippe Teuwen <philippe.teuwen_AT_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'*self.blocksize
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 == None:
71 raise ValueError,"segment size must be defined explicitely for CFB mode"
72 if segment_size > self.blocksize*8 or segment_size%8 <> 0:
73 # current CFB implementation doesn't support bit level acces => segment_size should be multiple of bytes
74 raise ValueError,"segment size should be a multiple of 8 bits between 8 and %i"%(self.blocksize*8)
75 self.chain = CFB(self.cipher, self.blocksize,self.IV,segment_size)
76 elif mode == MODE_OFB:
77 if len(self.IV) <> self.blocksize:
78 raise ValueError("the IV length should be %i bytes"%self.blocksize)
79 self.chain = OFB(self.cipher, self.blocksize,self.IV)
80 elif mode == MODE_CTR:
81 if (counter == None) or not callable(counter):
82 raise Exception,"Supply a valid counter object for the CTR mode"
83 self.chain = CTR(self.cipher,self.blocksize,counter)
84 elif mode == MODE_XTS:
85 if self.blocksize <> 16:
86 raise Exception,'XTS only works with blockcipher that have a 128-bit blocksize'
87 if not(type(key) == tuple and len(key) == 2):
88 raise Exception,'Supply two keys as a tuple when using XTS'
89 if 'keylen_valid' in dir(self): #wrappers for pycrypto functions don't have this function
90 if not self.keylen_valid(key[0]) or not self.keylen_valid(key[1]):
91 raise ValueError(self.key_error_message)
92 self.cipher = cipher_module(self.key[0],**args)
93 self.cipher2 = cipher_module(self.key[1],**args)
94 self.chain = XTS(self.cipher, self.cipher2)
95 elif mode == MODE_CMAC:
96 if self.blocksize not in (8,16):
97 raise Exception,'CMAC only works with blockcipher that have a 64 or 128-bit blocksize'
98 self.chain = CMAC(self.cipher,self.blocksize,self.IV)
99 else:
100 raise Exception,"Unknown chaining mode!"
102 def encrypt(self,plaintext,n=''):
103 """Encrypt some plaintext
105 plaintext = a string of binary data
106 n = the 'tweak' value when the chaining mode is XTS
108 The encrypt function will encrypt the supplied plaintext.
109 The behavior varies slightly depending on the chaining mode.
111 ECB, CBC:
112 ---------
113 When the supplied plaintext is not a multiple of the blocksize
114 of the cipher, then the remaining plaintext will be cached.
115 The next time the encrypt function is called with some plaintext,
116 the new plaintext will be concatenated to the cache and then
117 cache+plaintext will be encrypted.
119 CFB, OFB, CTR:
120 --------------
121 When the chaining mode allows the cipher to act as a stream cipher,
122 the encrypt function will always encrypt all of the supplied
123 plaintext immediately. No cache will be kept.
125 XTS:
126 ----
127 Because the handling of the last two blocks is linked,
128 it needs the whole block of plaintext to be supplied at once.
129 Every encrypt function called on a XTS cipher will output
130 an encrypted block based on the current supplied plaintext block.
132 CMAC:
133 -----
134 Everytime the function is called, the hash from the input data is calculated.
135 No finalizing needed.
136 The hashlength is equal to block size of the used block cipher.
138 #self.ed = 'e' if chain is encrypting, 'd' if decrypting,
139 # None if nothing happened with the chain yet
140 #assert self.ed in ('e',None)
141 # makes sure you don't encrypt with a cipher that has started decrypting
142 self.ed = 'e'
143 if self.mode == MODE_XTS:
144 # data sequence number (or 'tweak') has to be provided when in XTS mode
145 return self.chain.update(plaintext,'e',n)
146 else:
147 return self.chain.update(plaintext,'e')
149 def decrypt(self,ciphertext,n=''):
150 """Decrypt some ciphertext
152 ciphertext = a string of binary data
153 n = the 'tweak' value when the chaining mode is XTS
155 The decrypt function will decrypt the supplied ciphertext.
156 The behavior varies slightly depending on the chaining mode.
158 ECB, CBC:
159 ---------
160 When the supplied ciphertext is not a multiple of the blocksize
161 of the cipher, then the remaining ciphertext will be cached.
162 The next time the decrypt function is called with some ciphertext,
163 the new ciphertext will be concatenated to the cache and then
164 cache+ciphertext will be decrypted.
166 CFB, OFB, CTR:
167 --------------
168 When the chaining mode allows the cipher to act as a stream cipher,
169 the decrypt function will always decrypt all of the supplied
170 ciphertext immediately. No cache will be kept.
172 XTS:
173 ----
174 Because the handling of the last two blocks is linked,
175 it needs the whole block of ciphertext to be supplied at once.
176 Every decrypt function called on a XTS cipher will output
177 a decrypted block based on the current supplied ciphertext block.
179 CMAC:
180 -----
181 Mode not supported for decryption as this does not make sense.
183 #self.ed = 'e' if chain is encrypting, 'd' if decrypting,
184 # None if nothing happened with the chain yet
185 #assert self.ed in ('d',None)
186 # makes sure you don't decrypt with a cipher that has started encrypting
187 self.ed = 'd'
188 if self.mode == MODE_XTS:
189 # data sequence number (or 'tweak') has to be provided when in XTS mode
190 return self.chain.update(ciphertext,'d',n)
191 else:
192 return self.chain.update(ciphertext,'d')
194 def final(self,padfct=padding.PKCS7):
195 # TODO: after calling final, reset the IV? so the cipher is as good as new?
196 """Finalizes the encryption by padding the cache
198 padfct = padding function
199 import from CryptoPlus.Util.padding
201 For ECB, CBC: the remaining bytes in the cache will be padded and
202 encrypted.
203 For OFB,CFB, CTR: an encrypted padding will be returned, making the
204 total outputed bytes since construction of the cipher
205 a multiple of the blocksize of that cipher.
207 If the cipher has been used for decryption, the final function won't do
208 anything. You have to manually unpad if necessary.
210 After finalization, the chain can still be used but the IV, counter etc
211 aren't reset but just continue as they were after the last step (finalization step).
213 assert self.mode not in (MODE_XTS, MODE_CMAC) # finalizing (=padding) doesn't make sense when in XTS or CMAC mode
214 if self.ed == 'e':
215 # when the chain is in encryption mode, finalizing will pad the cache and encrypt this last block
216 if self.mode in (MODE_OFB,MODE_CFB,MODE_CTR):
217 dummy = '0'*(self.chain.totalbytes%self.blocksize) # a dummy string that will be used to get a valid padding
218 else: #ECB, CBC
219 dummy = self.chain.cache
220 pad = padfct(dummy,padding.PAD,self.blocksize)[len(dummy):] # construct the padding necessary
221 return self.chain.update(pad,'e') # supply the padding to the update function => chain cache will be "cache+padding"
222 else:
223 # final function doesn't make sense when decrypting => padding should be removed manually
224 pass
226 class ECB:
227 """ECB chaining mode
229 def __init__(self, codebook, blocksize):
230 self.cache = ''
231 self.codebook = codebook
232 self.blocksize = blocksize
234 def update(self, data, ed):
235 """Processes the given ciphertext/plaintext
237 Inputs:
238 data: raw string of any length
239 ed: 'e' for encryption, 'd' for decryption
240 Output:
241 processed raw string block(s), if any
243 When the supplied data is not a multiple of the blocksize
244 of the cipher, then the remaining input data will be cached.
245 The next time the update function is called with some data,
246 the new data will be concatenated to the cache and then
247 cache+data will be processed and full blocks will be outputted.
249 output_blocks = []
250 self.cache += data
251 if len(self.cache) < self.blocksize:
252 return ''
253 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
254 #the only difference between encryption/decryption in the chain is the cipher block
255 if ed == 'e':
256 output_blocks.append(self.codebook.encrypt( self.cache[i:i + self.blocksize] ))
257 else:
258 output_blocks.append(self.codebook.decrypt( self.cache[i:i + self.blocksize] ))
259 self.cache = self.cache[i+self.blocksize:]
260 return ''.join(output_blocks)
262 class CBC:
263 """CBC chaining mode
265 def __init__(self, codebook, blocksize, IV):
266 self.IV = IV
267 self.cache = ''
268 self.codebook = codebook
269 self.blocksize = blocksize
271 def update(self, data, ed):
272 """Processes the given ciphertext/plaintext
274 Inputs:
275 data: raw string of any length
276 ed: 'e' for encryption, 'd' for decryption
277 Output:
278 processed raw string block(s), if any
280 When the supplied data is not a multiple of the blocksize
281 of the cipher, then the remaining input data will be cached.
282 The next time the update function is called with some data,
283 the new data will be concatenated to the cache and then
284 cache+data will be processed and full blocks will be outputted.
286 if ed == 'e':
287 encrypted_blocks = ''
288 self.cache += data
289 if len(self.cache) < self.blocksize:
290 return ''
291 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
292 self.IV = self.codebook.encrypt(util.xorstring(self.cache[i:i+self.blocksize],self.IV))
293 encrypted_blocks += self.IV
294 self.cache = self.cache[i+self.blocksize:]
295 return encrypted_blocks
296 else:
297 decrypted_blocks = ''
298 self.cache += data
299 if len(self.cache) < self.blocksize:
300 return ''
301 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
302 plaintext = util.xorstring(self.IV,self.codebook.decrypt(self.cache[i:i + self.blocksize]))
303 self.IV = self.cache[i:i + self.blocksize]
304 decrypted_blocks+=plaintext
305 self.cache = self.cache[i+self.blocksize:]
306 return decrypted_blocks
308 class CFB:
309 # TODO: bit access instead of only byte level access
310 """CFB Chaining Mode
312 Can be accessed as a stream cipher.
315 def __init__(self, codebook, blocksize, IV,segment_size):
316 self.codebook = codebook
317 self.IV = IV
318 self.blocksize = blocksize
319 self.segment_size = segment_size/8
320 self.keystream = []
321 self.totalbytes = 0
323 def update(self, data, ed):
324 """Processes the given ciphertext/plaintext
326 Inputs:
327 data: raw string of any multiple of bytes
328 ed: 'e' for encryption, 'd' for decryption
329 Output:
330 processed raw string
332 The encrypt/decrypt functions will always process all of the supplied
333 input data immediately. No cache will be kept.
335 output = list(data)
337 for i in xrange(len(data)):
338 if ed =='e':
339 if len(self.keystream) == 0:
340 block = self.codebook.encrypt(self.IV)
341 self.keystream = list(block)[:self.segment_size] # keystream consists of the s MSB's
342 self.IV = self.IV[self.segment_size:] # keeping (b-s) LSB's
343 output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0)))
344 self.IV += output[i] # the IV for the next block in the chain is being built byte per byte as the ciphertext flows in
345 else:
346 if len(self.keystream) == 0:
347 block = self.codebook.encrypt(self.IV)
348 self.keystream = list(block)[:self.segment_size]
349 self.IV = self.IV[self.segment_size:]
350 self.IV += output[i]
351 output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0)))
352 self.totalbytes += len(output)
353 return ''.join(output)
355 class OFB:
356 """OFB Chaining Mode
358 Can be accessed as a stream cipher.
360 def __init__(self, codebook, blocksize, IV):
361 self.codebook = codebook
362 self.IV = IV
363 self.blocksize = blocksize
364 self.keystream = []
365 self.totalbytes = 0
367 def update(self, data, ed):
368 """Processes the given ciphertext/plaintext
370 Inputs:
371 data: raw string of any multiple of bytes
372 ed: 'e' for encryption, 'd' for decryption
373 Output:
374 processed raw string
376 The encrypt/decrypt functions will always process all of the supplied
377 input data immediately. No cache will be kept.
379 #no difference between encryption and decryption mode
380 n = len(data)
381 blocksize = self.blocksize
382 output = list(data)
384 for i in xrange(n):
385 if len(self.keystream) == 0: #encrypt a new counter block when the current keystream is fully used
386 self.IV = self.codebook.encrypt(self.IV)
387 self.keystream = list(self.IV)
388 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"
390 self.totalbytes += len(output)
391 return ''.join(output)
393 class CTR:
394 """CTR Chaining Mode
396 Can be accessed as a stream cipher.
398 # initial counter value can be choosen, decryption always starts from beginning
399 # -> you can start from anywhere yourself: just feed the cipher encoded blocks and feed a counter with the corresponding value
400 def __init__(self, codebook, blocksize, counter):
401 self.codebook = codebook
402 self.counter = counter
403 self.blocksize = blocksize
404 self.keystream = [] #holds the output of the current encrypted counter value
405 self.totalbytes = 0
407 def update(self, data, ed):
408 """Processes the given ciphertext/plaintext
410 Inputs:
411 data: raw string of any multiple of bytes
412 ed: 'e' for encryption, 'd' for decryption
413 Output:
414 processed raw string
416 The encrypt/decrypt functions will always process all of the supplied
417 input data immediately. No cache will be kept.
419 # no need for the encryption/decryption distinction: both are the same
420 n = len(data)
421 blocksize = self.blocksize
423 output = list(data)
424 for i in xrange(n):
425 if len(self.keystream) == 0: #encrypt a new counter block when the current keystream is fully used
426 block = self.codebook.encrypt(self.counter())
427 self.keystream = list(block)
428 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"
429 self.totalbytes += len(output)
430 return ''.join(output)
432 class XTS:
433 """XTS Chaining Mode
435 Usable with blockciphers with a 16-byte blocksize
437 # TODO: allow other blocksizes besides 16bytes?
438 def __init__(self,codebook1, codebook2):
439 self.cache = ''
440 self.codebook1 = codebook1
441 self.codebook2 = codebook2
443 def update(self, data, ed,tweak=''):
444 # supply n as a raw string
445 # tweak = data sequence number
446 """Perform a XTS encrypt/decrypt operation.
448 Because the handling of the last two blocks is linked,
449 it needs the whole block of ciphertext to be supplied at once.
450 Every decrypt function called on a XTS cipher will output
451 a decrypted block based on the current supplied ciphertext block.
453 output = ''
454 assert len(data) > 15, "At least one block of 128 bits needs to be supplied"
455 assert len(data) < 128*pow(2,20)
457 # initializing T
458 # e_k2_n = E_K2(tweak)
459 e_k2_n = self.codebook2.encrypt(tweak+ '\x00' * (16-len(tweak)))[::-1]
460 self.T = util.string2number(e_k2_n)
463 while i < ((len(data) // 16)-1): #Decrypt all the blocks but one last full block and opt one last partial block
464 # C = E_K1(P xor T) xor T
465 output += self.__xts_step(ed,data[i*16:(i+1)*16],self.T)
466 # T = E_K2(n) mul (a pow i)
467 self.__T_update()
468 i+=1
470 # Check if the data supplied is a multiple of 16 bytes -> one last full block and we're done
471 if len(data[i*16:]) == 16:
472 # C = E_K1(P xor T) xor T
473 output += self.__xts_step(ed,data[i*16:(i+1)*16],self.T)
474 # T = E_K2(n) mul (a pow i)
475 self.__T_update()
476 else:
477 T_temp = [self.T]
478 self.__T_update()
479 T_temp.append(self.T)
480 if ed=='d':
481 # Permutation of the last two indexes
482 T_temp.reverse()
483 # Decrypt/Encrypt the last two blocks when data is not a multiple of 16 bytes
484 Cm1 = data[i*16:(i+1)*16]
485 Cm = data[(i+1)*16:]
486 PP = self.__xts_step(ed,Cm1,T_temp[0])
487 Cp = PP[len(Cm):]
488 Pm = PP[:len(Cm)]
489 CC = Cm+Cp
490 Pm1 = self.__xts_step(ed,CC,T_temp[1])
491 output += Pm1 + Pm
492 return output
494 def __xts_step(self,ed,tocrypt,T):
495 T_string = util.number2string_N(T,16)[::-1]
496 # C = E_K1(P xor T) xor T
497 if ed == 'd':
498 return util.xorstring(T_string, self.codebook1.decrypt(util.xorstring(T_string, tocrypt)))
499 else:
500 return util.xorstring(T_string, self.codebook1.encrypt(util.xorstring(T_string, tocrypt)))
502 def __T_update(self):
503 # Used for calculating T for a certain step using the T value from the previous step
504 self.T = self.T << 1
505 # if (Cout)
506 if self.T >> (8*16):
507 #T[0] ^= GF_128_FDBK;
508 self.T = self.T ^ 0x100000000000000000000000000000087L
511 class CMAC:
512 """CMAC chaining mode
514 Supports every cipher with a blocksize available
515 in the list CMAC.supported_blocksizes.
516 The hashlength is equal to block size of the used block cipher.
518 Usable with blockciphers with a 8 or 16-byte blocksize
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,IV):
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
532 self.IV = IV
534 #Rb_dictionary: holds values for Rb for different blocksizes
535 # values for 64 and 128 bits found here: http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
536 # explanation from: http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
537 # Rb is a representation of a certain irreducible binary polynomial of degree b, namely,
538 # the lexicographically first among all such polynomials with the minimum possible number of
539 # nonzero terms. If this polynomial is expressed as ub+cb-1ub-1+...+c2u2+c1u+c0, where the
540 # coefficients cb-1, cb-2, ..., c2, c1, c0 are either 0 or 1, then Rb is the bit string cb-1cb-2...c2c1c0.
542 self.Rb = self.__Rb_dictionary[blocksize*8]
544 mask1 = int(('\xff'*blocksize).encode('hex'),16)
545 mask2 = int(('\x80' + '\x00'*(blocksize-1) ).encode('hex'),16)
547 L = int(self.codebook.encrypt('\x00'*blocksize).encode('hex'),16)
549 if L & mask2:
550 Lu = ((L << 1) & mask1) ^ self.Rb
551 else:
552 Lu = L << 1
553 Lu = Lu & mask1
555 if Lu & mask2:
556 Lu2 = ((Lu << 1) & mask1)^ self.Rb
557 else:
558 Lu2 = Lu << 1
559 Lu2 = Lu2 & mask1
561 self.Lu =util.number2string_N(Lu,self.blocksize)
562 self.Lu2=util.number2string_N(Lu2,self.blocksize)
564 def update(self, data, ed):
565 """Processes the given ciphertext/plaintext
567 Inputs:
568 data: raw string of any length
569 ed: 'e' for encryption, 'd' for decryption
570 Output:
571 hashed data as raw string
573 This is not really an update function:
574 Everytime the function is called, the hash from the input data is calculated.
575 No finalizing needed.
577 assert ed == 'e'
578 blocksize = self.blocksize
580 m = (len(data)+blocksize-1)/blocksize #m = amount of datablocks
582 for i in range(1,m):
583 self.IV = self.codebook.encrypt( util.xorstring(data[(i-1)*blocksize:(i)*blocksize],self.IV) )
585 if len(data[(i)*blocksize:])==blocksize:
586 X = util.xorstring(util.xorstring(data[(i)*blocksize:],self.IV),self.Lu)
587 else:
588 tmp = data[(i)*blocksize:] + '\x80' + '\x00'*(blocksize - len(data[(i)*blocksize:])-1)
589 X = util.xorstring(util.xorstring(tmp,self.IV),self.Lu2)
591 T = self.codebook.encrypt(X)
592 return T