Subversion Repositories pub

Compare Revisions

Problem with comparison.

Ignore whitespace Rev HEAD → Rev 183

/relevation/ext/cryptopy-1.2.5.patched/crypto/cipher/cbc.py
0,0 → 1,109
""" crypto.cipher.cbc
 
CBC mode of encryption for block ciphers.
 
This algorithm mode wraps any BlockCipher to make a
Cipher Block Chaining mode.
 
Note !!!! auto IV uses python default random :-(
should not be 'too bad' (tm) for this cbc applicaiton
 
Copyright © (c) 2002 by Paul A. Lambert
Read LICENSE.txt for license information.
"""
from crypto.cipher.base import BlockCipher, padWithPadLen, noPadding
from crypto.errors import EncryptError
from crypto.common import xor
from random import Random # should change to crypto.random!!!
 
 
class CBC(BlockCipher):
""" The CBC class wraps block ciphers to make cipher block chaining (CBC) mode
algorithms. The initialization (IV) is automatic if set to None. Padding
is also automatic based on the Pad class used to initialize the algorithm
"""
def __init__(self, blockCipherInstance, padding = padWithPadLen()):
""" CBC algorithms are created by initializing with a BlockCipher instance """
self.baseCipher = blockCipherInstance
self.name = self.baseCipher.name + '_CBC'
self.blockSize = self.baseCipher.blockSize
self.keySize = self.baseCipher.keySize
self.padding = padding
self.baseCipher.padding = noPadding() # baseCipher should NOT pad!!
self.r = Random() # for IV generation, currently uses
# mediocre standard distro version <----------------
import time
newSeed = time.ctime()+str(self.r) # seed with instance location
self.r.seed(newSeed) # to make unique
self.reset()
 
def setKey(self, key):
self.baseCipher.setKey(key)
 
# Overload to reset both CBC state and the wrapped baseCipher
def resetEncrypt(self):
BlockCipher.resetEncrypt(self) # reset CBC encrypt state (super class)
self.baseCipher.resetEncrypt() # reset base cipher encrypt state
 
def resetDecrypt(self):
BlockCipher.resetDecrypt(self) # reset CBC state (super class)
self.baseCipher.resetDecrypt() # reset base cipher decrypt state
 
def encrypt(self, plainText, iv=None, more=None):
""" CBC encryption - overloads baseCipher to allow optional explicit IV
when iv=None, iv is auto generated!
"""
if self.encryptBlockCount == 0:
self.iv = iv
else:
assert(iv==None), 'IV used only on first call to encrypt'
 
return BlockCipher.encrypt(self,plainText, more=more)
 
def decrypt(self, cipherText, iv=None, more=None):
""" CBC decryption - overloads baseCipher to allow optional explicit IV
when iv=None, iv is auto generated!
"""
if self.decryptBlockCount == 0:
self.iv = iv
else:
assert(iv==None), 'IV used only on first call to decrypt'
 
return BlockCipher.decrypt(self, cipherText, more=more)
 
def encryptBlock(self, plainTextBlock):
""" CBC block encryption, IV is set with 'encrypt' """
auto_IV = ''
if self.encryptBlockCount == 0:
if self.iv == None:
# generate IV and use
self.iv = ''.join([chr(self.r.randrange(256)) for i in range(self.blockSize)])
self.prior_encr_CT_block = self.iv
auto_IV = self.prior_encr_CT_block # prepend IV if it's automatic
else: # application provided IV
assert(len(self.iv) == self.blockSize ),'IV must be same length as block'
self.prior_encr_CT_block = self.iv
""" encrypt the prior CT XORed with the PT """
ct = self.baseCipher.encryptBlock( xor(self.prior_encr_CT_block, plainTextBlock) )
self.prior_encr_CT_block = ct
return auto_IV+ct
 
def decryptBlock(self, encryptedBlock):
""" Decrypt a single block """
 
if self.decryptBlockCount == 0: # first call, process IV
if self.iv == None: # auto decrypt IV?
self.prior_CT_block = encryptedBlock
return ''
else:
assert(len(self.iv)==self.blockSize),"Bad IV size on CBC decryption"
self.prior_CT_block = self.iv
 
dct = self.baseCipher.decryptBlock(encryptedBlock)
""" XOR the prior decrypted CT with the prior CT """
dct_XOR_priorCT = xor( self.prior_CT_block, dct )
 
self.prior_CT_block = encryptedBlock
 
return dct_XOR_priorCT