0,0 → 1,102 |
""" crypto.cipher.icedoll |
|
Modification of Rijndael to provide infinite error extension. |
The ith round of Rijndael is tapped and used to process the |
subsequent block. |
|
Changes to base Rijndael are marked with: '# --------------------------' |
|
For Rijndael with N rounds, normally ECB mode is C[i] = Ek(N,P[i]) |
|
Modification is: |
Fi = Ek(t,P[i-1]) ; Fi, with i=0 is nonce or a fixed value |
C[i] = Fi^Ek(N,P[i]^Fi) |
|
Copyright © (c) 2002 by Paul A. Lambert |
Read LICENSE.txt for license information. |
|
June 2002 |
February 2003 -> discovered Ron Rivest's "Tweakable Block Ciphers" |
http://theory.lcs.mit.edu/~rivest/publications.html |
These are about the same concept .... |
""" |
|
from crypto.cipher.base import BlockCipherWithIntegrity, padWithPadLen, noPadding |
from crypto.cipher.rijndael import * |
from binascii_plus import b2a_hex |
from copy import deepcopy |
|
class Icedoll(Rijndael): |
""" IceDoll encryption algorithm |
based on Rijndael, with added feedback for better integrity processing. |
Note - no integrity check is built into Icedoll directly |
""" |
def __init__(self,key=None,padding=padWithPadLen(),keySize=16,blockSize=16,tapRound=6,extraRounds=6): |
""" key, keysize, blockSize same as Rijndael, tapROund is feedback tap, """ |
self.tapRound = tapRound # <------- !!! change from Rijndael !!! |
self.extraRounds = extraRounds # <------- !!! change from Rijndael !!! |
self.name = 'ICEDOLL' |
self.keySize = keySize |
self.strength = keySize |
self.blockSize = blockSize # blockSize is in bytes |
self.padding = padding # change default to noPadding() to get normal ECB behavior |
|
assert( keySize%4==0 and NrTable[4].has_key(keySize/4)),'key size must be 16,20,24,29 or 32 bytes' |
assert( blockSize%4==0 and NrTable.has_key(blockSize/4)), 'block size must be 16,20,24,29 or 32 bytes' |
|
self.Nb = self.blockSize/4 # Nb is number of columns of 32 bit words |
self.Nk = keySize/4 # Nk is the key length in 32-bit words |
self.Nr = NrTable[self.Nb][self.Nk]+extraRounds # <------- !!! change from Rijndael !!! |
|
if key != None: |
self.setKey(key) |
|
def setKey(self, key): |
""" Set a key and generate the expanded key """ |
assert( len(key) == (self.Nk*4) ), 'Key length must be same as keySize parameter' |
self.__expandedKey = keyExpansion(self, key) |
self.reset() # BlockCipher.reset() |
|
def encryptBlock(self, plainTextBlock): |
""" Encrypt a block, plainTextBlock must be a array of bytes [Nb by 4] """ |
self.state = self._toBlock(plainTextBlock) |
if self.encryptBlockCount == 0: # first call, set frdd back |
self.priorFeedBack = self._toBlock(chr(0)*(4*self.Nb)) # <------- !!! change from Rijndael !!! |
AddRoundKey(self, self.priorFeedBack) # <------- !!! change from Rijndael !!! |
AddRoundKey(self, self.__expandedKey[0:self.Nb]) |
for round in range(1,self.Nr): #for round = 1 step 1 to Nr1 |
SubBytes(self) |
ShiftRows(self) |
MixColumns(self) |
if round == self.tapRound: |
nextFeedBack = deepcopy(self.state) # <------- !!! change from Rijndael !!! |
AddRoundKey(self, self.__expandedKey[round*self.Nb:(round+1)*self.Nb]) |
SubBytes(self) |
ShiftRows(self) |
AddRoundKey(self, self.__expandedKey[self.Nr*self.Nb:(self.Nr+1)*self.Nb]) |
AddRoundKey(self, self.priorFeedBack) # <------- !!! change from Rijndael !!! |
self.priorFeedBack = nextFeedBack # <------- !!! change from Rijndael !!! |
return self._toBString(self.state) |
|
def decryptBlock(self, encryptedBlock): |
""" decrypt a block (array of bytes) """ |
self.state = self._toBlock(encryptedBlock) |
if self.decryptBlockCount == 0: # first call, set frdd back |
self.priorFeedBack = self._toBlock( chr(0)*(4*self.Nb) ) # <------- !!! change from Rijndael !!! |
AddRoundKey(self, self.priorFeedBack) # <------- !!! change from Rijndael !!! |
AddRoundKey(self, self.__expandedKey[self.Nr*self.Nb:(self.Nr+1)*self.Nb]) |
for round in range(self.Nr-1,0,-1): |
InvShiftRows(self) |
InvSubBytes(self) |
AddRoundKey(self, self.__expandedKey[round*self.Nb:(round+1)*self.Nb]) |
if round == self.tapRound: |
nextFeedBack = deepcopy(self.state) # <------- !!! change from Rijndael !!! |
InvMixColumns(self) |
InvShiftRows(self) |
InvSubBytes(self) |
AddRoundKey(self, self.__expandedKey[0:self.Nb]) |
AddRoundKey(self, self.priorFeedBack) # <------- !!! change from Rijndael !!! |
self.priorFeedBack = nextFeedBack # <------- !!! change from Rijndael !!! |
return self._toBString(self.state) |
|
|