CFB: Array->List
[python-cryptoplus.git] / src / CryptoPlus / Cipher / blockcipher.py
blob60fcd1dd23327ffa08a3ec0fa0770a6a58c37115
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 = []
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 output = list(data)
346 for i in xrange(len(data)):
347 if ed =='e':
348 if len(self.keystream) == 0:
349 block = self.codebook.encrypt(self.IV)
350 self.keystream = list(block)
351 self.IV = ''
352 output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0)))
353 self.IV += output[i] # the IV for the next block in the chain is being built byte per byte as the ciphertext flows in
354 else:
355 if len(self.keystream) == 0:
356 block = self.codebook.encrypt(self.IV)
357 self.keystream = list(block)
358 self.IV = ''
359 self.IV += output[i]
360 output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0)))
361 return ''.join(output)
363 class OFB:
364 """OFB Chaining Mode
366 Can be accessed as a stream cipher.
368 def __init__(self, codebook, blocksize, IV):
369 self.codebook = codebook
370 self.IV = IV
371 self.blocksize = blocksize
372 self.keystream =array('B', '')
373 def update(self, data, ed):
374 """Processes the given ciphertext/plaintext
376 Inputs:
377 data: raw string of any multiple of bytes
378 ed: 'e' for encryption, 'd' for decryption
379 Output:
380 processed raw string
382 The encrypt/decrypt functions will always process all of the supplied
383 input data immediately. No cache will be kept.
385 #no difference between encryption and decryption mode
386 n = len(data)
387 blocksize = self.blocksize
388 output = array('B', data)
390 for i in xrange(n):
391 if self.keystream.buffer_info()[1] == 0: #encrypt a new counter block when the current keystream is fully used
392 self.IV = self.codebook.encrypt(self.IV)
393 self.keystream = array('B', self.IV)
394 output[i] ^= self.keystream.pop(0) #as long as an encrypted counter value is available, the output is just "input XOR keystream"
395 return output.tostring()
397 class CTR:
398 """CTR Chaining Mode
400 Can be accessed as a stream cipher.
402 # initial counter value can be choosen, decryption always starts from beginning
403 # -> you can start from anywhere yourself: just feed the cipher encoded blocks and feed a counter with the corresponding value
404 def __init__(self, codebook, blocksize, counter):
405 self.codebook = codebook
406 self.counter = counter
407 self.blocksize = blocksize
408 self.keystream =array('B', '') #holds the output of the current encrypted counter value
410 def update(self, data, ed):
411 """Processes the given ciphertext/plaintext
413 Inputs:
414 data: raw string of any multiple of bytes
415 ed: 'e' for encryption, 'd' for decryption
416 Output:
417 processed raw string
419 The encrypt/decrypt functions will always process all of the supplied
420 input data immediately. No cache will be kept.
422 # no need for the encryption/decryption distinction: both are the same
423 n = len(data)
424 blocksize = self.blocksize
426 output = array('B', data)
427 for i in xrange(n):
428 if self.keystream.buffer_info()[1] == 0: #encrypt a new counter block when the current keystream is fully used
429 block = self.codebook.encrypt(self.counter())
430 self.keystream = array('B', block)
431 output[i] ^= self.keystream.pop(0) #as long as an encrypted counter value is available, the output is just "input XOR keystream"
432 return output.tostring()
434 class XTS:
435 """XTS Chaining Mode
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 # TODO: move to hash module?
519 # TODO: change update behaviour to .update() and .digest() as for all hash modules?
520 # -> other hash functions in pycrypto: calling update, concatenates current input with previous input and hashes everything
521 __Rb_dictionary = {64:0x000000000000001b,128:0x00000000000000000000000000000087}
522 supported_blocksizes = __Rb_dictionary.keys()
523 def __init__(self,codebook,blocksize):
524 # Purpose of init: calculate Lu & Lu2
525 #blocksize (in bytes): to select the Rb constant in the dictionary
526 #Rb as a dictionary: adding support for other blocksizes is easy
527 self.cache=''
528 self.blocksize = blocksize
529 self.codebook = codebook
531 #Rb_dictionary: holds values for Rb for different blocksizes
532 # values for 64 and 128 bits found here: http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
533 # explanation from: http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
534 # Rb is a representation of a certain irreducible binary polynomial of degree b, namely,
535 # the lexicographically first among all such polynomials with the minimum possible number of
536 # nonzero terms. If this polynomial is expressed as ub+cb-1ub-1+...+c2u2+c1u+c0, where the
537 # coefficients cb-1, cb-2, ..., c2, c1, c0 are either 0 or 1, then Rb is the bit string cb-1cb-2...c2c1c0.
539 self.Rb = self.__Rb_dictionary[blocksize*8]
541 mask1 = int(('\xff'*blocksize).encode('hex'),16)
542 mask2 = int(('\x80' + '\x00'*(blocksize-1) ).encode('hex'),16)
544 L = int(self.codebook.encrypt('\x00'*blocksize).encode('hex'),16)
546 if L & mask2:
547 Lu = ((L << 1) & mask1) ^ self.Rb
548 else:
549 Lu = L << 1
550 Lu = Lu & mask1
552 if Lu & mask2:
553 Lu2 = ((Lu << 1) & mask1)^ self.Rb
554 else:
555 Lu2 = Lu << 1
556 Lu2 = Lu2 & mask1
558 self.Lu =util.number2string_N(Lu,self.blocksize)
559 self.Lu2=util.number2string_N(Lu2,self.blocksize)
561 def update(self, data, ed):
562 """Processes the given ciphertext/plaintext
564 Inputs:
565 data: raw string of any length
566 ed: 'e' for encryption, 'd' for decryption
567 Output:
568 hashed data as raw string
570 This is not really an update function:
571 Everytime the function is called, the hash from the input data is calculated.
572 No finalizing needed.
574 assert ed == 'e'
575 blocksize = self.blocksize
577 m = (len(data)+blocksize-1)/blocksize #m = amount of datablocks
578 y = '\x00'*blocksize
580 for i in range(1,m):
581 y = self.codebook.encrypt( util.xorstring(data[(i-1)*blocksize:(i)*blocksize],y) )
583 if len(data[(i)*blocksize:])==blocksize:
584 X = util.xorstring(util.xorstring(data[(i)*blocksize:],y),self.Lu)
585 else:
586 tmp = data[(i)*blocksize:] + '\x80' + '\x00'*(blocksize - len(data[(i)*blocksize:])-1)
587 X = util.xorstring(util.xorstring(tmp,y),self.Lu2)
589 T = self.codebook.encrypt(X)
590 return T