Subversion Repositories pub

Compare Revisions

Ignore whitespace Rev 167 → Rev 168

/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/DES3.py
0,0 → 1,74
from blockcipher import *
import Crypto.Cipher.DES3
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None):
"""Create a new cipher object
 
DES using pycrypto for algo and pycryptoplus for ciphermode
 
key = raw string containing the 2/3 keys
- DES-EDE2: supply 2 keys as 1 single concatenated 16byte key= key1|key2
- DES-EDE3: supply 3 keys as 1 single concatenated 24byte key= key1|key2|key3
mode = python_AES.MODE_ECB/CBC/CFB/OFB/CTR/CMAC, default is ECB
IV = IV as a raw string, default is "all zero" IV
-> only needed for CBC mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import DES3
 
CBC TDES-EDE3 EXAMPLE: (using test vectors from http://csrc.nist.gov/groups/STM/cavp/documents/des/DESMMT.pdf)
------------
>>> key = ('37ae5ebf46dff2dc0754b94f31cbb3855e7fd36dc870bfae').decode('hex')
>>> IV = ('3d1de3cc132e3b65').decode('hex')
>>> cipher = DES3.new(key, DES3.MODE_CBC, IV)
>>> ciphertext = cipher.encrypt(('84401f78fe6c10876d8ea23094ea5309').decode('hex'))
>>> (ciphertext).encode('hex')
'7b1f7c7e3b1c948ebd04a75ffba7d2f5'
>>> decipher = DES3.new(key, DES3.MODE_CBC, IV)
>>> plaintext = decipher.decrypt(ciphertext)
>>> (plaintext).encode('hex')
'84401f78fe6c10876d8ea23094ea5309'
 
CMAC TDES-EDE3 EXAMPLE: (http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf)
-------------
>>> key = '8aa83bf8cbda10620bc1bf19fbb6cd58bc313d4a371ca8b5'.decode('hex')
>>> plaintext = '6bc1bee22e409f96e93d7e117393172aae2d8a57'.decode('hex')
>>> cipher = DES3.new(key, DES3.MODE_CMAC)
>>> cipher.encrypt(plaintext).encode('hex')
'743ddbe0ce2dc2ed'
 
CMAC TDES-EDE2 EXAMPLE:
-----------------------
testvector: http://csrc.nist.gov/groups/STM/cavp/documents/mac/cmactestvectors.zip
 
>>> key1 = "5104f2c76180c1d3".decode('hex')
>>> key2 = "b9df763e31ada716".decode('hex')
>>> key = key1 + key2
>>> plaintext = 'a6866be2fa6678f264a19c4474968e3f4eec24f5086d'.decode('hex')
>>> cipher = DES3.new(key, DES3.MODE_CMAC)
>>> cipher.encrypt(plaintext).encode('hex')
'32e7758f3f614dbf'
"""
return DES3(key,mode,IV,counter,segment_size)
 
class DES3(BlockCipher):
def __init__(self,key,mode,IV,counter,segment_size):
cipher_module = Crypto.Cipher.DES3.new
self.blocksize = 8
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/__init__.py
0,0 → 1,10
from Crypto.Cipher import ARC4, XOR
 
__all__ = ["AES","python_AES","python_DES","python_DES3","DES","DES3","Blowfish","python_Blowfish","python_Twofish","python_Serpent","python_Rijndael","ARC4","ARC2","CAST","XOR","python_PRESENT"]
 
try:
import Crypto.Cipher.IDEA
__all__.append("IDEA")
__all__.append("RC5")
except ImportError:
pass
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/python_DES3.py
0,0 → 1,80
from blockcipher import *
import pyDes
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None):
"""Create a DES-EDE3 or DES-EDE2 cipher object
 
wrapper for pure python 3DES implementation pyDes.py
 
key = raw string containing the 2/3 keys
- DES-EDE2: supply 2 keys as 1 single concatenated 16byte key= key1|key2
- DES-EDE3: supply 3 keys as 1 single concatenated 24byte key= key1|key2|key3
mode = python_AES.MODE_ECB/CBC/CFB/OFB/CTR/CMAC, default is ECB
IV = IV as a raw string, default is "all zero" IV
-> only needed for CBC mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import python_DES3
 
CBC TDES-EDE3 EXAMPLE: (using test vectors from http://csrc.nist.gov/groups/STM/cavp/documents/des/DESMMT.pdf)
------------
>>> key = ('37ae5ebf46dff2dc0754b94f31cbb3855e7fd36dc870bfae').decode('hex')
>>> IV = ('3d1de3cc132e3b65').decode('hex')
>>> cipher = python_DES3.new(key, python_DES3.MODE_CBC, IV)
>>> ciphertext = cipher.encrypt(('84401f78fe6c10876d8ea23094ea5309').decode('hex'))
>>> (ciphertext).encode('hex')
'7b1f7c7e3b1c948ebd04a75ffba7d2f5'
>>> decipher = python_DES3.new(key, python_DES3.MODE_CBC, IV)
>>> plaintext = decipher.decrypt(ciphertext)
>>> (plaintext).encode('hex')
'84401f78fe6c10876d8ea23094ea5309'
 
CMAC TDES-EDE3 EXAMPLE:
-------------
testvector: http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
 
>>> key = '8aa83bf8cbda10620bc1bf19fbb6cd58bc313d4a371ca8b5'.decode('hex')
>>> plaintext = '6bc1bee22e409f96e93d7e117393172aae2d8a57'.decode('hex')
>>> cipher = python_DES3.new(key, python_DES3.MODE_CMAC)
>>> cipher.encrypt(plaintext).encode('hex')
'743ddbe0ce2dc2ed'
 
CMAC TDES-EDE2 EXAMPLE:
-----------------------
testvector: http://csrc.nist.gov/groups/STM/cavp/documents/mac/cmactestvectors.zip
 
>>> key1 = "5104f2c76180c1d3".decode('hex')
>>> key2 = "b9df763e31ada716".decode('hex')
>>> key = key1 + key2
>>> plaintext = 'a6866be2fa6678f264a19c4474968e3f4eec24f5086d'.decode('hex')
>>> cipher = python_DES3.new(key, python_DES3.MODE_CMAC)
>>> cipher.encrypt(plaintext).encode('hex')
'32e7758f3f614dbf'"""
return python_DES3(key,mode,IV,counter,segment_size)
 
class python_DES3(BlockCipher):
key_error_message = "Key should be 128 or 192 bits"
 
def __init__(self,key,mode,IV,counter,segment_size):
cipher_module = pyDes.triple_des
self.blocksize = 8
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size)
 
def keylen_valid(self,key):
return len(key) in (16,24)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/IDEA.py
0,0 → 1,52
from blockcipher import *
try:
import Crypto.Cipher.IDEA
except ImportError:
print "Crypto.Cipher.IDEA isn't available. You're probably using the Debian pycrypto version. Install the original pycrypto for IDEA."
raise
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None):
"""Create a new cipher object
 
IDEA using pycrypto for algo and pycryptoplus for ciphermode
 
key = raw string containing the keys
mode = python_AES.MODE_ECB/CBC/CFB/OFB/CTR/CMAC, default is ECB
IV = IV as a raw string, default is "all zero" IV
-> only needed for CBC mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import IDEA
 
https://www.cosic.esat.kuleuven.be/nessie/testvectors/
-----------------------------------------
>>> from CryptoPlus.Cipher import IDEA
>>> key = "2BD6459F82C5B300952C49104881FF48".decode('hex')
>>> plaintext = "F129A6601EF62A47".decode('hex')
>>> cipher = IDEA.new(key,IDEA.MODE_ECB,)
>>> cipher.encrypt(plaintext).encode('hex').upper()
'EA024714AD5C4D84'
"""
return IDEA(key,mode,IV,counter,segment_size)
 
class IDEA(BlockCipher):
def __init__(self,key,mode,IV,counter,segment_size):
cipher_module = Crypto.Cipher.IDEA.new
self.blocksize = 8
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/AES.py
0,0 → 1,147
from blockcipher import *
import Crypto.Cipher.AES
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None):
"""Create a new cipher object
 
key = raw string containing the key, AES-128..256 will be selected according to the key length
-> when using XTS mode: the key should be a tuple of the 2 keys needed
mode = AES.MODE_ECB/CBC/CFB/OFB/CTR/XTS/CMAC, default is ECB
IV = IV as a raw string, default is "all zero" IV
-> only needed for CBC mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import AES
 
ECB EXAMPLE:
-------------
NIST Special Publication 800-38A http://cryptome.org/bcm/sp800-38a.htm#F
 
>>> cipher = AES.new('2b7e151628aed2a6abf7158809cf4f3c'.decode('hex'))
>>> crypted = cipher.encrypt('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51'.decode('hex'))
>>> crypted.encode('hex')
'3ad77bb40d7a3660a89ecaf32466ef97f5d3d58503b9699de785895a96fdbaaf'
>>> decipher = AES.new('2b7e151628aed2a6abf7158809cf4f3c'.decode('hex'))
>>> decipher.decrypt(crypted).encode('hex')
'6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51'
 
CBC EXAMPLE (plaintext = 3 blocksizes):
-----------------------------------------
NIST Special Publication 800-38A http://cryptome.org/bcm/sp800-38a.htm#F
 
>>> key = ('2b7e151628aed2a6abf7158809cf4f3c').decode('hex')
>>> IV = ('000102030405060708090a0b0c0d0e0f').decode('hex')
>>> plaintext1 = ('6bc1bee22e409f96e93d7e117393172a').decode('hex')
>>> plaintext2 = ('ae2d8a571e03ac9c9eb76fac45af8e51').decode('hex')
>>> plaintext3 = ('30c81c46a35ce411e5fbc1191a0a52ef').decode('hex')
>>> cipher = AES.new(key,AES.MODE_CBC,IV)
>>> ciphertext = cipher.encrypt(plaintext1 + plaintext2 + plaintext3)
>>> (ciphertext).encode('hex')
'7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e22229516'
>>> decipher = AES.new(key,AES.MODE_CBC,IV)
>>> plaintext = decipher.decrypt(ciphertext)
>>> (plaintext).encode('hex')
'6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52ef'
 
OR: supply plaintext as separate pieces:
------------------------------------------
>>> cipher = AES.new(key,AES.MODE_CBC,IV)
>>> ( cipher.encrypt(plaintext1 + plaintext2[:-2]) ).encode('hex')
'7649abac8119b246cee98e9b12e9197d'
>>> ( cipher.encrypt(plaintext2[-2:] + plaintext3) ).encode('hex')
'5086cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e22229516'
>>> decipher = AES.new(key,AES.MODE_CBC,IV)
>>> (decipher.decrypt(ciphertext[:22])).encode('hex')
'6bc1bee22e409f96e93d7e117393172a'
>>> (decipher.decrypt(ciphertext[22:])).encode('hex')
'ae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52ef'
 
CTR EXAMPLE:
------------
NIST Special Publication 800-38A http://cryptome.org/bcm/sp800-38a.htm#F
 
>>> from CryptoPlus.Util.util import Counter
>>> key = '2b7e151628aed2a6abf7158809cf4f3c'.decode('hex')
>>> counter = Counter('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'.decode('hex'))
>>> cipher = AES.new(key,AES.MODE_CTR,counter=counter)
>>> plaintext1 = '6bc1bee22e409f96e93d7e117393172a'.decode('hex')
>>> plaintext2 = 'ae2d8a571e03ac9c9eb76fac45af8e51'.decode('hex')
>>> plaintext3 = '30c81c46a35ce411e5fbc1191a0a52ef'.decode('hex')
>>> ciphertext = cipher.encrypt(plaintext1 + plaintext2 + plaintext3)
>>> ciphertext.encode('hex')
'874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab'
>>> counter2 = Counter('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'.decode('hex'))
>>> decipher = AES.new(key,AES.MODE_CTR,counter=counter2)
>>> decipher.decrypt(ciphertext).encode('hex')
'6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52ef'
 
XTS EXAMPLE:
cipher/decipher plaintext of 3 blocks, provided as a 2 pieces (31 bytes + 33 bytes)
------------
>>> key = (('2b7e151628aed2a6abf7158809cf4f3c').decode('hex'),('2b7e151628aed2a6abf7158809cf4f3c').decode('hex'))
>>> plaintext1 = ('6bc1bee22e409f96e93d7e117393172a').decode('hex')
>>> plaintext2 = ('ae2d8a571e03ac9c9eb76fac45af8e51').decode('hex')
>>> plaintext3 = ('30c81c46a35ce411e5fbc1191a0a52ef').decode('hex')
>>> cipher = AES.new(key,AES.MODE_XTS)
>>> ciphertext = cipher.encrypt(plaintext1 + plaintext2[:15])
>>> decipher = AES.new(key,AES.MODE_XTS)
>>> deciphertext = decipher.decrypt(ciphertext)
>>> (deciphertext).encode('hex')
'6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e'
>>> ciphertext2 = cipher.encrypt(plaintext2[15:]+plaintext3)
>>> deciphertext2 = decipher.decrypt(ciphertext2)
>>> (deciphertext2).encode('hex')
'5130c81c46a35ce411e5fbc1191a0a52ef'
 
XTS-AES-128 applied for a data unit of 512 bytes
testvector: http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
 
>>> key = ('27182818284590452353602874713526'.decode('hex'),'31415926535897932384626433832795'.decode('hex'))
>>> plaintext = '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'.decode('hex')
>>> cipher = AES.new(key,AES.MODE_XTS)
>>> cipher.encrypt(plaintext).encode('hex')
'27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568'
 
CMAC EXAMPLE:
-------------
NIST publication 800-38B: http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
 
>>> key = '2b7e151628aed2a6abf7158809cf4f3c'.decode('hex')
>>> plaintext = '6bc1bee22e409f96e93d7e117393172a'.decode('hex')
>>> cipher = AES.new(key,AES.MODE_CMAC)
>>> cipher.encrypt(plaintext).encode('hex')
'070a16b46b4d4144f79bdd9dd04a287c'
 
CMAC EXAMPLE2:
--------------
>>> key = '2b7e151628aed2a6abf7158809cf4f3c'.decode('hex')
>>> plaintext = '6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411'.decode('hex')
>>> cipher = AES.new(key,AES.MODE_CMAC)
>>> cipher.encrypt(plaintext).encode('hex')
'dfa66747de9ae63030ca32611497c827'
"""
return AES(key,mode,IV,counter,segment_size)
 
class AES(BlockCipher):
"""AES using pycrypto for algo and pycryptoplus for ciphermode
"""
def __init__(self,key,mode,IV,counter,segment_size):
cipher_module = Crypto.Cipher.AES.new
self.blocksize = 16
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/python_AES.py
0,0 → 1,299
from blockcipher import *
from rijndael import rijndael
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None):
"""Create a new cipher object
 
Wrapper for pure python implementation rijndael.py
 
key = raw string containing the key, AES-128..256 will be selected according to the key length
-> when using XTS mode: the key should be a tuple containing the 2 keys needed
mode = python_AES.MODE_ECB/CBC/CFB/OFB/CTR/XTS/CMAC, default is ECB
-> for every mode, except ECB and CTR, it is important to construct a seperate cipher for encryption and decryption
IV = IV as a raw string, default is "all zero" IV
-> needed for CBC, CFB and OFB mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
-> use a seperate counter object for the cipher and decipher: the counter is updated directly, not a copy
see CTR example further on in the docstring
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
 
Notes:
- Always construct a seperate cipher object for encryption and decryption. Once a cipher object has been used for encryption,
it can't be used for decryption because it keeps a state (if necessary) for the IV.
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import python_AES
 
ECB EXAMPLE:
-------------
NIST Special Publication 800-38A http://cryptome.org/bcm/sp800-38a.htm#F
 
>>> cipher = python_AES.new('2b7e151628aed2a6abf7158809cf4f3c'.decode('hex'))
>>> crypted = cipher.encrypt('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51'.decode('hex'))
>>> crypted.encode('hex')
'3ad77bb40d7a3660a89ecaf32466ef97f5d3d58503b9699de785895a96fdbaaf'
>>> decipher = python_AES.new('2b7e151628aed2a6abf7158809cf4f3c'.decode('hex'))
>>> decipher.decrypt(crypted).encode('hex')
'6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51'
 
PADDING EXAMPLE:
-----------------
>>> cipher = python_AES.new('0123456789012345')
>>> crypt = cipher.encrypt('0123456789012')
>>> crypt += cipher.final()
>>> decipher = python_AES.new('0123456789012345')
>>> decipher.decrypt(crypt)
'0123456789012\\x03\\x03\\x03'
 
CBC EXAMPLE (plaintext = 3 blocksizes):
-----------------------------------------
NIST Special Publication 800-38A http://cryptome.org/bcm/sp800-38a.htm#F
 
>>> key = ('2b7e151628aed2a6abf7158809cf4f3c').decode('hex')
>>> IV = ('000102030405060708090a0b0c0d0e0f').decode('hex')
>>> plaintext1 = ('6bc1bee22e409f96e93d7e117393172a').decode('hex')
>>> plaintext2 = ('ae2d8a571e03ac9c9eb76fac45af8e51').decode('hex')
>>> plaintext3 = ('30c81c46a35ce411e5fbc1191a0a52ef').decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_CBC,IV)
>>> ciphertext = cipher.encrypt(plaintext1 + plaintext2 + plaintext3)
>>> (ciphertext).encode('hex')
'7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e22229516'
>>> decipher = python_AES.new(key,python_AES.MODE_CBC,IV)
>>> plaintext = decipher.decrypt(ciphertext)
>>> (plaintext).encode('hex')
'6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52ef'
 
OR: supply plaintext as seperate pieces:
------------------------------------------
>>> cipher = python_AES.new(key,python_AES.MODE_CBC,IV)
>>> ( cipher.encrypt(plaintext1 + plaintext2[:-2]) ).encode('hex')
'7649abac8119b246cee98e9b12e9197d'
>>> ( cipher.encrypt(plaintext2[-2:] + plaintext3) ).encode('hex')
'5086cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e22229516'
>>> decipher = python_AES.new(key,python_AES.MODE_CBC,IV)
>>> (decipher.decrypt(ciphertext[:22])).encode('hex')
'6bc1bee22e409f96e93d7e117393172a'
>>> (decipher.decrypt(ciphertext[22:])).encode('hex')
'ae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52ef'
 
CFB EXAMPLE: (CFB8-AES192)
------------
NIST Special Publication 800-38A http://cryptome.org/bcm/sp800-38a.htm#F
>>> key = '2b7e151628aed2a6abf7158809cf4f3c'.decode('hex')
>>> IV = '000102030405060708090a0b0c0d0e0f'.decode('hex')
>>> plain = '6bc1bee22e409f96e93d7e117393172a'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_CFB,IV=IV,segment_size=8)
>>> ciphertext = cipher.encrypt(plain)
>>> ciphertext.encode('hex')
'3b79424c9c0dd436bace9e0ed4586a4f'
>>> decipher = python_AES.new(key,python_AES.MODE_CFB,IV)
>>> decipher.decrypt(ciphertext).encode('hex')
'6bc1bee22e409f96e93d7e117393172a'
 
CFB EXAMPLE: (CFB128-AES192)
------------
NIST Special Publication 800-38A http://cryptome.org/bcm/sp800-38a.htm#F
 
>>> key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'.decode('hex')
>>> IV = '000102030405060708090a0b0c0d0e0f'.decode('hex')
>>> plain = '6bc1bee22e409f96e93d7e117393172a'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_CFB,IV=IV,segment_size=128)
>>> output1 = cipher.encrypt(plain)
>>> output1.encode('hex')
'cdc80d6fddf18cab34c25909c99a4174'
>>> plain = 'ae2d8a571e03ac9c9eb76fac45af8e51'.decode('hex')
>>> output2 = cipher.encrypt(plain)
>>> output2.encode('hex')
'67ce7f7f81173621961a2b70171d3d7a'
>>> decipher = python_AES.new(key,python_AES.MODE_CFB,IV=IV,segment_size=128)
>>> decipher.decrypt(output1+output2).encode('hex')
'6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51'
 
CFB EXAMPLE: same as previous but now as a streamcipher
------------
>>> key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'.decode('hex')
>>> IV = '000102030405060708090a0b0c0d0e0f'.decode('hex')
>>> plain = '6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_CFB,IV=IV,segment_size=128)
>>> output = ''
>>> for i in plain: output += cipher.encrypt(i)
>>> output.encode('hex')
'cdc80d6fddf18cab34c25909c99a417467ce7f7f81173621961a2b70171d3d7a'
 
OFB EXAMPLE: (OFB128-AES192)
------------
NIST Special Publication 800-38A http://cryptome.org/bcm/sp800-38a.htm#F
 
>>> key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'.decode('hex')
>>> IV = '000102030405060708090a0b0c0d0e0f'.decode('hex')
>>> plain = '6bc1bee22e409f96e93d7e117393172a'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_OFB,IV)
>>> output1 = cipher.encrypt(plain)
>>> output1.encode('hex')
'cdc80d6fddf18cab34c25909c99a4174'
>>> plain = 'ae2d8a571e03ac9c9eb76fac45af8e51'.decode('hex')
>>> output2 = cipher.encrypt(plain)
>>> output2.encode('hex')
'fcc28b8d4c63837c09e81700c1100401'
>>> decipher = python_AES.new(key,python_AES.MODE_OFB,IV)
>>> decipher.decrypt(output1 + output2).encode('hex')
'6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51'
 
OFB EXAMPLE: same as previous but now as a streamcipher
------------
>>> key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'.decode('hex')
>>> IV = '000102030405060708090a0b0c0d0e0f'.decode('hex')
>>> plain = '6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_OFB,IV)
>>> output = ''
>>> for i in plain: output += cipher.encrypt(i)
>>> output.encode('hex')
'cdc80d6fddf18cab34c25909c99a4174fcc28b8d4c63837c09e81700c1100401'
 
 
CTR EXAMPLE:
------------
NIST Special Publication 800-38A http://cryptome.org/bcm/sp800-38a.htm#F
 
>>> from CryptoPlus.Util.util import Counter
>>> key = '2b7e151628aed2a6abf7158809cf4f3c'.decode('hex')
>>> counter = Counter('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'.decode('hex'))
>>> cipher = python_AES.new(key,python_AES.MODE_CTR,counter=counter)
>>> plaintext1 = '6bc1bee22e409f96e93d7e117393172a'.decode('hex')
>>> plaintext2 = 'ae2d8a571e03ac9c9eb76fac45af8e51'.decode('hex')
>>> plaintext3 = '30c81c46a35ce411e5fbc1191a0a52ef'.decode('hex')
>>> ciphertext = cipher.encrypt(plaintext1 + plaintext2 + plaintext3)
>>> ciphertext.encode('hex')
'874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab'
>>> counter2 = Counter('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'.decode('hex'))
>>> decipher = python_AES.new(key,python_AES.MODE_CTR,counter=counter2)
>>> decipher.decrypt(ciphertext).encode('hex')
'6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52ef'
 
XTS EXAMPLE:
------------
XTS-AES-128 applied for a data unit of 512 bytes
IEEE P1619/D16: http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
 
>>> key = ('27182818284590452353602874713526'.decode('hex'),'31415926535897932384626433832795'.decode('hex'))
>>> plaintext = '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_XTS)
>>> ciphertext = cipher.encrypt(plaintext)
>>> ciphertext.encode('hex')
'27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568'
>>> decipher = python_AES.new(key,python_AES.MODE_XTS)
>>> decipher.decrypt(ciphertext).encode('hex')
'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'
 
using data sequence number n
 
>>> key = ('fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0'.decode('hex'),'22222222222222222222222222222222'.decode('hex'))
>>> plain ='4444444444444444444444444444444444444444444444444444444444444444'.decode('hex')
>>> n = '3333333333'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_XTS)
>>> ciphertext = cipher.encrypt(plain,n)
>>> ciphertext.encode('hex')
'af85336b597afc1a900b2eb21ec949d292df4c047e0b21532186a5971a227a89'
>>> decipher = python_AES.new(key,python_AES.MODE_XTS)
>>> decipher.decrypt(ciphertext,n).encode('hex')
'4444444444444444444444444444444444444444444444444444444444444444'
 
>>> key = ('27182818284590452353602874713526'.decode('hex'),'31415926535897932384626433832795'.decode('hex'))
>>> plain ='72efc1ebfe1ee25975a6eb3aa8589dda2b261f1c85bdab442a9e5b2dd1d7c3957a16fc08e526d4b1223f1b1232a11af274c3d70dac57f83e0983c498f1a6f1aecb021c3e70085a1e527f1ce41ee5911a82020161529cd82773762daf5459de94a0a82adae7e1703c808543c29ed6fb32d9e004327c1355180c995a07741493a09c21ba01a387882da4f62534b87bb15d60d197201c0fd3bf30c1500a3ecfecdd66d8721f90bcc4c17ee925c61b0a03727a9c0d5f5ca462fbfa0af1c2513a9d9d4b5345bd27a5f6e653f751693e6b6a2b8ead57d511e00e58c45b7b8d005af79288f5c7c22fd4f1bf7a898b03a5634c6a1ae3f9fae5de4f296a2896b23e7ed43ed14fa5a2803f4d28f0d3ffcf24757677aebdb47bb388378708948a8d4126ed1839e0da29a537a8c198b3c66ab00712dd261674bf45a73d67f76914f830ca014b65596f27e4cf62de66125a5566df9975155628b400fbfb3a29040ed50faffdbb18aece7c5c44693260aab386c0a37b11b114f1c415aebb653be468179428d43a4d8bc3ec38813eca30a13cf1bb18d524f1992d44d8b1a42ea30b22e6c95b199d8d182f8840b09d059585c31ad691fa0619ff038aca2c39a943421157361717c49d322028a74648113bd8c9d7ec77cf3c89c1ec8718ceff8516d96b34c3c614f10699c9abc4ed0411506223bea16af35c883accdbe1104eef0cfdb54e12fb230a'.decode('hex')
>>> n = 'ff'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_XTS)
>>> cipher.encrypt(plain,n).encode('hex')
'3260ae8dad1f4a32c5cafe3ab0eb95549d461a67ceb9e5aa2d3afb62dece0553193ba50c75be251e08d1d08f1088576c7efdfaaf3f459559571e12511753b07af073f35da06af0ce0bbf6b8f5ccc5cea500ec1b211bd51f63b606bf6528796ca12173ba39b8935ee44ccce646f90a45bf9ccc567f0ace13dc2d53ebeedc81f58b2e41179dddf0d5a5c42f5d8506c1a5d2f8f59f3ea873cbcd0eec19acbf325423bd3dcb8c2b1bf1d1eaed0eba7f0698e4314fbeb2f1566d1b9253008cbccf45a2b0d9c5c9c21474f4076e02be26050b99dee4fd68a4cf890e496e4fcae7b70f94ea5a9062da0daeba1993d2ccd1dd3c244b8428801495a58b216547e7e847c46d1d756377b6242d2e5fb83bf752b54e0df71e889f3a2bb0f4c10805bf3c590376e3c24e22ff57f7fa965577375325cea5d920db94b9c336b455f6e894c01866fe9fbb8c8d3f70a2957285f6dfb5dcd8cbf54782f8fe7766d4723819913ac773421e3a31095866bad22c86a6036b2518b2059b4229d18c8c2ccbdf906c6cc6e82464ee57bddb0bebcb1dc645325bfb3e665ef7251082c88ebb1cf203bd779fdd38675713c8daadd17e1cabee432b09787b6ddf3304e38b731b45df5df51b78fcfb3d32466028d0ba36555e7e11ab0ee0666061d1645d962444bc47a38188930a84b4d561395c73c087021927ca638b7afc8a8679ccb84c26555440ec7f10445cd'
 
>>> key = ('2718281828459045235360287471352662497757247093699959574966967627'.decode('hex'),'3141592653589793238462643383279502884197169399375105820974944592'.decode('hex'))
>>> plain ='000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'.decode('hex')
>>> n = 'ffffffffff'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_XTS)
>>> ciphertext = cipher.encrypt(plain,n)
>>> ciphertext.encode('hex')
'64497e5a831e4a932c09be3e5393376daa599548b816031d224bbf50a818ed2350eae7e96087c8a0db51ad290bd00c1ac1620857635bf246c176ab463be30b808da548081ac847b158e1264be25bb0910bbc92647108089415d45fab1b3d2604e8a8eff1ae4020cfa39936b66827b23f371b92200be90251e6d73c5f86de5fd4a950781933d79a28272b782a2ec313efdfcc0628f43d744c2dc2ff3dcb66999b50c7ca895b0c64791eeaa5f29499fb1c026f84ce5b5c72ba1083cddb5ce45434631665c333b60b11593fb253c5179a2c8db813782a004856a1653011e93fb6d876c18366dd8683f53412c0c180f9c848592d593f8609ca736317d356e13e2bff3a9f59cd9aeb19cd482593d8c46128bb32423b37a9adfb482b99453fbe25a41bf6feb4aa0bef5ed24bf73c762978025482c13115e4015aac992e5613a3b5c2f685b84795cb6e9b2656d8c88157e52c42f978d8634c43d06fea928f2822e465aa6576e9bf419384506cc3ce3c54ac1a6f67dc66f3b30191e698380bc999b05abce19dc0c6dcc2dd001ec535ba18deb2df1a101023108318c75dc98611a09dc48a0acdec676fabdf222f07e026f059b672b56e5cbc8e1d21bbd867dd927212054681d70ea737134cdfce93b6f82ae22423274e58a0821cc5502e2d0ab4585e94de6975be5e0b4efce51cd3e70c25a1fbbbd609d273ad5b0d59631c531f6a0a57b9'
>>> decipher = python_AES.new(key,python_AES.MODE_XTS)
>>> decipher.decrypt(ciphertext,n).encode('hex')
'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'
 
using plaintext not a multiple of 16
 
>>> key = ('fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0'.decode('hex'),'bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0'.decode('hex'))
>>> plaintext = '000102030405060708090a0b0c0d0e0f10111213'.decode('hex')
>>> n = '9a78563412'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_XTS)
>>> ciphertext = cipher.encrypt(plaintext,n)
>>> ciphertext.encode('hex')
'9d84c813f719aa2c7be3f66171c7c5c2edbf9dac'
>>> decipher = python_AES.new(key,python_AES.MODE_XTS)
>>> decipher.decrypt(ciphertext,n).encode('hex')
'000102030405060708090a0b0c0d0e0f10111213'
 
>>> key = ('fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0'.decode('hex'),'bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0'.decode('hex'))
>>> plaintext = '000102030405060708090a0b0c0d0e0f10'.decode('hex')
>>> n = '9a78563412'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_XTS)
>>> ciphertext = cipher.encrypt(plaintext,n)
>>> ciphertext.encode('hex')
'6c1625db4671522d3d7599601de7ca09ed'
>>> decipher = python_AES.new(key,python_AES.MODE_XTS)
>>> decipher.decrypt(ciphertext,n).encode('hex')
'000102030405060708090a0b0c0d0e0f10'
 
>>> key = ('e0e1e2e3e4e5e6e7e8e9eaebecedeeef'.decode('hex'),'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf'.decode('hex'))
>>> plaintext = '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'.decode('hex')
>>> n = '21436587a9'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_XTS)
>>> ciphertext = cipher.encrypt(plaintext,n)
>>> ciphertext.encode('hex')
'38b45812ef43a05bd957e545907e223b954ab4aaf088303ad910eadf14b42be68b2461149d8c8ba85f992be970bc621f1b06573f63e867bf5875acafa04e42ccbd7bd3c2a0fb1fff791ec5ec36c66ae4ac1e806d81fbf709dbe29e471fad38549c8e66f5345d7c1eb94f405d1ec785cc6f6a68f6254dd8339f9d84057e01a17741990482999516b5611a38f41bb6478e6f173f320805dd71b1932fc333cb9ee39936beea9ad96fa10fb4112b901734ddad40bc1878995f8e11aee7d141a2f5d48b7a4e1e7f0b2c04830e69a4fd1378411c2f287edf48c6c4e5c247a19680f7fe41cefbd49b582106e3616cbbe4dfb2344b2ae9519391f3e0fb4922254b1d6d2d19c6d4d537b3a26f3bcc51588b32f3eca0829b6a5ac72578fb814fb43cf80d64a233e3f997a3f02683342f2b33d25b492536b93becb2f5e1a8b82f5b883342729e8ae09d16938841a21a97fb543eea3bbff59f13c1a18449e398701c1ad51648346cbc04c27bb2da3b93a1372ccae548fb53bee476f9e9c91773b1bb19828394d55d3e1a20ed69113a860b6829ffa847224604435070221b257e8dff783615d2cae4803a93aa4334ab482a0afac9c0aeda70b45a481df5dec5df8cc0f423c77a5fd46cd312021d4b438862419a791be03bb4d97c0e59578542531ba466a83baf92cefc151b5cc1611a167893819b63fb8a6b18e86de60290fa72b797b0ce59f3'
>>> decipher = python_AES.new(key,python_AES.MODE_XTS)
>>> decipher.decrypt(ciphertext,n).encode('hex')
'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'
 
CMAC EXAMPLE:
-------------
NIST publication 800-38B: http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
 
>>> key = '2b7e151628aed2a6abf7158809cf4f3c'.decode('hex')
>>> plaintext = '6bc1bee22e409f96e93d7e117393172a'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_CMAC)
>>> cipher.encrypt(plaintext).encode('hex')[:16]
'070a16b46b4d4144'
 
CMAC EXAMPLE2:
--------------
>>> key = '2b7e151628aed2a6abf7158809cf4f3c'.decode('hex')
>>> plaintext = '6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411'.decode('hex')
>>> cipher = python_AES.new(key,python_AES.MODE_CMAC)
>>> cipher.encrypt(plaintext).encode('hex')[:16]
'dfa66747de9ae630'
"""
return python_AES(key,mode,IV,counter,segment_size)
 
class python_AES(BlockCipher):
key_error_message = ("Key should be 128, 192 or 256 bits")
 
def __init__(self,key,mode,IV,counter,segment_size):
cipher_module = rijndael
args = {'block_size':16}
self.blocksize = 16
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size,args)
 
def keylen_valid(self,key):
return len(key) in (16,24,32)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/DES.py
0,0 → 1,51
from blockcipher import *
import Crypto.Cipher.DES
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None):
"""Create a new cipher object
 
DES using pycrypto for algo and pycryptoplus for ciphermode
 
key = raw string containing the keys
mode = python_AES.MODE_ECB/CBC/CFB/OFB/CTR/CMAC, default is ECB
IV = IV as a raw string, default is "all zero" IV
-> only needed for CBC mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import DES
 
EXAMPLE (test vectors from NESSIE):
-----------------------------------
 
>>> cipher = DES.new(('7CA110454A1A6E57').decode('hex'))
>>> ciphertext = cipher.encrypt(('01A1D6D039776742').decode('hex'))
>>> (ciphertext).encode('hex')
'690f5b0d9a26939b'
>>> plaintext = cipher.decrypt(ciphertext)
>>> (plaintext).encode('hex')
'01a1d6d039776742'
 
"""
return DES(key,mode,IV,counter,segment_size)
 
class DES(BlockCipher):
def __init__(self,key,mode,IV,counter,segment_size):
cipher_module = Crypto.Cipher.DES.new
self.blocksize = 8
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/python_DES.py
0,0 → 1,57
from blockcipher import *
import pyDes
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None):
"""Create a new cipher object
 
wrapper for pure python implementation pyDes.py
 
key = raw string containing the key
mode = python_DES.MODE_ECB/CBC/CFB/OFB/CTR/CMAC, default is ECB
-> for every mode, except ECB and CTR, it is important to construct a seperate cipher for encryption and decryption
IV = IV as a raw string, default is "all zero" IV
-> needed for CBC, CFB and OFB mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
-> use a seperate counter object for the cipher and decipher: the counter is updated directly, not a copy
see CTR example further on in the docstring
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import python_DES
 
EXAMPLE (test vectors from NESSIE):
-----------------------------------
>>> cipher = python_DES.new(('7CA110454A1A6E57').decode('hex'))
>>> ciphertext = cipher.encrypt(('01A1D6D039776742').decode('hex'))
>>> (ciphertext).encode('hex')
'690f5b0d9a26939b'
>>> plaintext = cipher.decrypt(ciphertext)
>>> (plaintext).encode('hex')
'01a1d6d039776742'
"""
return python_DES(key,mode,IV,counter,segment_size)
 
class python_DES(BlockCipher):
key_error_message = ("Key should be 64 bits")
 
def __init__(self,key,mode,IV,counter,segment_size):
cipher_module = pyDes.des
self.blocksize = 8
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size)
 
def keylen_valid(self,key):
return len(key) == 8
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/Blowfish.py
0,0 → 1,77
from blockcipher import *
import Crypto.Cipher.Blowfish
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None):
"""Create a new cipher object
 
Blowfish using pycrypto for algo and pycryptoplus for ciphermode
 
key = raw string containing the key
mode = Blowfish.MODE_ECB/CBC/CFB/OFB/CTR/CMAC, default is ECB
IV = IV as a raw string, default is "all zero" IV
-> only needed for CBC mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import Blowfish
 
ECB EXAMPLE: http://www.schneier.com/code/vectors.txt
-------------
>>> cipher = Blowfish.new(('0131D9619DC1376E').decode('hex'))
>>> ( cipher.encrypt(('5CD54CA83DEF57DA').decode('hex')) ).encode('hex')
'b1b8cc0b250f09a0'
>>> ( cipher.decrypt((_).decode('hex')) ).encode('hex')
'5cd54ca83def57da'
 
CBC, CFB, OFB EXAMPLE: http://www.schneier.com/code/vectors.txt
----------------------
>>> key = ('0123456789ABCDEFF0E1D2C3B4A59687').decode('hex')
>>> IV = ('FEDCBA9876543210').decode('hex')
>>> plaintext = ('37363534333231204E6F77206973207468652074696D6520').decode('hex')
>>> cipher = Blowfish.new(key,Blowfish.MODE_CBC,IV)
>>> ciphertext = cipher.encrypt(plaintext)
>>> (ciphertext).encode('hex').upper()
'6B77B4D63006DEE605B156E27403979358DEB9E7154616D9'
 
 
>>> key = '0123456789ABCDEFF0E1D2C3B4A59687'.decode('hex')
>>> iv = 'FEDCBA9876543210'.decode('hex')
>>> plaintext = '37363534333231204E6F77206973207468652074696D6520666F722000'.decode('hex')
 
>>> cipher = Blowfish.new(key,Blowfish.MODE_CBC,iv)
>>> ciphertext = cipher.encrypt(plaintext)
>>> (ciphertext).encode('hex').upper()
'6B77B4D63006DEE605B156E27403979358DEB9E7154616D9'
 
>>> cipher = Blowfish.new(key,Blowfish.MODE_CFB,iv,segment_size=64)
>>> ciphertext = cipher.encrypt(plaintext)
>>> (ciphertext).encode('hex').upper()
'E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3'
 
>>> cipher = Blowfish.new(key,Blowfish.MODE_OFB,iv)
>>> ciphertext = cipher.encrypt(plaintext)
>>> (ciphertext).encode('hex').upper()
'E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA'
"""
return Blowfish(key,mode,IV,counter,segment_size)
 
class Blowfish(BlockCipher):
def __init__(self,key,mode,IV,counter,segment_size):
cipher_module = Crypto.Cipher.Blowfish.new
self.blocksize = 8
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/python_Blowfish.py
0,0 → 1,82
from blockcipher import *
from pyblowfish import Blowfish
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None):
"""Create a new cipher object
 
Wrapper for pure python implementation pyblowfish.py
 
key = raw string containing the key
mode = Blowfish.MODE_ECB/CBC/CFB/OFB/CTR/CMAC, default is ECB
IV = IV as a raw string, default is "all zero" IV
-> only needed for CBC mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import python_Blowfish
 
EXAMPLE: (http://www.schneier.com/code/vectors.txt)
----------
 
>>> cipher = python_Blowfish.new(('0131D9619DC1376E').decode('hex'))
>>> ( cipher.encrypt(('5CD54CA83DEF57DA').decode('hex')) ).encode('hex')
'b1b8cc0b250f09a0'
>>> ( cipher.decrypt((_).decode('hex')) ).encode('hex')
'5cd54ca83def57da'
 
CBC, CFB, OFB EXAMPLE: http://www.schneier.com/code/vectors.txt
----------------------
>>> key = ('0123456789ABCDEFF0E1D2C3B4A59687').decode('hex')
>>> IV = ('FEDCBA9876543210').decode('hex')
>>> plaintext = ('37363534333231204E6F77206973207468652074696D6520').decode('hex')
>>> cipher = python_Blowfish.new(key,python_Blowfish.MODE_CBC,IV)
>>> ciphertext = cipher.encrypt(plaintext)
>>> (ciphertext).encode('hex').upper()
'6B77B4D63006DEE605B156E27403979358DEB9E7154616D9'
 
 
>>> key = '0123456789ABCDEFF0E1D2C3B4A59687'.decode('hex')
>>> iv = 'FEDCBA9876543210'.decode('hex')
>>> plaintext = '37363534333231204E6F77206973207468652074696D6520666F722000'.decode('hex')
 
>>> cipher = python_Blowfish.new(key,python_Blowfish.MODE_CBC,iv)
>>> ciphertext = cipher.encrypt(plaintext)
>>> (ciphertext).encode('hex').upper()
'6B77B4D63006DEE605B156E27403979358DEB9E7154616D9'
 
>>> cipher = python_Blowfish.new(key,python_Blowfish.MODE_CFB,iv,segment_size=64)
>>> ciphertext = cipher.encrypt(plaintext)
>>> (ciphertext).encode('hex').upper()
'E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3'
 
>>> cipher = python_Blowfish.new(key,python_Blowfish.MODE_OFB,iv)
>>> ciphertext = cipher.encrypt(plaintext)
>>> (ciphertext).encode('hex').upper()
'E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA'"""
return python_Blowfish(key,mode,IV,counter,segment_size)
 
class python_Blowfish(BlockCipher):
key_error_message = "Key should be between 8 and 56 bytes (64 <-> 448 bits)"
 
def __init__(self,key,mode,IV,counter,segment_size):
cipher_module = Blowfish
self.blocksize = 8
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size)
 
def keylen_valid(self,key):
return 8 <= len(key) <= 56
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/python_Serpent.py
0,0 → 1,68
from blockcipher import *
from pyserpent import Serpent
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None):
"""Create a new cipher object
 
Wrapper for pure python implementation pyserpent.py
 
key = raw string containing the key
-> when using XTS mode: the key should be a tuple containing the 2 keys needed
mode = python_Serpent.MODE_ECB/CBC/CFB/OFB/CTR/XTS/CMAC, default is ECB
-> for every mode, except ECB and CTR, it is important to construct a seperate cipher for encryption and decryption
IV = IV as a raw string, default is "all zero" IV
-> needed for CBC, CFB and OFB mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
-> use a seperate counter object for the cipher and decipher: the counter is updated directly, not a copy
see CTR example further on in the docstring
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import python_Serpent
 
EXAMPLE:
---------
NESSIE Test Vectors: http://www.cs.technion.ac.il/~biham/Reports/Serpent/Serpent-128-128.verified.test-vectors
 
>>> cipher = python_Serpent.new(('000102030405060708090A0B0C0D0E0F').decode('hex'))
>>> (cipher.encrypt(('33B3DC87EDDD9B0F6A1F407D14919365').decode('hex'))).encode('hex').upper()
'00112233445566778899AABBCCDDEEFF'
>>> ( cipher.decrypt((_).decode('hex')) ).encode('hex').upper()
'33B3DC87EDDD9B0F6A1F407D14919365'
 
>>> cipher = python_Serpent.new(('FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD').decode('hex'))
>>> (cipher.encrypt(('FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD').decode('hex'))).encode('hex').upper()
'81F9163BDF39B5BB2932AB91DF2A5FFC'
>>> ( cipher.decrypt((_).decode('hex')) ).encode('hex').upper()
'FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD'
 
CBC EXAMPLE:
-------------
>>> key = ('000102030405060708090A0B0C0D0E0F').decode('hex')
>>> IV = ('00000000000000000000000000000000').decode('hex')
>>> plaintext = ('33B3DC87EDDD9B0F6A1F407D14919365'*3).decode('hex')
>>> cipher = python_Serpent.new(key,python_Serpent.MODE_CBC,IV)
>>> ciphertext = cipher.encrypt(plaintext)
>>> decipher = python_Serpent.new(key,python_Serpent.MODE_CBC,IV)
>>> ( decipher.decrypt(ciphertext)).encode('hex').upper()
'33B3DC87EDDD9B0F6A1F407D1491936533B3DC87EDDD9B0F6A1F407D1491936533B3DC87EDDD9B0F6A1F407D14919365'
"""
return python_Serpent(key,mode,IV,counter,segment_size)
 
class python_Serpent(BlockCipher):
def __init__(self,key,mode,IV,counter,segment_size):
if len(key) not in (16,24,32) and type(key) is not tuple:
raise ValueError("Key should be 128, 192 or 256 bits")
cipher_module = Serpent
self.blocksize = 16
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/python_PRESENT.py
0,0 → 1,94
from blockcipher import *
from pypresent import Present
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None,rounds=32):
"""Create a new cipher object
 
Wrapper for pure python implementation rijndael.py
 
key = raw string containing the key, AES-128..256 will be selected according to the key length
mode = python_PRESENT.MODE_ECB/CBC/CFB/OFB/CTR/CMAC, default is ECB
-> for every mode, except ECB and CTR, it is important to construct a seperate cipher for encryption and decryption
IV = IV as a raw string, default is "all zero" IV
-> needed for CBC, CFB and OFB mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
-> use a seperate counter object for the cipher and decipher: the counter is updated directly, not a copy
see CTR example further on in the docstring
rounds = amount of rounds
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
rounds = amount of rounds, default = 32
 
Notes:
- Always construct a seperate cipher object for encryption and decryption. Once a cipher object has been used for encryption,
it can't be used for decryption because it keeps a state (if necessary) for the IV.
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import python_PRESENT
 
ECB Test Vectors:
------------------
>>> key = "00000000000000000000".decode('hex')
>>> plain = "0000000000000000".decode('hex')
>>> cipher = python_PRESENT.new(key,python_PRESENT.MODE_ECB)
>>> cipher.encrypt(plain).encode('hex')
'5579c1387b228445'
>>> key = "00000000000000000000000000000000".decode('hex')
>>> plain = "0000000000000000".decode('hex')
>>> cipher = python_PRESENT.new(key,python_PRESENT.MODE_ECB,rounds=64)
>>> cipher.encrypt(plain).encode('hex')
'59a27d01607ebf05'
>>> key = "00000000000000000000".decode('hex')
>>> plain = "0000000000000000".decode('hex')
>>> cipher = python_PRESENT.new(key,python_PRESENT.MODE_ECB,rounds=64)
>>> cipher.encrypt(plain).encode('hex')
'13991dd588bc1288'
Test Vectors for maximum rounds supported by PRESENT reference C code:
-----------------------------------------------------------------------
>>> key = "0123456789abcdef0123".decode('hex')
>>> plain = "0123456789abcdef".decode('hex')
>>> cipher = python_PRESENT.new(key,python_PRESENT.MODE_ECB,rounds=65534)
>>> ciphertext = cipher.encrypt(plain)
>>> ciphertext.encode('hex')
'a140dc5d7175ca20'
>>> cipher.decrypt(ciphertext).encode('hex')
'0123456789abcdef'
>>> key = "0123456789abcdef0123456789abcdef".decode('hex')
>>> plain = "0123456789abcdef".decode('hex')
>>> cipher = python_PRESENT.new(key,python_PRESENT.MODE_ECB,rounds=65534)
>>> ciphertext = cipher.encrypt(plain)
>>> ciphertext.encode('hex')
'21007772e5d4ef14'
>>> cipher.decrypt(ciphertext).encode('hex')
'0123456789abcdef'
"""
return python_PRESENT(key,mode,IV,counter,rounds,segment_size)
 
class python_PRESENT(BlockCipher):
key_error_message = "Key should be 80 or 128 bits"
 
def __init__(self,key,mode,IV,counter,rounds,segment_size):
cipher_module = Present
args = {'rounds':rounds}
self.blocksize = 8
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size,args)
 
def keylen_valid(self,key):
return len(key) in (10,16)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/python_Twofish.py
0,0 → 1,55
from blockcipher import *
from pytwofish import Twofish
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None):
"""Create a new cipher object
 
Wrapper for pure python implementation pytwofish.py
 
key = raw string containing the key
-> when using XTS mode: the key should be a tuple containing the 2 keys needed
mode = python_Twofish.MODE_ECB/CBC/CFB/OFB/CTR/XTS/CMAC, default is ECB
-> for every mode, except ECB and CTR, it is important to construct a seperate cipher for encryption and decryption
IV = IV as a raw string, default is "all zero" IV
-> needed for CBC, CFB and OFB mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
-> use a seperate counter object for the cipher and decipher: the counter is updated directly, not a copy
see CTR example further on in the docstring
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import python_Twofish
 
EXAMPLE:
----------
http://www.schneier.com/code/ecb_ival.txt -> test vector I=5
 
>>> cipher = python_Twofish.new(('019F9809DE1711858FAAC3A3BA20FBC3').decode('hex'))
>>> (cipher.encrypt(('6363977DE839486297E661C6C9D668EB').decode('hex'))).encode('hex').upper()
'816D5BD0FAE35342BF2A7412C246F752'
>>> ( cipher.decrypt((_).decode('hex')) ).encode('hex').upper()
'6363977DE839486297E661C6C9D668EB'
"""
return python_Twofish(key,mode,IV,counter,segment_size)
 
class python_Twofish(BlockCipher):
def __init__(self,key,mode,IV,counter,segment_size):
if len(key) not in (16,24,32) and type(key) is not tuple:
raise ValueError("Key should be 128, 192 or 256 bits")
cipher_module = Twofish
self.blocksize = 16
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/pyDes.py
0,0 → 1,803
#############################################################################
# Documentation #
#############################################################################
 
# Author: Todd Whiteman
# Date: 12th September, 2005
# Verion: 1.2
# Homepage: http://twhiteman.netfirms.com/des.html
#
# This algorithm is a pure python implementation of the DES algorithm.
# It is in pure python to avoid portability issues, since most DES
# implementations are programmed in C (for performance reasons).
#
# Triple DES class is also implemented, utilising the DES base. Triple DES
# is either DES-EDE3 with a 24 byte key, or DES-EDE2 with a 16 byte key.
#
# See the README.txt that should come with this python module for the
# implementation methods used.
#
# Thanks to David Broadwell for ideas, comments and suggestions.
# Thanks to Mario Wolff for pointing out and debugging some triple des CBC errors.
#
"""A pure python implementation of the DES and TRIPLE DES encryption algorithms
 
pyDes.des(key, [mode], [IV])
pyDes.triple_des(key, [mode], [IV])
 
key -> String containing the encryption key. 8 bytes for DES, 16 or 24 bytes
for Triple DES
mode -> Optional argument for encryption type, can be either
pyDes.ECB (Electronic Code Book) or pyDes.CBC (Cypher Block Chaining)
IV -> Optional argument, must be supplied if using CBC mode. Must be 8 bytes
 
 
Example:
from pyDes import *
 
data = "Please encrypt my string"
k = des("DESCRYPT", " ", CBC, "\0\0\0\0\0\0\0\0")
d = k.encrypt(data)
print "Encypted string: " + d
print "Decypted string: " + k.decrypt(d)
 
See the module source (pyDes.py) for more examples of use.
You can slo run the pyDes.py file without and arguments to see a simple test.
 
Note: This code was not written for high-end systems needing a fast
implementation, but rather a handy portable solution with small usage.
 
"""
 
 
# Modes of crypting / cyphering
ECB = 0
CBC = 1
 
 
#############################################################################
# DES #
#############################################################################
class des:
"""DES encryption/decrytpion class
 
Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes.
 
pyDes.des(key,[mode], [IV])
 
key -> The encryption key string, must be exactly 8 bytes
mode -> Optional argument for encryption type, can be either pyDes.ECB
(Electronic Code Book), pyDes.CBC (Cypher Block Chaining)
IV -> Optional string argument, must be supplied if using CBC mode.
Must be 8 bytes in length.
"""
 
 
# Permutation and translation tables for DES
__pc1 = [56, 48, 40, 32, 24, 16, 8,
0, 57, 49, 41, 33, 25, 17,
9, 1, 58, 50, 42, 34, 26,
18, 10, 2, 59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14,
6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28,
20, 12, 4, 27, 19, 11, 3
]
 
# number left rotations of pc1
__left_rotations = [
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
]
 
# permuted choice key (table 2)
__pc2 = [
13, 16, 10, 23, 0, 4,
2, 27, 14, 5, 20, 9,
22, 18, 11, 3, 25, 7,
15, 6, 26, 19, 12, 1,
40, 51, 30, 36, 46, 54,
29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52,
45, 41, 49, 35, 28, 31
]
 
# initial permutation IP
__ip = [57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7,
56, 48, 40, 32, 24, 16, 8, 0,
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6
]
 
# Expansion table for turning 32 bit blocks into 48 bits
__expansion_table = [
31, 0, 1, 2, 3, 4,
3, 4, 5, 6, 7, 8,
7, 8, 9, 10, 11, 12,
11, 12, 13, 14, 15, 16,
15, 16, 17, 18, 19, 20,
19, 20, 21, 22, 23, 24,
23, 24, 25, 26, 27, 28,
27, 28, 29, 30, 31, 0
]
 
# The (in)famous S-boxes
__sbox = [
# S1
[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
 
# S2
[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
 
# S3
[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
 
# S4
[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
 
# S5
[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
 
# S6
[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
 
# S7
[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
 
# S8
[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],
]
 
 
# 32-bit permutation function P used on the output of the S-boxes
__p = [
15, 6, 19, 20, 28, 11,
27, 16, 0, 14, 22, 25,
4, 17, 30, 9, 1, 7,
23,13, 31, 26, 2, 8,
18, 12, 29, 5, 21, 10,
3, 24
]
 
# final permutation IP^-1
__fp = [
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25,
32, 0, 40, 8, 48, 16, 56, 24
]
 
# Type of crypting being done
ENCRYPT = 0x00
DECRYPT = 0x01
 
# Initialisation
def __init__(self, key, mode=ECB, IV=None):
if len(key) != 8:
raise ValueError("Invalid DES key size. Key must be exactly 8 bytes long.")
self.block_size = 8
self.key_size = 8
self.__padding = ''
 
# Set the passed in variables
self.setMode(mode)
if IV:
self.setIV(IV)
 
self.L = []
self.R = []
self.Kn = [ [0] * 48 ] * 16 # 16 48-bit keys (K1 - K16)
self.final = []
 
self.setKey(key)
 
 
def getKey(self):
"""getKey() -> string"""
return self.__key
 
def setKey(self, key):
"""Will set the crypting key for this object. Must be 8 bytes."""
self.__key = key
self.__create_sub_keys()
 
def getMode(self):
"""getMode() -> pyDes.ECB or pyDes.CBC"""
return self.__mode
 
def setMode(self, mode):
"""Sets the type of crypting mode, pyDes.ECB or pyDes.CBC"""
self.__mode = mode
 
def getIV(self):
"""getIV() -> string"""
return self.__iv
 
def setIV(self, IV):
"""Will set the Initial Value, used in conjunction with CBC mode"""
if not IV or len(IV) != self.block_size:
raise ValueError("Invalid Initial Value (IV), must be a multiple of " + str(self.block_size) + " bytes")
self.__iv = IV
 
def getPadding(self):
"""getPadding() -> string of length 1. Padding character."""
return self.__padding
 
def __String_to_BitList(self, data):
"""Turn the string data, into a list of bits (1, 0)'s"""
l = len(data) * 8
result = [0] * l
pos = 0
for c in data:
i = 7
ch = ord(c)
while i >= 0:
if ch & (1 << i) != 0:
result[pos] = 1
else:
result[pos] = 0
pos += 1
i -= 1
 
return result
 
def __BitList_to_String(self, data):
"""Turn the list of bits -> data, into a string"""
result = ''
pos = 0
c = 0
while pos < len(data):
c += data[pos] << (7 - (pos % 8))
if (pos % 8) == 7:
result += chr(c)
c = 0
pos += 1
 
return result
 
def __permutate(self, table, block):
"""Permutate this block with the specified table"""
return map(lambda x: block[x], table)
 
# Transform the secret key, so that it is ready for data processing
# Create the 16 subkeys, K[1] - K[16]
def __create_sub_keys(self):
"""Create the 16 subkeys K[1] to K[16] from the given key"""
key = self.__permutate(des.__pc1, self.__String_to_BitList(self.getKey()))
i = 0
# Split into Left and Right sections
self.L = key[:28]
self.R = key[28:]
while i < 16:
j = 0
# Perform circular left shifts
while j < des.__left_rotations[i]:
self.L.append(self.L[0])
del self.L[0]
 
self.R.append(self.R[0])
del self.R[0]
 
j += 1
 
# Create one of the 16 subkeys through pc2 permutation
self.Kn[i] = self.__permutate(des.__pc2, self.L + self.R)
 
i += 1
 
# Main part of the encryption algorithm, the number cruncher :)
def __des_crypt(self, block, crypt_type):
"""Crypt the block of data through DES bit-manipulation"""
block = self.__permutate(des.__ip, block)
self.L = block[:32]
self.R = block[32:]
 
# Encryption starts from Kn[1] through to Kn[16]
if crypt_type == des.ENCRYPT:
iteration = 0
iteration_adjustment = 1
# Decryption starts from Kn[16] down to Kn[1]
else:
iteration = 15
iteration_adjustment = -1
 
i = 0
while i < 16:
# Make a copy of R[i-1], this will later become L[i]
tempR = self.R[:]
 
# Permutate R[i - 1] to start creating R[i]
self.R = self.__permutate(des.__expansion_table, self.R)
 
# Exclusive or R[i - 1] with K[i], create B[1] to B[8] whilst here
self.R = map(lambda x, y: x ^ y, self.R, self.Kn[iteration])
B = [self.R[:6], self.R[6:12], self.R[12:18], self.R[18:24], self.R[24:30], self.R[30:36], self.R[36:42], self.R[42:]]
# Optimization: Replaced below commented code with above
#j = 0
#B = []
#while j < len(self.R):
# self.R[j] = self.R[j] ^ self.Kn[iteration][j]
# j += 1
# if j % 6 == 0:
# B.append(self.R[j-6:j])
 
# Permutate B[1] to B[8] using the S-Boxes
j = 0
Bn = [0] * 32
pos = 0
while j < 8:
# Work out the offsets
m = (B[j][0] << 1) + B[j][5]
n = (B[j][1] << 3) + (B[j][2] << 2) + (B[j][3] << 1) + B[j][4]
 
# Find the permutation value
v = des.__sbox[j][(m << 4) + n]
 
# Turn value into bits, add it to result: Bn
Bn[pos] = (v & 8) >> 3
Bn[pos + 1] = (v & 4) >> 2
Bn[pos + 2] = (v & 2) >> 1
Bn[pos + 3] = v & 1
 
pos += 4
j += 1
 
# Permutate the concatination of B[1] to B[8] (Bn)
self.R = self.__permutate(des.__p, Bn)
 
# Xor with L[i - 1]
self.R = map(lambda x, y: x ^ y, self.R, self.L)
# Optimization: This now replaces the below commented code
#j = 0
#while j < len(self.R):
# self.R[j] = self.R[j] ^ self.L[j]
# j += 1
 
# L[i] becomes R[i - 1]
self.L = tempR
 
i += 1
iteration += iteration_adjustment
 
# Final permutation of R[16]L[16]
self.final = self.__permutate(des.__fp, self.R + self.L)
return self.final
 
 
# Data to be encrypted/decrypted
def crypt(self, data, crypt_type):
"""Crypt the data in blocks, running it through des_crypt()"""
 
# Error check the data
if not data:
return ''
if len(data) % self.block_size != 0:
if crypt_type == des.DECRYPT: # Decryption must work on 8 byte blocks
raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n.")
if not self.getPadding():
raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n. Try setting the optional padding character")
else:
data += (self.block_size - (len(data) % self.block_size)) * self.getPadding()
# print "Len of data: %f" % (len(data) / self.block_size)
 
if self.getMode() == CBC:
if self.getIV():
iv = self.__String_to_BitList(self.getIV())
else:
raise ValueError("For CBC mode, you must supply the Initial Value (IV) for ciphering")
 
# Split the data into blocks, crypting each one seperately
i = 0
dict = {}
result = []
#cached = 0
#lines = 0
while i < len(data):
# Test code for caching encryption results
#lines += 1
#if dict.has_key(data[i:i+8]):
#print "Cached result for: %s" % data[i:i+8]
# cached += 1
# result.append(dict[data[i:i+8]])
# i += 8
# continue
 
block = self.__String_to_BitList(data[i:i+8])
 
# Xor with IV if using CBC mode
if self.getMode() == CBC:
if crypt_type == des.ENCRYPT:
block = map(lambda x, y: x ^ y, block, iv)
#j = 0
#while j < len(block):
# block[j] = block[j] ^ iv[j]
# j += 1
 
processed_block = self.__des_crypt(block, crypt_type)
 
if crypt_type == des.DECRYPT:
processed_block = map(lambda x, y: x ^ y, processed_block, iv)
#j = 0
#while j < len(processed_block):
# processed_block[j] = processed_block[j] ^ iv[j]
# j += 1
iv = block
else:
iv = processed_block
else:
processed_block = self.__des_crypt(block, crypt_type)
 
 
# Add the resulting crypted block to our list
#d = self.__BitList_to_String(processed_block)
#result.append(d)
result.append(self.__BitList_to_String(processed_block))
#dict[data[i:i+8]] = d
i += 8
 
# print "Lines: %d, cached: %d" % (lines, cached)
 
# Remove the padding from the last block
if crypt_type == des.DECRYPT and self.getPadding():
#print "Removing decrypt pad"
s = result[-1]
while s[-1] == self.getPadding():
s = s[:-1]
result[-1] = s
 
# Return the full crypted string
return ''.join(result)
 
def encrypt(self, data, pad=''):
"""encrypt(data, [pad]) -> string
 
data : String to be encrypted
pad : Optional argument for encryption padding. Must only be one byte
 
The data must be a multiple of 8 bytes and will be encrypted
with the already specified key. Data does not have to be a
multiple of 8 bytes if the padding character is supplied, the
data will then be padded to a multiple of 8 bytes with this
pad character.
"""
self.__padding = pad
return self.crypt(data, des.ENCRYPT)
 
def decrypt(self, data, pad=''):
"""decrypt(data, [pad]) -> string
 
data : String to be encrypted
pad : Optional argument for decryption padding. Must only be one byte
 
The data must be a multiple of 8 bytes and will be decrypted
with the already specified key. If the optional padding character
is supplied, then the un-encypted data will have the padding characters
removed from the end of the string. This pad removal only occurs on the
last 8 bytes of the data (last data block).
"""
self.__padding = pad
return self.crypt(data, des.DECRYPT)
 
 
#############################################################################
# Triple DES #
#############################################################################
class triple_des:
"""Triple DES encryption/decrytpion class
 
This algorithm uses the DES-EDE3 (when a 24 byte key is supplied) or
the DES-EDE2 (when a 16 byte key is supplied) encryption methods.
Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes.
 
pyDes.des(key, [mode], [IV])
 
key -> The encryption key string, must be either 16 or 24 bytes long
mode -> Optional argument for encryption type, can be either pyDes.ECB
(Electronic Code Book), pyDes.CBC (Cypher Block Chaining)
IV -> Optional string argument, must be supplied if using CBC mode.
Must be 8 bytes in length.
"""
def __init__(self, key, mode=ECB, IV=None):
self.block_size = 8
self.setMode(mode)
self.__padding = ''
self.__iv = IV
self.setKey(key)
 
def getKey(self):
"""getKey() -> string"""
return self.__key
 
def setKey(self, key):
"""Will set the crypting key for this object. Either 16 or 24 bytes long."""
self.key_size = 24 # Use DES-EDE3 mode
if len(key) != self.key_size:
if len(key) == 16: # Use DES-EDE2 mode
self.key_size = 16
else:
raise ValueError("Invalid triple DES key size. Key must be either 16 or 24 bytes long")
if self.getMode() == CBC:
if not self.getIV():
# Use the first 8 bytes of the key
self.setIV(key[:self.block_size])
if len(self.getIV()) != self.block_size:
raise ValueError("Invalid IV, must be 8 bytes in length")
self.__key1 = des(key[:8], self.getMode(), self.getIV())
self.__key2 = des(key[8:16], self.getMode(), self.getIV())
if self.key_size == 16:
self.__key3 = self.__key1
else:
self.__key3 = des(key[16:], self.getMode(), self.getIV())
self.__key = key
 
def getMode(self):
"""getMode() -> pyDes.ECB or pyDes.CBC"""
return self.__mode
 
def setMode(self, mode):
"""Sets the type of crypting mode, pyDes.ECB or pyDes.CBC"""
self.__mode = mode
 
def getIV(self):
"""getIV() -> string"""
return self.__iv
 
def setIV(self, IV):
"""Will set the Initial Value, used in conjunction with CBC mode"""
self.__iv = IV
 
def encrypt(self, data, pad=''):
"""encrypt(data, [pad]) -> string
 
data : String to be encrypted
pad : Optional argument for encryption padding. Must only be one byte
 
The data must be a multiple of 8 bytes and will be encrypted
with the already specified key. Data does not have to be a
multiple of 8 bytes if the padding character is supplied, the
data will then be padded to a multiple of 8 bytes with this
pad character.
"""
if self.getMode() == CBC:
self.__key1.setIV(self.getIV())
self.__key2.setIV(self.getIV())
self.__key3.setIV(self.getIV())
i = 0
result = []
while i < len(data):
block = self.__key1.encrypt(data[i:i+8], pad)
block = self.__key2.decrypt(block)
block = self.__key3.encrypt(block)
self.__key1.setIV(block)
self.__key2.setIV(block)
self.__key3.setIV(block)
result.append(block)
i += 8
return ''.join(result)
else:
data = self.__key1.encrypt(data, pad)
data = self.__key2.decrypt(data)
return self.__key3.encrypt(data)
 
def decrypt(self, data, pad=''):
"""decrypt(data, [pad]) -> string
 
data : String to be encrypted
pad : Optional argument for decryption padding. Must only be one byte
 
The data must be a multiple of 8 bytes and will be decrypted
with the already specified key. If the optional padding character
is supplied, then the un-encypted data will have the padding characters
removed from the end of the string. This pad removal only occurs on the
last 8 bytes of the data (last data block).
"""
if self.getMode() == CBC:
self.__key1.setIV(self.getIV())
self.__key2.setIV(self.getIV())
self.__key3.setIV(self.getIV())
i = 0
result = []
while i < len(data):
iv = data[i:i+8]
block = self.__key3.decrypt(iv)
block = self.__key2.encrypt(block)
block = self.__key1.decrypt(block, pad)
self.__key1.setIV(iv)
self.__key2.setIV(iv)
self.__key3.setIV(iv)
result.append(block)
i += 8
return ''.join(result)
else:
data = self.__key3.decrypt(data)
data = self.__key2.encrypt(data)
return self.__key1.decrypt(data, pad)
 
 
#############################################################################
# Examples #
#############################################################################
def example_triple_des():
from time import time
 
# Utility module
from binascii import unhexlify as unhex
 
# example shows triple-des encryption using the des class
print "Example of triple DES encryption in default ECB mode (DES-EDE3)\n"
 
print "Triple des using the des class (3 times)"
t = time()
k1 = des(unhex("133457799BBCDFF1"))
k2 = des(unhex("1122334455667788"))
k3 = des(unhex("77661100DD223311"))
d = "Triple DES test string, to be encrypted and decrypted..."
print "Key1: %s" % k1.getKey()
print "Key2: %s" % k2.getKey()
print "Key3: %s" % k3.getKey()
print "Data: %s" % d
 
e1 = k1.encrypt(d)
e2 = k2.decrypt(e1)
e3 = k3.encrypt(e2)
print "Encrypted: " + e3
 
d3 = k3.decrypt(e3)
d2 = k2.encrypt(d3)
d1 = k1.decrypt(d2)
print "Decrypted: " + d1
print "DES time taken: %f (%d crypt operations)" % (time() - t, 6 * (len(d) / 8))
print ""
 
# Example below uses the triple-des class to achieve the same as above
print "Now using triple des class"
t = time()
t1 = triple_des(unhex("133457799BBCDFF1112233445566778877661100DD223311"))
print "Key: %s" % t1.getKey()
print "Data: %s" % d
 
td1 = t1.encrypt(d)
print "Encrypted: " + td1
 
td2 = t1.decrypt(td1)
print "Decrypted: " + td2
 
print "Triple DES time taken: %f (%d crypt operations)" % (time() - t, 6 * (len(d) / 8))
 
def example_des():
from time import time
 
# example of DES encrypting in CBC mode with the IV of "\0\0\0\0\0\0\0\0"
print "Example of DES encryption using CBC mode\n"
t = time()
k = des("DESCRYPT", CBC, "\0\0\0\0\0\0\0\0")
data = "DES encryption algorithm"
print "Key : " + k.getKey()
print "Data : " + data
 
d = k.encrypt(data)
print "Encrypted: " + d
 
d = k.decrypt(d)
print "Decrypted: " + d
print "DES time taken: %f (6 crypt operations)" % (time() - t)
print ""
 
def __test__():
example_des()
example_triple_des()
 
 
def __fulltest__():
# This should not produce any unexpected errors or exceptions
from binascii import unhexlify as unhex
from binascii import hexlify as dohex
 
__test__()
print ""
 
k = des("\0\0\0\0\0\0\0\0", CBC, "\0\0\0\0\0\0\0\0")
d = k.encrypt("DES encryption algorithm")
if k.decrypt(d) != "DES encryption algorithm":
print "Test 1 Error: Unencypted data block does not match start data"
 
k = des("\0\0\0\0\0\0\0\0", CBC, "\0\0\0\0\0\0\0\0")
d = k.encrypt("Default string of text", '*')
if k.decrypt(d, "*") != "Default string of text":
print "Test 2 Error: Unencypted data block does not match start data"
 
k = des("\r\n\tABC\r\n")
d = k.encrypt("String to Pad", '*')
if k.decrypt(d) != "String to Pad***":
print "'%s'" % k.decrypt(d)
print "Test 3 Error: Unencypted data block does not match start data"
 
k = des("\r\n\tABC\r\n")
d = k.encrypt(unhex("000102030405060708FF8FDCB04080"), unhex("44"))
if k.decrypt(d, unhex("44")) != unhex("000102030405060708FF8FDCB04080"):
print "Test 4a Error: Unencypted data block does not match start data"
if k.decrypt(d) != unhex("000102030405060708FF8FDCB0408044"):
print "Test 4b Error: Unencypted data block does not match start data"
 
k = triple_des("MyDesKey\r\n\tABC\r\n0987*543")
d = k.encrypt(unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080"))
if k.decrypt(d) != unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080"):
print "Test 5 Error: Unencypted data block does not match start data"
 
k = triple_des("\r\n\tABC\r\n0987*543")
d = k.encrypt(unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080"))
if k.decrypt(d) != unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080"):
print "Test 6 Error: Unencypted data block does not match start data"
 
k = triple_des("MyDesKey\r\n\tABC\r\n0987*54B", CBC, "12341234")
d = k.encrypt(unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080"))
if k.decrypt(d) != unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080"):
print "Test 7 Error: Triple DES CBC failed."
 
k = triple_des("MyDesKey\r\n\tABC\r\n0987*54B", CBC, "12341234")
d = k.encrypt(unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDC"), '.')
if k.decrypt(d, '.') != unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDC"):
print "Test 8 Error: Triple DES CBC with padding failed."
 
def __filetest__():
from time import time
 
f = open("pyDes.py", "rb+")
d = f.read()
f.close()
 
t = time()
k = des("MyDESKey")
 
d = k.encrypt(d, " ")
f = open("pyDes.py.enc", "wb+")
f.write(d)
f.close()
 
d = k.decrypt(d, " ")
f = open("pyDes.py.dec", "wb+")
f.write(d)
f.close()
print "DES file test time: %f" % (time() - t)
 
def __profile__():
import profile
profile.run('__fulltest__()')
#profile.run('__filetest__()')
 
if __name__ == '__main__':
__test__()
#__fulltest__()
#__filetest__()
#__profile__()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/blockcipher.py
0,0 → 1,594
# =============================================================================
# Copyright (c) 2008 Christophe Oosterlynck <christophe.oosterlynck_AT_gmail.com>
# & NXP ( Philippe Teuwen <philippe.teuwen_AT_nxp.com> )
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# =============================================================================
from ..Util import util
from array import array
from ..Util import padding
 
MODE_ECB = 1
MODE_CBC = 2
MODE_CFB = 3
MODE_OFB = 5
MODE_CTR = 6
MODE_XTS = 7
MODE_CMAC = 8
 
class BlockCipher():
""" Base class for all blockciphers
"""
 
key_error_message = "Wrong key size" #should be overwritten in child classes
 
def __init__(self,key,mode,IV,counter,cipher_module,segment_size,args={}):
# Cipher classes inheriting from this one take care of:
# self.blocksize
# self.cipher
self.key = key
self.mode = mode
self.cache = ''
self.ed = None
 
if 'keylen_valid' in dir(self): #wrappers for pycrypto functions don't have this function
if not self.keylen_valid(key) and type(key) is not tuple:
raise ValueError(self.key_error_message)
 
if IV == None:
self.IV = '\x00'*self.blocksize
else:
self.IV = IV
if segment_size == None:
segment_size = 8
 
if mode <> MODE_XTS:
self.cipher = cipher_module(self.key,**args)
if mode == MODE_ECB:
self.chain = ECB(self.cipher, self.blocksize)
elif mode == MODE_CBC:
if len(self.IV) <> self.blocksize:
raise Exception,"the IV length should be %i bytes"%self.blocksize
self.chain = CBC(self.cipher, self.blocksize,self.IV)
elif mode == MODE_CFB:
if len(self.IV) <> self.blocksize:
raise Exception,"the IV length should be %i bytes"%self.blocksize
if segment_size > self.blocksize*8 or segment_size%8 <> 0:
# current CFB implementation doesn't support bit level acces => segment_size should be multiple of bytes
raise ValueError,"segment size should be a multiple of 8 bits between 8 and %i"%(self.blocksize*8)
self.chain = CFB(self.cipher, self.blocksize,self.IV,segment_size)
elif mode == MODE_OFB:
if len(self.IV) <> self.blocksize:
raise ValueError("the IV length should be %i bytes"%self.blocksize)
self.chain = OFB(self.cipher, self.blocksize,self.IV)
elif mode == MODE_CTR:
if (counter == None) or not callable(counter):
raise Exception,"Supply a valid counter object for the CTR mode"
self.chain = CTR(self.cipher,self.blocksize,counter)
elif mode == MODE_XTS:
if self.blocksize <> 16:
raise Exception,'XTS only works with blockcipher that have a 128-bit blocksize'
if not(type(key) == tuple and len(key) == 2):
raise Exception,'Supply two keys as a tuple when using XTS'
if 'keylen_valid' in dir(self): #wrappers for pycrypto functions don't have this function
if not self.keylen_valid(key[0]) or not self.keylen_valid(key[1]):
raise ValueError(self.key_error_message)
self.cipher = cipher_module(self.key[0],**args)
self.cipher2 = cipher_module(self.key[1],**args)
self.chain = XTS(self.cipher, self.cipher2)
elif mode == MODE_CMAC:
if self.blocksize not in (8,16):
raise Exception,'CMAC only works with blockcipher that have a 64 or 128-bit blocksize'
self.chain = CMAC(self.cipher,self.blocksize,self.IV)
else:
raise Exception,"Unknown chaining mode!"
 
def encrypt(self,plaintext,n=''):
"""Encrypt some plaintext
 
plaintext = a string of binary data
n = the 'tweak' value when the chaining mode is XTS
 
The encrypt function will encrypt the supplied plaintext.
The behavior varies slightly depending on the chaining mode.
 
ECB, CBC:
---------
When the supplied plaintext is not a multiple of the blocksize
of the cipher, then the remaining plaintext will be cached.
The next time the encrypt function is called with some plaintext,
the new plaintext will be concatenated to the cache and then
cache+plaintext will be encrypted.
 
CFB, OFB, CTR:
--------------
When the chaining mode allows the cipher to act as a stream cipher,
the encrypt function will always encrypt all of the supplied
plaintext immediately. No cache will be kept.
 
XTS:
----
Because the handling of the last two blocks is linked,
it needs the whole block of plaintext to be supplied at once.
Every encrypt function called on a XTS cipher will output
an encrypted block based on the current supplied plaintext block.
 
CMAC:
-----
Everytime the function is called, the hash from the input data is calculated.
No finalizing needed.
The hashlength is equal to block size of the used block cipher.
"""
#self.ed = 'e' if chain is encrypting, 'd' if decrypting,
# None if nothing happened with the chain yet
#assert self.ed in ('e',None)
# makes sure you don't encrypt with a cipher that has started decrypting
self.ed = 'e'
if self.mode == MODE_XTS:
# data sequence number (or 'tweak') has to be provided when in XTS mode
return self.chain.update(plaintext,'e',n)
else:
return self.chain.update(plaintext,'e')
 
def decrypt(self,ciphertext,n=''):
"""Decrypt some ciphertext
 
ciphertext = a string of binary data
n = the 'tweak' value when the chaining mode is XTS
 
The decrypt function will decrypt the supplied ciphertext.
The behavior varies slightly depending on the chaining mode.
 
ECB, CBC:
---------
When the supplied ciphertext is not a multiple of the blocksize
of the cipher, then the remaining ciphertext will be cached.
The next time the decrypt function is called with some ciphertext,
the new ciphertext will be concatenated to the cache and then
cache+ciphertext will be decrypted.
 
CFB, OFB, CTR:
--------------
When the chaining mode allows the cipher to act as a stream cipher,
the decrypt function will always decrypt all of the supplied
ciphertext immediately. No cache will be kept.
 
XTS:
----
Because the handling of the last two blocks is linked,
it needs the whole block of ciphertext to be supplied at once.
Every decrypt function called on a XTS cipher will output
a decrypted block based on the current supplied ciphertext block.
 
CMAC:
-----
Mode not supported for decryption as this does not make sense.
"""
#self.ed = 'e' if chain is encrypting, 'd' if decrypting,
# None if nothing happened with the chain yet
#assert self.ed in ('d',None)
# makes sure you don't decrypt with a cipher that has started encrypting
self.ed = 'd'
if self.mode == MODE_XTS:
# data sequence number (or 'tweak') has to be provided when in XTS mode
return self.chain.update(ciphertext,'d',n)
else:
return self.chain.update(ciphertext,'d')
 
def final(self,padfct=padding.PKCS7):
# TODO: after calling final, reset the IV? so the cipher is as good as new?
"""Finalizes the encryption by padding the cache
 
padfct = padding function
import from CryptoPlus.Util.padding
 
For ECB, CBC: the remaining bytes in the cache will be padded and
encrypted.
For OFB,CFB, CTR: an encrypted padding will be returned, making the
total outputed bytes since construction of the cipher
a multiple of the blocksize of that cipher.
 
If the cipher has been used for decryption, the final function won't do
anything. You have to manually unpad if necessary.
 
After finalization, the chain can still be used but the IV, counter etc
aren't reset but just continue as they were after the last step (finalization step).
"""
assert self.mode not in (MODE_XTS, MODE_CMAC) # finalizing (=padding) doesn't make sense when in XTS or CMAC mode
if self.ed == 'e':
# when the chain is in encryption mode, finalizing will pad the cache and encrypt this last block
if self.mode in (MODE_OFB,MODE_CFB,MODE_CTR):
dummy = '0'*(self.chain.totalbytes%self.blocksize) # a dummy string that will be used to get a valid padding
else: #ECB, CBC
dummy = self.chain.cache
pad = padfct(dummy,padding.PAD,self.blocksize)[len(dummy):] # construct the padding necessary
return self.chain.update(pad,'e') # supply the padding to the update function => chain cache will be "cache+padding"
else:
# final function doesn't make sense when decrypting => padding should be removed manually
pass
 
class ECB:
"""ECB chaining mode
"""
def __init__(self, codebook, blocksize):
self.cache = ''
self.codebook = codebook
self.blocksize = blocksize
 
def update(self, data, ed):
"""Processes the given ciphertext/plaintext
 
Inputs:
data: raw string of any length
ed: 'e' for encryption, 'd' for decryption
Output:
processed raw string block(s), if any
 
When the supplied data is not a multiple of the blocksize
of the cipher, then the remaining input data will be cached.
The next time the update function is called with some data,
the new data will be concatenated to the cache and then
cache+data will be processed and full blocks will be outputted.
"""
output_blocks = []
self.cache += data
if len(self.cache) < self.blocksize:
return ''
for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
#the only difference between encryption/decryption in the chain is the cipher block
if ed == 'e':
output_blocks.append(self.codebook.encrypt( self.cache[i:i + self.blocksize] ))
else:
output_blocks.append(self.codebook.decrypt( self.cache[i:i + self.blocksize] ))
self.cache = self.cache[i+self.blocksize:]
return ''.join(output_blocks)
 
class CBC:
"""CBC chaining mode
"""
def __init__(self, codebook, blocksize, IV):
self.IV = IV
self.cache = ''
self.codebook = codebook
self.blocksize = blocksize
 
def update(self, data, ed):
"""Processes the given ciphertext/plaintext
 
Inputs:
data: raw string of any length
ed: 'e' for encryption, 'd' for decryption
Output:
processed raw string block(s), if any
 
When the supplied data is not a multiple of the blocksize
of the cipher, then the remaining input data will be cached.
The next time the update function is called with some data,
the new data will be concatenated to the cache and then
cache+data will be processed and full blocks will be outputted.
"""
if ed == 'e':
encrypted_blocks = ''
self.cache += data
if len(self.cache) < self.blocksize:
return ''
for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
self.IV = self.codebook.encrypt(util.xorstring(self.cache[i:i+self.blocksize],self.IV))
encrypted_blocks += self.IV
self.cache = self.cache[i+self.blocksize:]
return encrypted_blocks
else:
decrypted_blocks = ''
self.cache += data
if len(self.cache) < self.blocksize:
return ''
for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
plaintext = util.xorstring(self.IV,self.codebook.decrypt(self.cache[i:i + self.blocksize]))
self.IV = self.cache[i:i + self.blocksize]
decrypted_blocks+=plaintext
self.cache = self.cache[i+self.blocksize:]
return decrypted_blocks
 
class CFB:
# TODO: bit access instead of only byte level access
"""CFB Chaining Mode
 
Can be accessed as a stream cipher.
"""
 
def __init__(self, codebook, blocksize, IV,segment_size):
self.codebook = codebook
self.IV = IV
self.blocksize = blocksize
self.segment_size = segment_size/8
self.keystream = []
self.totalbytes = 0
def update(self, data, ed):
"""Processes the given ciphertext/plaintext
 
Inputs:
data: raw string of any multiple of bytes
ed: 'e' for encryption, 'd' for decryption
Output:
processed raw string
 
The encrypt/decrypt functions will always process all of the supplied
input data immediately. No cache will be kept.
"""
output = list(data)
 
for i in xrange(len(data)):
if ed =='e':
if len(self.keystream) == 0:
block = self.codebook.encrypt(self.IV)
self.keystream = list(block)[:self.segment_size] # keystream consists of the s MSB's
self.IV = self.IV[self.segment_size:] # keeping (b-s) LSB's
output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0)))
self.IV += output[i] # the IV for the next block in the chain is being built byte per byte as the ciphertext flows in
else:
if len(self.keystream) == 0:
block = self.codebook.encrypt(self.IV)
self.keystream = list(block)[:self.segment_size]
self.IV = self.IV[self.segment_size:]
self.IV += output[i]
output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0)))
self.totalbytes += len(output)
return ''.join(output)
 
class OFB:
"""OFB Chaining Mode
 
Can be accessed as a stream cipher.
"""
def __init__(self, codebook, blocksize, IV):
self.codebook = codebook
self.IV = IV
self.blocksize = blocksize
self.keystream = []
self.totalbytes = 0
def update(self, data, ed):
"""Processes the given ciphertext/plaintext
 
Inputs:
data: raw string of any multiple of bytes
ed: 'e' for encryption, 'd' for decryption
Output:
processed raw string
 
The encrypt/decrypt functions will always process all of the supplied
input data immediately. No cache will be kept.
"""
#no difference between encryption and decryption mode
n = len(data)
blocksize = self.blocksize
output = list(data)
 
for i in xrange(n):
if len(self.keystream) == 0: #encrypt a new counter block when the current keystream is fully used
self.IV = self.codebook.encrypt(self.IV)
self.keystream = list(self.IV)
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"
self.totalbytes += len(output)
return ''.join(output)
 
class CTR:
"""CTR Chaining Mode
 
Can be accessed as a stream cipher.
"""
# initial counter value can be choosen, decryption always starts from beginning
# -> you can start from anywhere yourself: just feed the cipher encoded blocks and feed a counter with the corresponding value
def __init__(self, codebook, blocksize, counter):
self.codebook = codebook
self.counter = counter
self.blocksize = blocksize
self.keystream = [] #holds the output of the current encrypted counter value
self.totalbytes = 0
 
def update(self, data, ed):
"""Processes the given ciphertext/plaintext
 
Inputs:
data: raw string of any multiple of bytes
ed: 'e' for encryption, 'd' for decryption
Output:
processed raw string
 
The encrypt/decrypt functions will always process all of the supplied
input data immediately. No cache will be kept.
"""
# no need for the encryption/decryption distinction: both are the same
n = len(data)
blocksize = self.blocksize
 
output = list(data)
for i in xrange(n):
if len(self.keystream) == 0: #encrypt a new counter block when the current keystream is fully used
block = self.codebook.encrypt(self.counter())
self.keystream = list(block)
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"
self.totalbytes += len(output)
return ''.join(output)
 
class XTS:
"""XTS Chaining Mode
Usable with blockciphers with a 16-byte blocksize
"""
# TODO: allow other blocksizes besides 16bytes?
def __init__(self,codebook1, codebook2):
self.cache = ''
self.codebook1 = codebook1
self.codebook2 = codebook2
 
def update(self, data, ed,tweak=''):
# supply n as a raw string
# tweak = data sequence number
"""Perform a XTS encrypt/decrypt operation.
 
Because the handling of the last two blocks is linked,
it needs the whole block of ciphertext to be supplied at once.
Every decrypt function called on a XTS cipher will output
a decrypted block based on the current supplied ciphertext block.
"""
output = ''
assert len(data) > 15, "At least one block of 128 bits needs to be supplied"
assert len(data) < 128*pow(2,20)
 
# initializing T
# e_k2_n = E_K2(tweak)
e_k2_n = self.codebook2.encrypt(tweak+ '\x00' * (16-len(tweak)))[::-1]
self.T = util.string2number(e_k2_n)
 
i=0
while i < ((len(data) // 16)-1): #Decrypt all the blocks but one last full block and opt one last partial block
# C = E_K1(P xor T) xor T
output += self.__xts_step(ed,data[i*16:(i+1)*16],self.T)
# T = E_K2(n) mul (a pow i)
self.__T_update()
i+=1
 
# Check if the data supplied is a multiple of 16 bytes -> one last full block and we're done
if len(data[i*16:]) == 16:
# C = E_K1(P xor T) xor T
output += self.__xts_step(ed,data[i*16:(i+1)*16],self.T)
# T = E_K2(n) mul (a pow i)
self.__T_update()
else:
T_temp = [self.T]
self.__T_update()
T_temp.append(self.T)
if ed=='d':
# Permutation of the last two indexes
T_temp.reverse()
# Decrypt/Encrypt the last two blocks when data is not a multiple of 16 bytes
Cm1 = data[i*16:(i+1)*16]
Cm = data[(i+1)*16:]
PP = self.__xts_step(ed,Cm1,T_temp[0])
Cp = PP[len(Cm):]
Pm = PP[:len(Cm)]
CC = Cm+Cp
Pm1 = self.__xts_step(ed,CC,T_temp[1])
output += Pm1 + Pm
return output
 
def __xts_step(self,ed,tocrypt,T):
T_string = util.number2string_N(T,16)[::-1]
# C = E_K1(P xor T) xor T
if ed == 'd':
return util.xorstring(T_string, self.codebook1.decrypt(util.xorstring(T_string, tocrypt)))
else:
return util.xorstring(T_string, self.codebook1.encrypt(util.xorstring(T_string, tocrypt)))
 
def __T_update(self):
# Used for calculating T for a certain step using the T value from the previous step
self.T = self.T << 1
# if (Cout)
if self.T >> (8*16):
#T[0] ^= GF_128_FDBK;
self.T = self.T ^ 0x100000000000000000000000000000087L
 
 
class CMAC:
"""CMAC chaining mode
 
Supports every cipher with a blocksize available
in the list CMAC.supported_blocksizes.
The hashlength is equal to block size of the used block cipher.
Usable with blockciphers with a 8 or 16-byte blocksize
"""
# TODO: move to hash module?
# TODO: change update behaviour to .update() and .digest() as for all hash modules?
# -> other hash functions in pycrypto: calling update, concatenates current input with previous input and hashes everything
__Rb_dictionary = {64:0x000000000000001b,128:0x00000000000000000000000000000087}
supported_blocksizes = __Rb_dictionary.keys()
def __init__(self,codebook,blocksize,IV):
# Purpose of init: calculate Lu & Lu2
#blocksize (in bytes): to select the Rb constant in the dictionary
#Rb as a dictionary: adding support for other blocksizes is easy
self.cache=''
self.blocksize = blocksize
self.codebook = codebook
self.IV = IV
 
#Rb_dictionary: holds values for Rb for different blocksizes
# values for 64 and 128 bits found here: http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
# explanation from: http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
# Rb is a representation of a certain irreducible binary polynomial of degree b, namely,
# the lexicographically first among all such polynomials with the minimum possible number of
# nonzero terms. If this polynomial is expressed as ub+cb-1ub-1+...+c2u2+c1u+c0, where the
# coefficients cb-1, cb-2, ..., c2, c1, c0 are either 0 or 1, then Rb is the bit string cb-1cb-2...c2c1c0.
 
self.Rb = self.__Rb_dictionary[blocksize*8]
 
mask1 = int(('\xff'*blocksize).encode('hex'),16)
mask2 = int(('\x80' + '\x00'*(blocksize-1) ).encode('hex'),16)
 
L = int(self.codebook.encrypt('\x00'*blocksize).encode('hex'),16)
 
if L & mask2:
Lu = ((L << 1) & mask1) ^ self.Rb
else:
Lu = L << 1
Lu = Lu & mask1
 
if Lu & mask2:
Lu2 = ((Lu << 1) & mask1)^ self.Rb
else:
Lu2 = Lu << 1
Lu2 = Lu2 & mask1
 
self.Lu =util.number2string_N(Lu,self.blocksize)
self.Lu2=util.number2string_N(Lu2,self.blocksize)
 
def update(self, data, ed):
"""Processes the given ciphertext/plaintext
 
Inputs:
data: raw string of any length
ed: 'e' for encryption, 'd' for decryption
Output:
hashed data as raw string
 
This is not really an update function:
Everytime the function is called, the hash from the input data is calculated.
No finalizing needed.
"""
assert ed == 'e'
blocksize = self.blocksize
 
m = (len(data)+blocksize-1)/blocksize #m = amount of datablocks
i=0
for i in range(1,m):
self.IV = self.codebook.encrypt( util.xorstring(data[(i-1)*blocksize:(i)*blocksize],self.IV) )
 
if len(data[(i)*blocksize:])==blocksize:
X = util.xorstring(util.xorstring(data[(i)*blocksize:],self.IV),self.Lu)
else:
tmp = data[(i)*blocksize:] + '\x80' + '\x00'*(blocksize - len(data[(i)*blocksize:])-1)
X = util.xorstring(util.xorstring(tmp,self.IV),self.Lu2)
 
T = self.codebook.encrypt(X)
return T
 
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/pyblowfish.py
0,0 → 1,513
#
# blowfish.py
# Copyright (C) Michael Gilfix <mgilfix@gmail.com>
#
# This module is open source; you can redistribute it and/or
# modify it under the terms of the GPL or Artistic License.
# These licenses are available at http://www.opensource.org
#
# This software must be used and distributed in accordance
# with the law. The author claims no liability for its
# misuse.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
 
"""
Blowfish Encryption
 
This module is a pure python implementation of Bruce Schneier's
encryption scheme 'Blowfish'. Blowish is a 16-round Feistel Network
cipher and offers substantial speed gains over DES.
 
The key is a string of length anywhere between 64 and 448 bits, or
equivalently 8 and 56 bytes. The encryption and decryption functions
operate on 64-bit blocks, or 8 byte strings.
 
Send questions, comments, bugs my way. Or, just let me know you're
using the software:
Michael Gilfix <mgilfix@gmail.com>
"""
 
__author__ = "Michael Gilfix <mgilfix@gmail.com>"
 
import copy
 
class Blowfish:
"""Blowfish encryption Scheme
 
This class implements the encryption and decryption
functionality of the Blowfish cipher.
 
Public functions:
 
def __init__(self, key)
Creates an instance of blowfish using 'key'
as the encryption key. Key is a string of
length ranging from 8 to 56 bytes (64 to 448
bits). Once the instance of the object is
created, the key is no longer necessary.
 
def encrypt(self, data):
Convenience method. Calls crypt under the covers.
 
def decrypt(self, data):
Convenience method. Calls crypt under the covers.
 
def crypt(self, data, direction):
Performs actual encryption/decryption of data
depending on the direction. The data is broken
up into 8 byte chunks for the ciphering
process. If the data does not align on 8 byte
chunks, then null padding is added. This is
removed upon decryption.
 
def cipher(self, xl, xr, direction):
Encrypts a 64-bit block of data where xl is
the upper 32-bits and xr is the lower 32-bits.
'direction' is the direction to apply the
cipher, either ENCRYPT or DECRYPT constants.
returns a tuple of either encrypted or decrypted
data of the left half and right half of the
64-bit block.
 
Private members:
 
def __round_func(self, xl)
Performs an obscuring function on the 32-bit
block of data 'xl', which is the left half of
the 64-bit block of data. Returns the 32-bit
result as a long integer.
 
"""
# Cipher directions
ENCRYPT = 0
DECRYPT = 1
 
# For the __round_func
MODULUS = 2L ** 32
 
# Constants
BLOCK_SIZE = 8
MAX_KEY_LENGTH = 56
 
P_BOXES = [
0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,
0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,
0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL,
0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L,
0x9216D5D9L, 0x8979FB1BL
]
 
S_BOXES = [
[
0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,
0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L,
0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L,
0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL,
0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL,
0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L,
0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL,
0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL,
0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L,
0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L,
0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL,
0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL,
0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL,
0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L,
0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L,
0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L,
0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L,
0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L,
0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL,
0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L,
0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L,
0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L,
0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L,
0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL,
0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L,
0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL,
0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL,
0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L,
0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL,
0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L,
0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL,
0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L,
0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L,
0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL,
0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L,
0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L,
0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL,
0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L,
0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL,
0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L,
0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L,
0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL,
0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L,
0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L,
0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L,
0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L,
0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L,
0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL,
0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL,
0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L,
0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L,
0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L,
0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L,
0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL,
0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L,
0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL,
0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL,
0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L,
0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L,
0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L,
0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L,
0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L,
0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L,
0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076A
],
[
0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L,
0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L,
0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L,
0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL,
0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L,
0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L,
0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL,
0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L,
0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L,
0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L,
0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL,
0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL,
0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L,
0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L,
0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L,
0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L,
0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL,
0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL,
0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL,
0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L,
0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL,
0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L,
0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L,
0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL,
0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL,
0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L,
0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL,
0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L,
0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL,
0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL,
0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L,
0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L,
0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L,
0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L,
0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L,
0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L,
0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L,
0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL,
0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L,
0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL,
0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L,
0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L,
0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L,
0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L,
0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L,
0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L,
0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L,
0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L,
0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L,
0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L,
0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L,
0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L,
0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L,
0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L,
0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L,
0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L,
0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL,
0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL,
0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L,
0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL,
0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L,
0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L,
0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L,
0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7
],
[
0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L,
0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L,
0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL,
0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L,
0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L,
0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L,
0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL,
0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL,
0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL,
0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L,
0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L,
0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL,
0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L,
0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL,
0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L,
0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL,
0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L,
0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL,
0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L,
0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL,
0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L,
0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L,
0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL,
0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L,
0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L,
0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L,
0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L,
0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL,
0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L,
0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL,
0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L,
0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL,
0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L,
0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL,
0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL,
0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL,
0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L,
0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L,
0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL,
0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL,
0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL,
0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL,
0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL,
0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L,
0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L,
0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L,
0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L,
0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL,
0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL,
0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L,
0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L,
0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L,
0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L,
0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L,
0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L,
0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L,
0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L,
0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L,
0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L,
0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL,
0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L,
0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL,
0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L,
0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0
],
[
0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL,
0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL,
0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL,
0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L,
0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L,
0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L,
0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L,
0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L,
0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L,
0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L,
0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L,
0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L,
0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L,
0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L,
0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L,
0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL,
0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL,
0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L,
0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL,
0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL,
0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL,
0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L,
0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL,
0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL,
0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L,
0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L,
0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L,
0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L,
0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL,
0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL,
0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L,
0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L,
0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L,
0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL,
0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L,
0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L,
0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L,
0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL,
0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L,
0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L,
0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L,
0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL,
0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL,
0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L,
0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L,
0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L,
0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L,
0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL,
0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L,
0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL,
0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL,
0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L,
0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L,
0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL,
0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L,
0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL,
0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L,
0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL,
0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L,
0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L,
0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL,
0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L,
0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL,
0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6
]
]
 
def __init__(self, key):
if not key or len(key) < 8 or len(key) > 56:
raise ValueError, "Invalid cipher key length: %s" %len(key)
 
# Initialize cipher copies from static data
self.p_boxes = copy.deepcopy(self.P_BOXES)
self.s_boxes = copy.deepcopy(self.S_BOXES)
 
# Cycle through the p-boxes and round-robin XOR the
# key ordinals with the p-boxes
key_ord = map(ord, key)
key_len = len(key_ord)
index = 0
for i in range(len(self.p_boxes)):
val = (key_ord[index % key_len] << 24) + \
(key_ord[(index + 1) % key_len] << 16) + \
(key_ord[(index + 2) % key_len] << 8) + \
key_ord[(index + 3) % key_len]
self.p_boxes[i] = self.p_boxes[i] ^ val
index = index + 4
 
# For the chaining process
l, r = 0, 0
 
# Begin chain replacing the p-boxes
for i in range(0, len(self.p_boxes), 2):
l, r = self.cipher(l, r, self.ENCRYPT)
self.p_boxes[i] = l
self.p_boxes[i + 1] = r
 
# Chain replace the s-boxes
for i in range(len(self.s_boxes)):
for j in range(0, len(self.s_boxes[i]), 2):
l, r = self.cipher(l, r, self.ENCRYPT)
self.s_boxes[i][j] = l
self.s_boxes[i][j + 1] = r
 
def cipher(self, xl, xr, direction):
if direction == self.ENCRYPT:
for i in range(16):
xl = xl ^ self.p_boxes[i]
xr = self.__round_func(xl) ^ xr
xl, xr = xr, xl
xl, xr = xr, xl
xr = xr ^ self.p_boxes[16]
xl = xl ^ self.p_boxes[17]
else:
for i in range(17, 1, -1):
xl = xl ^ self.p_boxes[i]
xr = self.__round_func(xl) ^ xr
xl, xr = xr, xl
xl, xr = xr, xl
xr = xr ^ self.p_boxes[1]
xl = xl ^ self.p_boxes[0]
return xl, xr
 
def __round_func(self, xl):
a = (xl & 0xFF000000) >> 24
b = (xl & 0x00FF0000) >> 16
c = (xl & 0x0000FF00) >> 8
d = xl & 0x000000FF
 
# Perform all ops as longs then and out the last 32-bits to
# obtain the integer
f = (self.s_boxes[0][a] + self.s_boxes[1][b]) % self.MODULUS
f = f ^ self.s_boxes[2][c]
f = f + self.s_boxes[3][d]
f = (f % self.MODULUS) & 0xFFFFFFFF
return int(f)
 
def crypt(self, data, direction):
# Pad the data if need be so it has 8 byte chunks
align = len(data) % 8
if align != 0:
padding = '\x00' * (8 - align)
data += padding
 
result = ''
for i in range(0, len(data), 8):
# Use big endianess since that's what everyone else uses
chunk = map(ord, data[i : i + 8])
xl = chunk[3] | (chunk[2] << 8) | (chunk[1] << 16) | (chunk[0] << 24)
xr = chunk[7] | (chunk[6] << 8) | (chunk[5] << 16) | (chunk[4] << 24)
xl, xr = self.cipher(xl, xr, direction)
chunk = (
(xl >> 24) & 0xFF, (xl >> 16) & 0xFF, (xl >> 8) & 0xFF, xl & 0xFF,
(xr >> 24) & 0xFF, (xr >> 16) & 0xFF, (xr >> 8) & 0xFF, xr & 0xFF
)
result += ''.join(map(chr, chunk))
 
# Strip the padding if we decrypted
if direction == self.DECRYPT:
result = result.rstrip('\x00')
return result
 
def encrypt(self, data):
return self.crypt(data, self.ENCRYPT)
 
def decrypt(self, data):
return self.crypt(data, self.DECRYPT)
 
def block_size(self):
return self.BLOCK_SIZE
 
def max_key_length(self):
return self.MAX_KEY_LENGTH
 
def max_key_bits(self):
return self.max_key_length() * self.block_size()
 
##############################################################
# Simple module testing
 
if __name__ == '__main__':
key = 'This is a simple test key'
cipher = Blowfish(key)
print "Max key bits: %s" %cipher.max_key_bits()
 
print "Testing encryption:"
xl = 123456
xr = 654321
print "\tPlain text: (%s, %s)" %(xl, xr)
cl, cr = cipher.cipher(xl, xr, cipher.ENCRYPT)
print "\tCrypted is: (%s, %s)" %(cl, cr)
dl, dr = cipher.cipher(cl, cr, cipher.DECRYPT)
print "\tUnencrypted is: (%s, %s)" %(dl, dr)
 
print "Testing buffer encrypt:"
text = 'This is my test string. Sample text goes here'
print "\tText: [%s], len: %s" %(text, len(text))
crypted = cipher.encrypt(text)
print "\tEncrypted: [%s]" %crypted
decrypted = cipher.decrypt(crypted)
print "\tDecrypted: [%s]" %decrypted
 
print "Testing decryption from separate instances:"
cipher1 = Blowfish(key)
crypted = cipher1.encrypt(text)
print "\tEncrypt cipher1: [%s]" %crypted
cipher2 = Blowfish(key)
decrypted = cipher2.decrypt(crypted)
print "\tDecrypt cipher2: [%s]" %decrypted
 
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/ARC2.py
0,0 → 1,59
from blockcipher import *
import Crypto.Cipher.ARC2
import Crypto
from pkg_resources import parse_version
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None,effective_keylen=None):
"""Create a new cipher object
 
ARC2 using pycrypto for algo and pycryptoplus for ciphermode
 
key = raw string containing the keys
mode = python_AES.MODE_ECB/CBC/CFB/OFB/CTR/CMAC, default is ECB
IV = IV as a raw string, default is "all zero" IV
-> only needed for CBC mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
effective_keylen = how much bits to effectively use from the supplied key
-> will only be used when the pycrypto version on your system is >2.0.1
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import ARC2
 
http://www.ietf.org/rfc/rfc2268.txt
Doctest will fail when using pycrypto 2.0.1 and older
------------------------------------
>>> key = "0000000000000000".decode('hex')
>>> plaintext = "0000000000000000".decode('hex')
>>> ek = 63
>>> cipher = ARC2.new(key,ARC2.MODE_ECB,effective_keylen=ek)
>>> cipher.encrypt(plaintext).encode('hex')
'ebb773f993278eff'
"""
return ARC2(key,mode,IV,counter,effective_keylen,segment_size)
 
class ARC2(BlockCipher):
def __init__(self,key,mode,IV,counter,effective_keylen,segment_size):
# pycrypto versions newer than 2.0.1 will have support for "effective_keylen"
if parse_version(Crypto.__version__) <= parse_version("2.0.1"):
cipher_module = Crypto.Cipher.ARC2.new
args = {}
else:
cipher_module = Crypto.Cipher.ARC2.new
args = {'effective_keylen':effective_keylen}
self.blocksize = 8
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size,args)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/rijndael.py
0,0 → 1,392
"""
A pure python (slow) implementation of rijndael with a decent interface
 
To include -
 
from rijndael import rijndael
 
To do a key setup -
 
r = rijndael(key, block_size = 16)
 
key must be a string of length 16, 24, or 32
blocksize must be 16, 24, or 32. Default is 16
 
To use -
 
ciphertext = r.encrypt(plaintext)
plaintext = r.decrypt(ciphertext)
 
If any strings are of the wrong length a ValueError is thrown
"""
 
# ported from the Java reference code by Bram Cohen, bram@gawth.com, April 2001
# this code is public domain, unless someone makes
# an intellectual property claim against the reference
# code, in which case it can be made public domain by
# deleting all the comments and renaming all the variables
 
import copy
import string
 
 
 
#-----------------------
#TREV - ADDED BECAUSE THERE'S WARNINGS ABOUT INT OVERFLOW BEHAVIOR CHANGING IN
#2.4.....
import os
if os.name != "java":
import exceptions
if hasattr(exceptions, "FutureWarning"):
import warnings
warnings.filterwarnings("ignore", category=FutureWarning, append=1)
#-----------------------
 
 
 
shifts = [[[0, 0], [1, 3], [2, 2], [3, 1]],
[[0, 0], [1, 5], [2, 4], [3, 3]],
[[0, 0], [1, 7], [3, 5], [4, 4]]]
 
# [keysize][block_size]
num_rounds = {16: {16: 10, 24: 12, 32: 14}, 24: {16: 12, 24: 12, 32: 14}, 32: {16: 14, 24: 14, 32: 14}}
 
A = [[1, 1, 1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 0],
[0, 0, 0, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 1, 1, 1, 1],
[1, 1, 0, 0, 0, 1, 1, 1],
[1, 1, 1, 0, 0, 0, 1, 1],
[1, 1, 1, 1, 0, 0, 0, 1]]
 
# produce log and alog tables, needed for multiplying in the
# field GF(2^m) (generator = 3)
alog = [1]
for i in xrange(255):
j = (alog[-1] << 1) ^ alog[-1]
if j & 0x100 != 0:
j ^= 0x11B
alog.append(j)
 
log = [0] * 256
for i in xrange(1, 255):
log[alog[i]] = i
 
# multiply two elements of GF(2^m)
def mul(a, b):
if a == 0 or b == 0:
return 0
return alog[(log[a & 0xFF] + log[b & 0xFF]) % 255]
 
# substitution box based on F^{-1}(x)
box = [[0] * 8 for i in xrange(256)]
box[1][7] = 1
for i in xrange(2, 256):
j = alog[255 - log[i]]
for t in xrange(8):
box[i][t] = (j >> (7 - t)) & 0x01
 
B = [0, 1, 1, 0, 0, 0, 1, 1]
 
# affine transform: box[i] <- B + A*box[i]
cox = [[0] * 8 for i in xrange(256)]
for i in xrange(256):
for t in xrange(8):
cox[i][t] = B[t]
for j in xrange(8):
cox[i][t] ^= A[t][j] * box[i][j]
 
# S-boxes and inverse S-boxes
S = [0] * 256
Si = [0] * 256
for i in xrange(256):
S[i] = cox[i][0] << 7
for t in xrange(1, 8):
S[i] ^= cox[i][t] << (7-t)
Si[S[i] & 0xFF] = i
 
# T-boxes
G = [[2, 1, 1, 3],
[3, 2, 1, 1],
[1, 3, 2, 1],
[1, 1, 3, 2]]
 
AA = [[0] * 8 for i in xrange(4)]
 
for i in xrange(4):
for j in xrange(4):
AA[i][j] = G[i][j]
AA[i][i+4] = 1
 
for i in xrange(4):
pivot = AA[i][i]
if pivot == 0:
t = i + 1
while AA[t][i] == 0 and t < 4:
t += 1
assert t != 4, 'G matrix must be invertible'
for j in xrange(8):
AA[i][j], AA[t][j] = AA[t][j], AA[i][j]
pivot = AA[i][i]
for j in xrange(8):
if AA[i][j] != 0:
AA[i][j] = alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255]
for t in xrange(4):
if i != t:
for j in xrange(i+1, 8):
AA[t][j] ^= mul(AA[i][j], AA[t][i])
AA[t][i] = 0
 
iG = [[0] * 4 for i in xrange(4)]
 
for i in xrange(4):
for j in xrange(4):
iG[i][j] = AA[i][j + 4]
 
def mul4(a, bs):
if a == 0:
return 0
r = 0
for b in bs:
r <<= 8
if b != 0:
r = r | mul(a, b)
return r
 
T1 = []
T2 = []
T3 = []
T4 = []
T5 = []
T6 = []
T7 = []
T8 = []
U1 = []
U2 = []
U3 = []
U4 = []
 
for t in xrange(256):
s = S[t]
T1.append(mul4(s, G[0]))
T2.append(mul4(s, G[1]))
T3.append(mul4(s, G[2]))
T4.append(mul4(s, G[3]))
 
s = Si[t]
T5.append(mul4(s, iG[0]))
T6.append(mul4(s, iG[1]))
T7.append(mul4(s, iG[2]))
T8.append(mul4(s, iG[3]))
 
U1.append(mul4(t, iG[0]))
U2.append(mul4(t, iG[1]))
U3.append(mul4(t, iG[2]))
U4.append(mul4(t, iG[3]))
 
# round constants
rcon = [1]
r = 1
for t in xrange(1, 30):
r = mul(2, r)
rcon.append(r)
 
del A
del AA
del pivot
del B
del G
del box
del log
del alog
del i
del j
del r
del s
del t
del mul
del mul4
del cox
del iG
 
class rijndael:
def __init__(self, key, block_size = 16):
if block_size != 16 and block_size != 24 and block_size != 32:
raise ValueError('Invalid block size: ' + str(block_size))
if len(key) != 16 and len(key) != 24 and len(key) != 32:
raise ValueError('Invalid key size: ' + str(len(key)))
self.block_size = block_size
 
ROUNDS = num_rounds[len(key)][block_size]
BC = block_size / 4
# encryption round keys
Ke = [[0] * BC for i in xrange(ROUNDS + 1)]
# decryption round keys
Kd = [[0] * BC for i in xrange(ROUNDS + 1)]
ROUND_KEY_COUNT = (ROUNDS + 1) * BC
KC = len(key) / 4
 
# copy user material bytes into temporary ints
tk = []
for i in xrange(0, KC):
tk.append((ord(key[i * 4]) << 24) | (ord(key[i * 4 + 1]) << 16) |
(ord(key[i * 4 + 2]) << 8) | ord(key[i * 4 + 3]))
 
# copy values into round key arrays
t = 0
j = 0
while j < KC and t < ROUND_KEY_COUNT:
Ke[t / BC][t % BC] = tk[j]
Kd[ROUNDS - (t / BC)][t % BC] = tk[j]
j += 1
t += 1
tt = 0
rconpointer = 0
while t < ROUND_KEY_COUNT:
# extrapolate using phi (the round key evolution function)
tt = tk[KC - 1]
tk[0] ^= (S[(tt >> 16) & 0xFF] & 0xFF) << 24 ^ \
(S[(tt >> 8) & 0xFF] & 0xFF) << 16 ^ \
(S[ tt & 0xFF] & 0xFF) << 8 ^ \
(S[(tt >> 24) & 0xFF] & 0xFF) ^ \
(rcon[rconpointer] & 0xFF) << 24
rconpointer += 1
if KC != 8:
for i in xrange(1, KC):
tk[i] ^= tk[i-1]
else:
for i in xrange(1, KC / 2):
tk[i] ^= tk[i-1]
tt = tk[KC / 2 - 1]
tk[KC / 2] ^= (S[ tt & 0xFF] & 0xFF) ^ \
(S[(tt >> 8) & 0xFF] & 0xFF) << 8 ^ \
(S[(tt >> 16) & 0xFF] & 0xFF) << 16 ^ \
(S[(tt >> 24) & 0xFF] & 0xFF) << 24
for i in xrange(KC / 2 + 1, KC):
tk[i] ^= tk[i-1]
# copy values into round key arrays
j = 0
while j < KC and t < ROUND_KEY_COUNT:
Ke[t / BC][t % BC] = tk[j]
Kd[ROUNDS - (t / BC)][t % BC] = tk[j]
j += 1
t += 1
# inverse MixColumn where needed
for r in xrange(1, ROUNDS):
for j in xrange(BC):
tt = Kd[r][j]
Kd[r][j] = U1[(tt >> 24) & 0xFF] ^ \
U2[(tt >> 16) & 0xFF] ^ \
U3[(tt >> 8) & 0xFF] ^ \
U4[ tt & 0xFF]
self.Ke = Ke
self.Kd = Kd
 
def encrypt(self, plaintext):
if len(plaintext) != self.block_size:
raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(plaintext)))
Ke = self.Ke
 
BC = self.block_size / 4
ROUNDS = len(Ke) - 1
if BC == 4:
SC = 0
elif BC == 6:
SC = 1
else:
SC = 2
s1 = shifts[SC][1][0]
s2 = shifts[SC][2][0]
s3 = shifts[SC][3][0]
a = [0] * BC
# temporary work array
t = []
# plaintext to ints + key
for i in xrange(BC):
t.append((ord(plaintext[i * 4 ]) << 24 |
ord(plaintext[i * 4 + 1]) << 16 |
ord(plaintext[i * 4 + 2]) << 8 |
ord(plaintext[i * 4 + 3]) ) ^ Ke[0][i])
# apply round transforms
for r in xrange(1, ROUNDS):
for i in xrange(BC):
a[i] = (T1[(t[ i ] >> 24) & 0xFF] ^
T2[(t[(i + s1) % BC] >> 16) & 0xFF] ^
T3[(t[(i + s2) % BC] >> 8) & 0xFF] ^
T4[ t[(i + s3) % BC] & 0xFF] ) ^ Ke[r][i]
t = copy.copy(a)
# last round is special
result = []
for i in xrange(BC):
tt = Ke[ROUNDS][i]
result.append((S[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
result.append((S[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
result.append((S[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
result.append((S[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF)
return string.join(map(chr, result), '')
 
def decrypt(self, ciphertext):
if len(ciphertext) != self.block_size:
raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(plaintext)))
Kd = self.Kd
 
BC = self.block_size / 4
ROUNDS = len(Kd) - 1
if BC == 4:
SC = 0
elif BC == 6:
SC = 1
else:
SC = 2
s1 = shifts[SC][1][1]
s2 = shifts[SC][2][1]
s3 = shifts[SC][3][1]
a = [0] * BC
# temporary work array
t = [0] * BC
# ciphertext to ints + key
for i in xrange(BC):
t[i] = (ord(ciphertext[i * 4 ]) << 24 |
ord(ciphertext[i * 4 + 1]) << 16 |
ord(ciphertext[i * 4 + 2]) << 8 |
ord(ciphertext[i * 4 + 3]) ) ^ Kd[0][i]
# apply round transforms
for r in xrange(1, ROUNDS):
for i in xrange(BC):
a[i] = (T5[(t[ i ] >> 24) & 0xFF] ^
T6[(t[(i + s1) % BC] >> 16) & 0xFF] ^
T7[(t[(i + s2) % BC] >> 8) & 0xFF] ^
T8[ t[(i + s3) % BC] & 0xFF] ) ^ Kd[r][i]
t = copy.copy(a)
# last round is special
result = []
for i in xrange(BC):
tt = Kd[ROUNDS][i]
result.append((Si[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
result.append((Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
result.append((Si[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
result.append((Si[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF)
return string.join(map(chr, result), '')
 
def encrypt(key, block):
return rijndael(key, len(block)).encrypt(block)
 
def decrypt(key, block):
return rijndael(key, len(block)).decrypt(block)
 
def test():
def t(kl, bl):
b = 'b' * bl
r = rijndael('a' * kl, bl)
assert r.decrypt(r.encrypt(b)) == b
t(16, 16)
t(16, 24)
t(16, 32)
t(24, 16)
t(24, 24)
t(24, 32)
t(32, 16)
t(32, 24)
t(32, 32)
 
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/python_Rijndael.py
0,0 → 1,107
from blockcipher import *
from rijndael import rijndael
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None,blocksize=None):
"""Create a new cipher object
 
Wrapper for pure python implementation rijndael.py
 
key = raw string containing the key
-> supported key size are 16, 24 and 32 bytes
mode = python_Rijndael.MODE_ECB/CBC/CFB/OFB/CTR/XTS/CMAC, default is ECB
-> for every mode, except ECB and CTR, it is important to construct a seperate cipher for encryption and decryption
IV = IV as a raw string, default is "all zero" IV
-> needed for CBC, CFB and OFB mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
-> use a seperate counter object for the cipher and decipher: the counter is updated directly, not a copy
see CTR example further on in the docstring
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
blocksize = blocksize in bytes
-> supported blocksizes are 16, 24 and 32 bytes, must be 16 if XTS mode.
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import python_Rijndael
 
EXAMPLE:
--------
24 byte block, 32 byte key (http://fp.gladman.plus.com/cryptography_technology/rijndael/)
>>> key = '2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe'.decode('hex')
>>> plaintext ='3243f6a8885a308d313198a2e03707344a4093822299f31d'.decode('hex')
>>> cipher = python_Rijndael.new(key,python_Rijndael.MODE_ECB,blocksize=24)
>>> cipher.encrypt(plaintext).encode('hex')
'0ebacf199e3315c2e34b24fcc7c46ef4388aa475d66c194c'
 
CBC EXAMPLE (plaintext = 3 blocksizes) (AES):
-----------------------------------------
>>> key = ('2b7e151628aed2a6abf7158809cf4f3c').decode('hex')
>>> IV = ('000102030405060708090a0b0c0d0e0f').decode('hex')
>>> plaintext1 = ('6bc1bee22e409f96e93d7e117393172a').decode('hex')
>>> plaintext2 = ('ae2d8a571e03ac9c9eb76fac45af8e51').decode('hex')
>>> plaintext3 = ('30c81c46a35ce411e5fbc1191a0a52ef').decode('hex')
>>> cipher = python_Rijndael.new(key,python_Rijndael.MODE_CBC,IV,blocksize=16)
>>> ciphertext = cipher.encrypt(plaintext1 + plaintext2 + plaintext3)
>>> (ciphertext).encode('hex')
'7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e22229516'
>>> decipher = python_Rijndael.new(key,python_Rijndael.MODE_CBC,IV,blocksize=16)
>>> plaintext = decipher.decrypt(ciphertext)
>>> (plaintext).encode('hex')
'6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52ef'
 
XTS EXAMPLE:
------------
(Examples for XTS-AES)
XTS-AES-128 applied for a data unit of 512 bytes
testvector: http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
 
>>> key = ('27182818284590452353602874713526'.decode('hex'),'31415926535897932384626433832795'.decode('hex'))
>>> plaintext = '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'.decode('hex')
>>> cipher = python_Rijndael.new(key,python_Rijndael.MODE_XTS,blocksize=16)
>>> ciphertext = cipher.encrypt(plaintext)
>>> ciphertext.encode('hex')
'27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568'
>>> decipher = python_Rijndael.new(key,python_Rijndael.MODE_XTS,blocksize=16)
>>> decipher.decrypt(ciphertext).encode('hex')
'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'
 
using data sequence number n
 
>>> key = ('fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0'.decode('hex'),'22222222222222222222222222222222'.decode('hex'))
>>> plain ='4444444444444444444444444444444444444444444444444444444444444444'.decode('hex')
>>> n = '3333333333'.decode('hex')
>>> cipher = python_Rijndael.new(key,python_Rijndael.MODE_XTS,blocksize=16)
>>> ciphertext = cipher.encrypt(plain,n)
>>> ciphertext.encode('hex')
'af85336b597afc1a900b2eb21ec949d292df4c047e0b21532186a5971a227a89'
>>> decipher = python_Rijndael.new(key,python_Rijndael.MODE_XTS,blocksize=16)
>>> decipher.decrypt(ciphertext,n).encode('hex')
'4444444444444444444444444444444444444444444444444444444444444444'
"""
return python_Rijndael(key,mode,IV,counter,blocksize,segment_size)
 
class python_Rijndael(BlockCipher):
key_error_message = ("Key should be 128, 192 or 256 bits")
 
def __init__(self,key,mode,IV,counter,blocksize,segment_size):
if blocksize not in (16,24,32):
raise ValueError("Blocksize should be 16, 24 or 32")
cipher_module = rijndael
args = {'block_size':blocksize}
self.blocksize = blocksize
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size,args)
 
def keylen_valid(self,key):
return len(key) in (16,24,32)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/RC5.py
0,0 → 1,58
from blockcipher import *
try:
import Crypto.Cipher.RC5
except ImportError:
print "Crypto.Cipher.RC5 isn't available. You're probably using the Debian pycrypto version. Install the original pycrypto for RC5."
raise
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None,rounds=12,word_size=32):
"""Create a new cipher object
 
RC5 using pycrypto for algo and pycryptoplus for ciphermode
 
key = raw string containing the keys
multiple of 8 bits between 0 <-> 2040 bits
mode = python_AES.MODE_ECB/CBC/CFB/OFB/CTR/CMAC, default is ECB
IV = IV as a raw string, default is "all zero" IV
-> only needed for CBC mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
rounds = amount of rounds, default = 12
minimum 12 and multiple of 2
word_size = RC5 word size (bits), supported = 16 and 32, default = 32
RC5 encrypts blocks of size 2*word_size
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import RC5
 
https://www.cosic.esat.kuleuven.be/nessie/testvectors/
-----------------------------------------
>>> key = "00000000000000000000000000000000".decode('hex')
>>> plaintext = "0000000000000000".decode('hex')
>>> rounds = 12
>>> cipher = RC5.new(key,RC5.MODE_ECB,rounds=rounds)
>>> cipher.encrypt(plaintext).encode('hex')
'21a5dbee154b8f6d'
"""
return RC5(key,mode,IV,counter,rounds,word_size,segment_size)
 
class RC5(BlockCipher):
def __init__(self,key,mode,IV,counter,rounds,word_size,segment_size):
cipher_module = Crypto.Cipher.RC5.new
args = {'rounds':rounds,'word_size':word_size}
self.blocksize = (2*word_size)/8
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size,args)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/pypresent.py
0,0 → 1,229
# Python PRESENT implementation
# Version: 1.0
# Date: 13/10/2008
#
# =============================================================================
# Copyright (c) 2008 Christophe Oosterlynck <christophe.oosterlynck_AT_gmail.com>
# & NXP ( Philippe Teuwen <philippe.teuwen_AT_nxp.com> )
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# =============================================================================
 
""" PRESENT block cipher implementation
 
USAGE EXAMPLE:
---------------
Importing:
-----------
>>> from pypresent import Present
 
Encrypting with a 80-bit key:
------------------------------
>>> key = "00000000000000000000".decode('hex')
>>> plain = "0000000000000000".decode('hex')
>>> cipher = Present(key)
>>> encrypted = cipher.encrypt(plain)
>>> encrypted.encode('hex')
'5579c1387b228445'
>>> decrypted = cipher.decrypt(encrypted)
>>> decrypted.encode('hex')
'0000000000000000'
 
Encrypting with a 128-bit key:
-------------------------------
>>> key = "0123456789abcdef0123456789abcdef".decode('hex')
>>> plain = "0123456789abcdef".decode('hex')
>>> cipher = Present(key)
>>> encrypted = cipher.encrypt(plain)
>>> encrypted.encode('hex')
'0e9d28685e671dd6'
>>> decrypted = cipher.decrypt(encrypted)
>>> decrypted.encode('hex')
'0123456789abcdef'
 
fully based on standard specifications: http://www.crypto.ruhr-uni-bochum.de/imperia/md/content/texte/publications/conferences/present_ches2007.pdf
test vectors: http://www.crypto.ruhr-uni-bochum.de/imperia/md/content/texte/publications/conferences/slides/present_testvectors.zip
"""
class Present:
 
def __init__(self,key,rounds=32):
"""Create a PRESENT cipher object
 
key: the key as a 128-bit or 80-bit rawstring
rounds: the number of rounds as an integer, 32 by default
"""
self.rounds = rounds
if len(key) * 8 == 80:
self.roundkeys = generateRoundkeys80(string2number(key),self.rounds)
elif len(key) * 8 == 128:
self.roundkeys = generateRoundkeys128(string2number(key),self.rounds)
else:
raise ValueError, "Key must be a 128-bit or 80-bit rawstring"
 
def encrypt(self,block):
"""Encrypt 1 block (8 bytes)
 
Input: plaintext block as raw string
Output: ciphertext block as raw string
"""
state = string2number(block)
for i in xrange (self.rounds-1):
state = addRoundKey(state,self.roundkeys[i])
state = sBoxLayer(state)
state = pLayer(state)
cipher = addRoundKey(state,self.roundkeys[-1])
return number2string_N(cipher,8)
 
def decrypt(self,block):
"""Decrypt 1 block (8 bytes)
 
Input: ciphertext block as raw string
Output: plaintext block as raw string
"""
state = string2number(block)
for i in xrange (self.rounds-1):
state = addRoundKey(state,self.roundkeys[-i-1])
state = pLayer_dec(state)
state = sBoxLayer_dec(state)
decipher = addRoundKey(state,self.roundkeys[0])
return number2string_N(decipher,8)
 
def get_block_size(self):
return 8
 
# 0 1 2 3 4 5 6 7 8 9 a b c d e f
Sbox= [0xc,0x5,0x6,0xb,0x9,0x0,0xa,0xd,0x3,0xe,0xf,0x8,0x4,0x7,0x1,0x2]
Sbox_inv = [Sbox.index(x) for x in xrange(16)]
PBox = [0,16,32,48,1,17,33,49,2,18,34,50,3,19,35,51,
4,20,36,52,5,21,37,53,6,22,38,54,7,23,39,55,
8,24,40,56,9,25,41,57,10,26,42,58,11,27,43,59,
12,28,44,60,13,29,45,61,14,30,46,62,15,31,47,63]
PBox_inv = [PBox.index(x) for x in xrange(64)]
 
def generateRoundkeys80(key,rounds):
"""Generate the roundkeys for a 80-bit key
 
Input:
key: the key as a 80-bit integer
rounds: the number of rounds as an integer
Output: list of 64-bit roundkeys as integers"""
roundkeys = []
for i in xrange(1,rounds+1): # (K1 ... K32)
# rawkey: used in comments to show what happens at bitlevel
# rawKey[0:64]
roundkeys.append(key >>16)
#1. Shift
#rawKey[19:len(rawKey)]+rawKey[0:19]
key = ((key & (2**19-1)) << 61) + (key >> 19)
#2. SBox
#rawKey[76:80] = S(rawKey[76:80])
key = (Sbox[key >> 76] << 76)+(key & (2**76-1))
#3. Salt
#rawKey[15:20] ^ i
key ^= i << 15
return roundkeys
 
def generateRoundkeys128(key,rounds):
"""Generate the roundkeys for a 128-bit key
 
Input:
key: the key as a 128-bit integer
rounds: the number of rounds as an integer
Output: list of 64-bit roundkeys as integers"""
roundkeys = []
for i in xrange(1,rounds+1): # (K1 ... K32)
# rawkey: used in comments to show what happens at bitlevel
roundkeys.append(key >>64)
#1. Shift
key = ((key & (2**67-1)) << 61) + (key >> 67)
#2. SBox
key = (Sbox[key >> 124] << 124)+(Sbox[(key >> 120) & 0xF] << 120)+(key & (2**120-1))
#3. Salt
#rawKey[62:67] ^ i
key ^= i << 62
return roundkeys
 
def addRoundKey(state,roundkey):
return state ^ roundkey
 
def sBoxLayer(state):
"""SBox function for encryption
 
Input: 64-bit integer
Output: 64-bit integer"""
 
output = 0
for i in xrange(16):
output += Sbox[( state >> (i*4)) & 0xF] << (i*4)
return output
 
def sBoxLayer_dec(state):
"""Inverse SBox function for decryption
 
Input: 64-bit integer
Output: 64-bit integer"""
output = 0
for i in xrange(16):
output += Sbox_inv[( state >> (i*4)) & 0xF] << (i*4)
return output
 
def pLayer(state):
"""Permutation layer for encryption
 
Input: 64-bit integer
Output: 64-bit integer"""
output = 0
for i in xrange(64):
output += ((state >> i) & 0x01) << PBox[i]
return output
 
def pLayer_dec(state):
"""Permutation layer for decryption
 
Input: 64-bit integer
Output: 64-bit integer"""
output = 0
for i in xrange(64):
output += ((state >> i) & 0x01) << PBox_inv[i]
return output
 
def string2number(i):
""" Convert a string to a number
 
Input: string (big-endian)
Output: long or integer
"""
return int(i.encode('hex'),16)
 
def number2string_N(i, N):
"""Convert a number to a string of fixed size
 
i: long or integer
N: length of string
Output: string (big-endian)
"""
s = '%0*x' % (N*2, i)
return s.decode('hex')
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/pyserpent.py
0,0 → 1,1354
#!/usr/local/bin/python
 
# $Id: serpref.py,v 1.19 1998/09/02 21:28:02 fms Exp $
#
# Python reference implementation of Serpent.
#
# Written by Frank Stajano,
# Olivetti Oracle Research Laboratory <http://www.orl.co.uk/~fms/> and
# Cambridge University Computer Laboratory <http://www.cl.cam.ac.uk/~fms27/>.
#
# (c) 1998 Olivetti Oracle Research Laboratory (ORL)
#
# Original (Python) Serpent reference development started on 1998 02 12.
# C implementation development started on 1998 03 04.
#
# Serpent cipher invented by Ross Anderson, Eli Biham, Lars Knudsen.
# Serpent is a candidate for the Advanced Encryption Standard.
 
# --------------------------------------------------------------
 
"""This is an illustrative reference implementation of the Serpent cipher
invented by Eli Biham, Ross Anderson, Lars Knudsen. It is written for the
human reader more than for the machine and, as such, it is optimised for
clarity rather than speed. ("Premature optimisation is the root of all
evil.")
 
It can print out all the intermediate results (such as the subkeys) for a
given input and key so that implementers debugging erroneous code can
quickly verify which one of the building blocks is giving the wrong
answers.
 
This version implements Serpent-1, i.e. the variant defined in the final
submission to NIST.
"""
 
# --------------------------------------------------------------
# My own additions
# --------------------------------------------------------------
class Serpent:
#class to
def __init__(self,key):
key = key.encode('hex')
bitsInKey = keyLengthInBitsOf(key)
rawKey = convertToBitstring(reverse(key.lower()), bitsInKey)
self.userKey = makeLongKey(rawKey)
 
def encrypt(self,block):
plainText = convertToBitstring(reverse(block.encode("hex").lower()), 128)
cipherText = encrypt(plainText, self.userKey)
return reverse(bitstring2hexstring(cipherText)).decode('hex')
 
def decrypt(self,block):
cipherText = convertToBitstring(reverse(block.encode("hex").lower()), 128)
plainText = decrypt(cipherText, self.userKey)
return reverse(bitstring2hexstring(plainText)).decode('hex')
 
def get_block_size(self):
return 16
 
def reverse(toreverse):
out = ""
for i in range(len(toreverse)/2):
out += toreverse[len(toreverse)-i*2-2:len(toreverse)-i*2]
return out
# --------------------------------------------------------------
#
# --------------------------------------------------------------
 
# --------------------------------------------------------------
# Requires python 1.5, freely available from http://www.python.org/
# --------------------------------------------------------------
import string
import sys
import getopt
import re
 
# --------------------------------------------------------------
# Functions used in the formal description of the cipher
 
def S(box, input):
"""Apply S-box number 'box' to 4-bit bitstring 'input' and return a
4-bit bitstring as the result."""
 
return SBoxBitstring[box%8][input]
# There used to be 32 different S-boxes in serpent-0. Now there are
# only 8, each of which is used 4 times (Sboxes 8, 16, 24 are all
# identical to Sbox 0, etc). Hence the %8.
 
def SInverse(box, output):
"""Apply S-box number 'box' in reverse to 4-bit bitstring 'output' and
return a 4-bit bitstring (the input) as the result."""
 
return SBoxBitstringInverse[box%8][output]
 
 
def SHat(box, input):
"""Apply a parallel array of 32 copies of S-box number 'box' to the
128-bit bitstring 'input' and return a 128-bit bitstring as the
result."""
 
result = ""
for i in range(32):
result = result + S(box, input[4*i:4*(i+1)])
return result
 
def SHatInverse(box, output):
"""Apply, in reverse, a parallel array of 32 copies of S-box number
'box' to the 128-bit bitstring 'output' and return a 128-bit bitstring
(the input) as the result."""
 
result = ""
for i in range(32):
result = result + SInverse(box, output[4*i:4*(i+1)])
return result
 
 
def SBitslice(box, words):
"""Take 'words', a list of 4 32-bit bitstrings, least significant word
first. Return a similar list of 4 32-bit bitstrings obtained as
follows. For each bit position from 0 to 31, apply S-box number 'box'
to the 4 input bits coming from the current position in each of the
items in 'words'; and put the 4 output bits in the corresponding
positions in the output words."""
 
result = ["", "", "", ""]
for i in range(32): # ideally in parallel
quad = S(box, words[0][i] + words[1][i] + words[2][i] + words[3][i])
for j in range(4):
result[j] = result[j] + quad[j]
return result
 
def SBitsliceInverse(box, words):
"""Take 'words', a list of 4 32-bit bitstrings, least significant word
first. Return a similar list of 4 32-bit bitstrings obtained as
follows. For each bit position from 0 to 31, apply S-box number 'box'
in reverse to the 4 output bits coming from the current position in
each of the items in the supplied 'words'; and put the 4 input bits in
the corresponding positions in the returned words."""
 
result = ["", "", "", ""]
for i in range(32): # ideally in parallel
quad = SInverse(
box, words[0][i] + words[1][i] + words[2][i] + words[3][i])
for j in range(4):
result[j] = result[j] + quad[j]
return result
 
 
def LT(input):
"""Apply the table-based version of the linear transformation to the
128-bit string 'input' and return a 128-bit string as the result."""
 
if len(input) != 128:
raise ValueError, "input to LT is not 128 bit long"
 
result = ""
for i in range(len(LTTable)):
outputBit = "0"
for j in LTTable[i]:
outputBit = xor(outputBit, input[j])
result = result + outputBit
return result
 
def LTInverse(output):
"""Apply the table-based version of the inverse of the linear
transformation to the 128-bit string 'output' and return a 128-bit
string (the input) as the result."""
 
if len(output) != 128:
raise ValueError, "input to inverse LT is not 128 bit long"
 
result = ""
for i in range(len(LTTableInverse)):
inputBit = "0"
for j in LTTableInverse[i]:
inputBit = xor(inputBit, output[j])
result = result + inputBit
return result
 
 
 
def LTBitslice(X):
"""Apply the equations-based version of the linear transformation to
'X', a list of 4 32-bit bitstrings, least significant bitstring first,
and return another list of 4 32-bit bitstrings as the result."""
 
X[0] = rotateLeft(X[0], 13)
X[2] = rotateLeft(X[2], 3)
X[1] = xor(X[1], X[0], X[2])
X[3] = xor(X[3], X[2], shiftLeft(X[0], 3))
X[1] = rotateLeft(X[1], 1)
X[3] = rotateLeft(X[3], 7)
X[0] = xor(X[0], X[1], X[3])
X[2] = xor(X[2], X[3], shiftLeft(X[1], 7))
X[0] = rotateLeft(X[0], 5)
X[2] = rotateLeft(X[2], 22)
 
return X
 
def LTBitsliceInverse(X):
"""Apply, in reverse, the equations-based version of the linear
transformation to 'X', a list of 4 32-bit bitstrings, least significant
bitstring first, and return another list of 4 32-bit bitstrings as the
result."""
 
X[2] = rotateRight(X[2], 22)
X[0] = rotateRight(X[0], 5)
X[2] = xor(X[2], X[3], shiftLeft(X[1], 7))
X[0] = xor(X[0], X[1], X[3])
X[3] = rotateRight(X[3], 7)
X[1] = rotateRight(X[1], 1)
X[3] = xor(X[3], X[2], shiftLeft(X[0], 3))
X[1] = xor(X[1], X[0], X[2])
X[2] = rotateRight(X[2], 3)
X[0] = rotateRight(X[0], 13)
 
return X
 
 
def IP(input):
"""Apply the Initial Permutation to the 128-bit bitstring 'input'
and return a 128-bit bitstring as the result."""
 
return applyPermutation(IPTable, input)
 
def FP(input):
"""Apply the Final Permutation to the 128-bit bitstring 'input'
and return a 128-bit bitstring as the result."""
 
return applyPermutation(FPTable, input)
 
 
def IPInverse(output):
"""Apply the Initial Permutation in reverse."""
 
return FP(output)
 
def FPInverse(output):
"""Apply the Final Permutation in reverse."""
 
return IP(output)
 
 
def applyPermutation(permutationTable, input):
"""Apply the permutation specified by the 128-element list
'permutationTable' to the 128-bit bitstring 'input' and return a
128-bit bitstring as the result."""
 
if len(input) != len(permutationTable):
raise ValueError, "input size (%d) doesn't match perm table size (%d)"\
% (len(input), len(permutationTable))
 
result = ""
for i in range(len(permutationTable)):
result = result + input[permutationTable[i]]
return result
 
 
def R(i, BHati, KHat):
"""Apply round 'i' to the 128-bit bitstring 'BHati', returning another
128-bit bitstring (conceptually BHatiPlus1). Do this using the
appropriately numbered subkey(s) from the 'KHat' list of 33 128-bit
bitstrings."""
 
#O.show("BHati", BHati, "(i=%2d) BHati" % i)
 
xored = xor(BHati, KHat[i])
#O.show("xored", xored, "(i=%2d) xored" % i)
 
SHati = SHat(i, xored)
#O.show("SHati", SHati, "(i=%2d) SHati" % i)
 
if 0 <= i <= r-2:
BHatiPlus1 = LT(SHati)
elif i == r-1:
BHatiPlus1 = xor(SHati, KHat[r])
else:
raise ValueError, "round %d is out of 0..%d range" % (i, r-1)
#O.show("BHatiPlus1", BHatiPlus1, "(i=%2d) BHatiPlus1" % i)
 
return BHatiPlus1
 
 
def RInverse(i, BHatiPlus1, KHat):
"""Apply round 'i' in reverse to the 128-bit bitstring 'BHatiPlus1',
returning another 128-bit bitstring (conceptually BHati). Do this using
the appropriately numbered subkey(s) from the 'KHat' list of 33 128-bit
bitstrings."""
 
#O.show("BHatiPlus1", BHatiPlus1, "(i=%2d) BHatiPlus1" % i)
 
if 0 <= i <= r-2:
SHati = LTInverse(BHatiPlus1)
elif i == r-1:
SHati = xor(BHatiPlus1, KHat[r])
else:
raise ValueError, "round %d is out of 0..%d range" % (i, r-1)
#O.show("SHati", SHati, "(i=%2d) SHati" % i)
 
xored = SHatInverse(i, SHati)
#O.show("xored", xored, "(i=%2d) xored" % i)
 
BHati = xor(xored, KHat[i])
#O.show("BHati", BHati, "(i=%2d) BHati" % i)
 
return BHati
 
 
def RBitslice(i, Bi, K):
"""Apply round 'i' (bitslice version) to the 128-bit bitstring 'Bi' and
return another 128-bit bitstring (conceptually B i+1). Use the
appropriately numbered subkey(s) from the 'K' list of 33 128-bit
bitstrings."""
 
#O.show("Bi", Bi, "(i=%2d) Bi" % i)
 
# 1. Key mixing
xored = xor (Bi, K[i])
#O.show("xored", xored, "(i=%2d) xored" % i)
 
# 2. S Boxes
Si = SBitslice(i, quadSplit(xored))
# Input and output to SBitslice are both lists of 4 32-bit bitstrings
#O.show("Si", Si, "(i=%2d) Si" % i, "tlb")
 
 
# 3. Linear Transformation
if i == r-1:
# In the last round, replaced by an additional key mixing
BiPlus1 = xor(quadJoin(Si), K[r])
else:
BiPlus1 = quadJoin(LTBitslice(Si))
# BIPlus1 is a 128-bit bitstring
#O.show("BiPlus1", BiPlus1, "(i=%2d) BiPlus1" % i)
 
return BiPlus1
 
 
def RBitsliceInverse(i, BiPlus1, K):
"""Apply the inverse of round 'i' (bitslice version) to the 128-bit
bitstring 'BiPlus1' and return another 128-bit bitstring (conceptually
B i). Use the appropriately numbered subkey(s) from the 'K' list of 33
128-bit bitstrings."""
 
#O.show("BiPlus1", BiPlus1, "(i=%2d) BiPlus1" % i)
 
# 3. Linear Transformation
if i == r-1:
# In the last round, replaced by an additional key mixing
Si = quadSplit(xor(BiPlus1, K[r]))
else:
Si = LTBitsliceInverse(quadSplit(BiPlus1))
# SOutput (same as LTInput) is a list of 4 32-bit bitstrings
 
#O.show("Si", Si, "(i=%2d) Si" % i, "tlb")
 
# 2. S Boxes
xored = SBitsliceInverse(i, Si)
# SInput and SOutput are both lists of 4 32-bit bitstrings
 
#O.show("xored", xored, "(i=%2d) xored" % i)
 
# 1. Key mixing
Bi = xor (quadJoin(xored), K[i])
 
#O.show("Bi", Bi, "(i=%2d) Bi" % i)
 
return Bi
 
 
 
def encrypt(plainText, userKey):
"""Encrypt the 128-bit bitstring 'plainText' with the 256-bit bitstring
'userKey', using the normal algorithm, and return a 128-bit ciphertext
bitstring."""
 
#O.show("fnTitle", "encrypt", None, "tu")
#O.show("plainText", plainText, "plainText")
#O.show("userKey", userKey, "userKey")
 
K, KHat = makeSubkeys(userKey)
 
BHat = IP(plainText) # BHat_0 at this stage
for i in range(r):
BHat = R(i, BHat, KHat) # Produce BHat_i+1 from BHat_i
# BHat is now _32 i.e. _r
C = FP(BHat)
 
#O.show("cipherText", C, "cipherText")
 
return C
 
 
def encryptBitslice(plainText, userKey):
"""Encrypt the 128-bit bitstring 'plainText' with the 256-bit bitstring
'userKey', using the bitslice algorithm, and return a 128-bit ciphertext
bitstring."""
 
#O.show("fnTitle", "encryptBitslice", None, "tu")
#O.show("plainText", plainText, "plainText")
#O.show("userKey", userKey, "userKey")
 
K, KHat = makeSubkeys(userKey)
 
B = plainText # B_0 at this stage
for i in range(r):
B = RBitslice(i, B, K) # Produce B_i+1 from B_i
# B is now _r
 
#O.show("cipherText", B, "cipherText")
 
return B
 
def decrypt(cipherText, userKey):
"""Decrypt the 128-bit bitstring 'cipherText' with the 256-bit
bitstring 'userKey', using the normal algorithm, and return a 128-bit
plaintext bitstring."""
 
#O.show("fnTitle", "decrypt", None, "tu")
#O.show("cipherText", cipherText, "cipherText")
#O.show("userKey", userKey, "userKey")
 
K, KHat = makeSubkeys(userKey)
 
BHat = FPInverse(cipherText) # BHat_r at this stage
for i in range(r-1, -1, -1): # from r-1 down to 0 included
BHat = RInverse(i, BHat, KHat) # Produce BHat_i from BHat_i+1
# BHat is now _0
plainText = IPInverse(BHat)
 
#O.show("plainText", plainText, "plainText")
return plainText
 
 
def decryptBitslice(cipherText, userKey):
"""Decrypt the 128-bit bitstring 'cipherText' with the 256-bit
bitstring 'userKey', using the bitslice algorithm, and return a 128-bit
plaintext bitstring."""
 
#O.show("fnTitle", "decryptBitslice", None, "tu")
#O.show("cipherText", cipherText, "cipherText")
#O.show("userKey", userKey, "userKey")
 
K, KHat = makeSubkeys(userKey)
 
B = cipherText # B_r at this stage
for i in range(r-1, -1, -1): # from r-1 down to 0 included
B = RBitsliceInverse(i, B, K) # Produce B_i from B_i+1
# B is now _0
 
#O.show("plainText", B, "plainText")
return B
 
 
def makeSubkeys(userKey):
"""Given the 256-bit bitstring 'userKey' (shown as K in the paper, but
we can't use that name because of a collision with K[i] used later for
something else), return two lists (conceptually K and KHat) of 33
128-bit bitstrings each."""
 
# Because in Python I can't index a list from anything other than 0,
# I use a dictionary instead to legibly represent the w_i that are
# indexed from -8.
 
# We write the key as 8 32-bit words w-8 ... w-1
# ENOTE: w-8 is the least significant word
w = {}
for i in range(-8, 0):
w[i] = userKey[(i+8)*32:(i+9)*32]
#O.show("wi", w[i], "(i=%2d) wi" % i)
 
# We expand these to a prekey w0 ... w131 with the affine recurrence
for i in range(132):
w[i] = rotateLeft(
xor(w[i-8], w[i-5], w[i-3], w[i-1],
bitstring(phi, 32), bitstring(i,32)),
11)
#O.show("wi", w[i], "(i=%2d) wi" % i)
 
# The round keys are now calculated from the prekeys using the S-boxes
# in bitslice mode. Each k[i] is a 32-bit bitstring.
k = {}
for i in range(r+1):
whichS = (r + 3 - i) % r
k[0+4*i] = ""
k[1+4*i] = ""
k[2+4*i] = ""
k[3+4*i] = ""
for j in range(32): # for every bit in the k and w words
# ENOTE: w0 and k0 are the least significant words, w99 and k99
# the most.
input = w[0+4*i][j] + w[1+4*i][j] + w[2+4*i][j] + w[3+4*i][j]
output = S(whichS, input)
for l in range(4):
k[l+4*i] = k[l+4*i] + output[l]
 
# We then renumber the 32 bit values k_j as 128 bit subkeys K_i.
K = []
for i in range(33):
# ENOTE: k4i is the least significant word, k4i+3 the most.
K.append(k[4*i] + k[4*i+1] + k[4*i+2] + k[4*i+3])
 
# We now apply IP to the round key in order to place the key bits in
# the correct column
KHat = []
for i in range(33):
KHat.append(IP(K[i]))
 
#O.show("Ki", K[i], "(i=%2d) Ki" % i)
#O.show("KHati", KHat[i], "(i=%2d) KHati" % i)
 
return K, KHat
 
 
def makeLongKey(k):
"""Take a key k in bitstring format. Return the long version of that
key."""
 
l = len(k)
if l % 32 != 0 or l < 64 or l > 256:
raise ValueError, "Invalid key length (%d bits)" % l
 
if l == 256:
return k
else:
return k + "1" + "0"*(256 -l -1)
 
# --------------------------------------------------------------
# Generic bit-level primitives
 
# Internally, we represent the numbers manipulated by the cipher in a
# format that we call 'bitstring'. This is a string of "0" and "1"
# characters containing the binary representation of the number in
# little-endian format (so that subscripting with an index of i gives bit
# number i, corresponding to a weight of 2^i). This representation is only
# defined for nonnegative numbers (you can see why: think of the great
# unnecessary mess that would result from sign extension, two's complement
# and so on). Example: 10 decimal is "0101" in bitstring format.
 
def bitstring(n, minlen=1):
"""Translate n from integer to bitstring, padding it with 0s as
necessary to reach the minimum length 'minlen'. 'n' must be >= 0 since
the bitstring format is undefined for negative integers. Note that,
while the bitstring format can represent arbitrarily large numbers,
this is not so for Python's normal integer type: on a 32-bit machine,
values of n >= 2^31 need to be expressed as python long integers or
they will "look" negative and won't work. E.g. 0x80000000 needs to be
passed in as 0x80000000L, or it will be taken as -2147483648 instead of
+2147483648L.
 
EXAMPLE: bitstring(10, 8) -> "01010000"
"""
 
if minlen < 1:
raise ValueError, "a bitstring must have at least 1 char"
if n < 0:
raise ValueError, "bitstring representation undefined for neg numbers"
 
result = ""
while n > 0:
if n & 1:
result = result + "1"
else:
result = result + "0"
n = n >> 1
if len(result) < minlen:
result = result + "0" * (minlen - len(result))
return result
 
 
def binaryXor(n1, n2):
"""Return the xor of two bitstrings of equal length as another
bitstring of the same length.
 
EXAMPLE: binaryXor("10010", "00011") -> "10001"
"""
 
if len(n1) != len(n2):
raise ValueError, "can't xor bitstrings of different " + \
"lengths (%d and %d)" % (len(n1), len(n2))
# We assume that they are genuine bitstrings instead of just random
# character strings.
 
result = ""
for i in range(len(n1)):
if n1[i] == n2[i]:
result = result + "0"
else:
result = result + "1"
return result
 
 
def xor(*args):
"""Return the xor of an arbitrary number of bitstrings of the same
length as another bitstring of the same length.
 
EXAMPLE: xor("01", "11", "10") -> "00"
"""
 
if args == []:
raise ValueError, "at least one argument needed"
 
result = args[0]
for arg in args[1:]:
result = binaryXor(result, arg)
return result
 
 
def rotateLeft(input, places):
"""Take a bitstring 'input' of arbitrary length. Rotate it left by
'places' places. Left means that the 'places' most significant bits are
taken out and reinserted as the least significant bits. Note that,
because the bitstring representation is little-endian, the visual
effect is actually that of rotating the string to the right.
 
EXAMPLE: rotateLeft("000111", 2) -> "110001"
"""
 
p = places % len(input)
return input[-p:] + input[:-p]
 
def rotateRight(input, places):
return rotateLeft(input, -places)
 
def shiftLeft(input, p):
"""Take a bitstring 'input' of arbitrary length. Shift it left by 'p'
places. Left means that the 'p' most significant bits are shifted out
and dropped, while 'p' 0s are inserted in the the least significant
bits. Note that, because the bitstring representation is little-endian,
the visual effect is actually that of shifting the string to the
right. Negative values for 'p' are allowed, with the effect of shifting
right instead (i.e. the 0s are inserted in the most significant bits).
 
EXAMPLE: shiftLeft("000111", 2) -> "000001"
shiftLeft("000111", -2) -> "011100"
"""
 
if abs(p) >= len(input):
# Everything gets shifted out anyway
return "0" * len(input)
if p < 0:
# Shift right instead
return input[-p:] + "0" * len(input[:-p])
elif p == 0:
return input
else: # p > 0, normal case
return "0" * len(input[-p:]) + input[:-p]
 
def shiftRight(input, p):
"""Take a bitstring 'input' and shift it right by 'p' places. See the
doc for shiftLeft for more details."""
 
return shiftLeft(input, -p)
 
 
def keyLengthInBitsOf(k):
"""Take a string k in I/O format and return the number of bits in it."""
 
return len(k) * 4
 
# --------------------------------------------------------------
# Hex conversion functions
 
# For I/O we use BIG-ENDIAN hexstrings. Do not get confused: internal stuff
# is LITTLE-ENDIAN bitstrings (so that digit i has weight 2^i) while
# external stuff is in BIG-ENDIAN hexstrings (so that it's shorter and it
# looks like the numbers you normally write down). The external (I/O)
# representation is the same as used by the C reference implementation.
 
bin2hex = {
# Given a 4-char bitstring, return the corresponding 1-char hexstring
"0000": "0", "1000": "1", "0100": "2", "1100": "3",
"0010": "4", "1010": "5", "0110": "6", "1110": "7",
"0001": "8", "1001": "9", "0101": "a", "1101": "b",
"0011": "c", "1011": "d", "0111": "e", "1111": "f",
}
 
# Make the reverse lookup table too
hex2bin = {}
for (bin, hex) in bin2hex.items():
hex2bin[hex] = bin
 
 
def bitstring2hexstring(b):
"""Take bitstring 'b' and return the corresponding hexstring."""
 
result = ""
l = len(b)
if l % 4:
b = b + "0" * (4-(l%4))
for i in range(0, len(b), 4):
result = result+bin2hex[b[i:i+4]]
return reverseString(result)
 
def hexstring2bitstring(h):
"""Take hexstring 'h' and return the corresponding bitstring."""
 
result = ""
for c in reverseString(h):
result = result + hex2bin[c]
return result
 
def reverseString(s):
l = list(s)
l.reverse()
return string.join(l, "")
 
 
 
 
# --------------------------------------------------------------
# Format conversions
 
def quadSplit(b128):
"""Take a 128-bit bitstring and return it as a list of 4 32-bit
bitstrings, least significant bitstring first."""
 
if len(b128) != 128:
raise ValueError, "must be 128 bits long, not " + len(b128)
 
result = []
for i in range(4):
result.append(b128[(i*32):(i+1)*32])
return result
 
 
def quadJoin(l4x32):
"""Take a list of 4 32-bit bitstrings and return it as a single 128-bit
bitstring obtained by concatenating the internal ones."""
 
if len(l4x32) != 4:
raise ValueError, "need a list of 4 bitstrings, not " + len(l4x32)
 
return l4x32[0] + l4x32[1] + l4x32[2] + l4x32[3]
 
# --------------------------------------------------
# Seeing what happens inside
 
class Observer:
"""An object of this class can selectively display the values of the
variables you want to observe while the program is running. There are
tags that you can switch on or off. You sprinkle show() statements
throughout the program to show the value of a variable at a particular
point: show() will display the relevant variable only if the
corresponding tag is currently on. The special tag "ALL" forces all
show() statements to display their variable."""
 
typesOfVariable = {
"tu": "unknown", "tb": "bitstring", "tlb": "list of bitstrings",}
 
def __init__(self, tags=[]):
self.tags = {}
for tag in tags:
self.tags[tag] = 1
 
 
def addTag(self, *tags):
"""Add the supplied tag(s) to those that are currently active,
i.e. those that, if a corresponding "show()" is executed, will
print something."""
 
for t in tags:
self.tags[t] = 1
 
def removeTag(self, *tags):
"""Remove the supplied tag(s) from those currently active."""
for t in tags:
if t in self.tags.keys():
del self.tags[t]
 
def show(self, tag, variable, label=None, type="tb"):
"""Conditionally print a message with the current value of
'variable'. The message will only be printed if the supplied 'tag'
is among the active ones (or if the 'ALL' tag is active). The
'label', if not null, is printed before the value of the
'variable'; if it is null, it is substituted with the 'tag'. The
'type' of the 'variable' (giving us a clue on how to print it) must
be one of Observer.typesOfVariable."""
 
if label == None:
label = tag
if "ALL" in self.tags.keys() or tag in self.tags.keys():
if type == "tu":
output = `variable`
elif type == "tb":
output = bitstring2hexstring(variable)
elif type == "tlb":
output = ""
for item in variable:
output = output + " %s" % bitstring2hexstring(item)
output = "[" + output[1:] + "]"
else:
raise ValueError, "unknown type: %s. Valid ones are %s" % (
type, self.typesOfVariable.keys())
 
print label,
if output:
print "=", output
else:
print
 
 
# We make one global observer object that is always available
O = Observer(["plainText", "userKey", "cipherText"])
 
# --------------------------------------------------------------
# Constants
phi = 0x9e3779b9L
r = 32
# --------------------------------------------------------------
# Data tables
 
 
# Each element of this list corresponds to one S-box. Each S-box in turn is
# a list of 16 integers in the range 0..15, without repetitions. Having the
# value v (say, 14) in position p (say, 0) means that if the input to that
# S-box is the pattern p (0, or 0x0) then the output will be the pattern v
# (14, or 0xe).
SBoxDecimalTable = [
[ 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 ], # S0
[15,12, 2, 7, 9, 0, 5,10, 1,11,14, 8, 6,13, 3, 4 ], # S1
[ 8, 6, 7, 9, 3,12,10,15,13, 1,14, 4, 0,11, 5, 2 ], # S2
[ 0,15,11, 8,12, 9, 6, 3,13, 1, 2, 4,10, 7, 5,14 ], # S3
[ 1,15, 8, 3,12, 0,11, 6, 2, 5, 4,10, 9,14, 7,13 ], # S4
[15, 5, 2,11, 4,10, 9,12, 0, 3,14, 8,13, 6, 7, 1 ], # S5
[ 7, 2,12, 5, 8, 4, 6,11,14, 9, 1,15,13, 3,10, 0 ], # S6
[ 1,13,15, 0,14, 8, 2,11, 7, 4,12,10, 9, 3, 5, 6 ], # S7
]
# NB: in serpent-0, this was a list of 32 sublists (for the 32 different
# S-boxes derived from DES). In the final version of Serpent only 8 S-boxes
# are used, with each one being reused 4 times.
 
 
# Make another version of this table as a list of dictionaries: one
# dictionary per S-box, where the value of the entry indexed by i tells you
# the output configuration when the input is i, with both the index and the
# value being bitstrings. Make also the inverse: another list of
# dictionaries, one per S-box, where each dictionary gets the output of the
# S-box as the key and gives you the input, with both values being 4-bit
# bitstrings.
SBoxBitstring = []
SBoxBitstringInverse = []
for line in SBoxDecimalTable:
dict = {}
inverseDict = {}
for i in range(len(line)):
index = bitstring(i, 4)
value = bitstring(line[i], 4)
dict[index] = value
inverseDict[value] = index
SBoxBitstring.append(dict)
SBoxBitstringInverse.append(inverseDict)
 
 
# The Initial and Final permutations are each represented by one list
# containing the integers in 0..127 without repetitions. Having value v
# (say, 32) at position p (say, 1) means that the output bit at position p
# (1) comes from the input bit at position v (32).
IPTable = [
0, 32, 64, 96, 1, 33, 65, 97, 2, 34, 66, 98, 3, 35, 67, 99,
4, 36, 68, 100, 5, 37, 69, 101, 6, 38, 70, 102, 7, 39, 71, 103,
8, 40, 72, 104, 9, 41, 73, 105, 10, 42, 74, 106, 11, 43, 75, 107,
12, 44, 76, 108, 13, 45, 77, 109, 14, 46, 78, 110, 15, 47, 79, 111,
16, 48, 80, 112, 17, 49, 81, 113, 18, 50, 82, 114, 19, 51, 83, 115,
20, 52, 84, 116, 21, 53, 85, 117, 22, 54, 86, 118, 23, 55, 87, 119,
24, 56, 88, 120, 25, 57, 89, 121, 26, 58, 90, 122, 27, 59, 91, 123,
28, 60, 92, 124, 29, 61, 93, 125, 30, 62, 94, 126, 31, 63, 95, 127,
]
FPTable = [
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124,
1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61,
65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125,
2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62,
66, 70, 74, 78, 82, 86, 90, 94, 98, 102, 106, 110, 114, 118, 122, 126,
3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63,
67, 71, 75, 79, 83, 87, 91, 95, 99, 103, 107, 111, 115, 119, 123, 127,
]
 
 
# The Linear Transformation is represented as a list of 128 lists, one for
# each output bit. Each one of the 128 lists is composed of a variable
# number of integers in 0..127 specifying the positions of the input bits
# that must be XORed together (say, 72, 144 and 125) to yield the output
# bit corresponding to the position of that list (say, 1).
LTTable = [
[16, 52, 56, 70, 83, 94, 105],
[72, 114, 125],
[2, 9, 15, 30, 76, 84, 126],
[36, 90, 103],
[20, 56, 60, 74, 87, 98, 109],
[1, 76, 118],
[2, 6, 13, 19, 34, 80, 88],
[40, 94, 107],
[24, 60, 64, 78, 91, 102, 113],
[5, 80, 122],
[6, 10, 17, 23, 38, 84, 92],
[44, 98, 111],
[28, 64, 68, 82, 95, 106, 117],
[9, 84, 126],
[10, 14, 21, 27, 42, 88, 96],
[48, 102, 115],
[32, 68, 72, 86, 99, 110, 121],
[2, 13, 88],
[14, 18, 25, 31, 46, 92, 100],
[52, 106, 119],
[36, 72, 76, 90, 103, 114, 125],
[6, 17, 92],
[18, 22, 29, 35, 50, 96, 104],
[56, 110, 123],
[1, 40, 76, 80, 94, 107, 118],
[10, 21, 96],
[22, 26, 33, 39, 54, 100, 108],
[60, 114, 127],
[5, 44, 80, 84, 98, 111, 122],
[14, 25, 100],
[26, 30, 37, 43, 58, 104, 112],
[3, 118],
[9, 48, 84, 88, 102, 115, 126],
[18, 29, 104],
[30, 34, 41, 47, 62, 108, 116],
[7, 122],
[2, 13, 52, 88, 92, 106, 119],
[22, 33, 108],
[34, 38, 45, 51, 66, 112, 120],
[11, 126],
[6, 17, 56, 92, 96, 110, 123],
[26, 37, 112],
[38, 42, 49, 55, 70, 116, 124],
[2, 15, 76],
[10, 21, 60, 96, 100, 114, 127],
[30, 41, 116],
[0, 42, 46, 53, 59, 74, 120],
[6, 19, 80],
[3, 14, 25, 100, 104, 118],
[34, 45, 120],
[4, 46, 50, 57, 63, 78, 124],
[10, 23, 84],
[7, 18, 29, 104, 108, 122],
[38, 49, 124],
[0, 8, 50, 54, 61, 67, 82],
[14, 27, 88],
[11, 22, 33, 108, 112, 126],
[0, 42, 53],
[4, 12, 54, 58, 65, 71, 86],
[18, 31, 92],
[2, 15, 26, 37, 76, 112, 116],
[4, 46, 57],
[8, 16, 58, 62, 69, 75, 90],
[22, 35, 96],
[6, 19, 30, 41, 80, 116, 120],
[8, 50, 61],
[12, 20, 62, 66, 73, 79, 94],
[26, 39, 100],
[10, 23, 34, 45, 84, 120, 124],
[12, 54, 65],
[16, 24, 66, 70, 77, 83, 98],
[30, 43, 104],
[0, 14, 27, 38, 49, 88, 124],
[16, 58, 69],
[20, 28, 70, 74, 81, 87, 102],
[34, 47, 108],
[0, 4, 18, 31, 42, 53, 92],
[20, 62, 73],
[24, 32, 74, 78, 85, 91, 106],
[38, 51, 112],
[4, 8, 22, 35, 46, 57, 96],
[24, 66, 77],
[28, 36, 78, 82, 89, 95, 110],
[42, 55, 116],
[8, 12, 26, 39, 50, 61, 100],
[28, 70, 81],
[32, 40, 82, 86, 93, 99, 114],
[46, 59, 120],
[12, 16, 30, 43, 54, 65, 104],
[32, 74, 85],
[36, 90, 103, 118],
[50, 63, 124],
[16, 20, 34, 47, 58, 69, 108],
[36, 78, 89],
[40, 94, 107, 122],
[0, 54, 67],
[20, 24, 38, 51, 62, 73, 112],
[40, 82, 93],
[44, 98, 111, 126],
[4, 58, 71],
[24, 28, 42, 55, 66, 77, 116],
[44, 86, 97],
[2, 48, 102, 115],
[8, 62, 75],
[28, 32, 46, 59, 70, 81, 120],
[48, 90, 101],
[6, 52, 106, 119],
[12, 66, 79],
[32, 36, 50, 63, 74, 85, 124],
[52, 94, 105],
[10, 56, 110, 123],
[16, 70, 83],
[0, 36, 40, 54, 67, 78, 89],
[56, 98, 109],
[14, 60, 114, 127],
[20, 74, 87],
[4, 40, 44, 58, 71, 82, 93],
[60, 102, 113],
[3, 18, 72, 114, 118, 125],
[24, 78, 91],
[8, 44, 48, 62, 75, 86, 97],
[64, 106, 117],
[1, 7, 22, 76, 118, 122],
[28, 82, 95],
[12, 48, 52, 66, 79, 90, 101],
[68, 110, 121],
[5, 11, 26, 80, 122, 126],
[32, 86, 99],
]
 
# The following table is necessary for the non-bitslice decryption.
LTTableInverse = [
[53, 55, 72],
[1, 5, 20, 90],
[15, 102],
[3, 31, 90],
[57, 59, 76],
[5, 9, 24, 94],
[19, 106],
[7, 35, 94],
[61, 63, 80],
[9, 13, 28, 98],
[23, 110],
[11, 39, 98],
[65, 67, 84],
[13, 17, 32, 102],
[27, 114],
[1, 3, 15, 20, 43, 102],
[69, 71, 88],
[17, 21, 36, 106],
[1, 31, 118],
[5, 7, 19, 24, 47, 106],
[73, 75, 92],
[21, 25, 40, 110],
[5, 35, 122],
[9, 11, 23, 28, 51, 110],
[77, 79, 96],
[25, 29, 44, 114],
[9, 39, 126],
[13, 15, 27, 32, 55, 114],
[81, 83, 100],
[1, 29, 33, 48, 118],
[2, 13, 43],
[1, 17, 19, 31, 36, 59, 118],
[85, 87, 104],
[5, 33, 37, 52, 122],
[6, 17, 47],
[5, 21, 23, 35, 40, 63, 122],
[89, 91, 108],
[9, 37, 41, 56, 126],
[10, 21, 51],
[9, 25, 27, 39, 44, 67, 126],
[93, 95, 112],
[2, 13, 41, 45, 60],
[14, 25, 55],
[2, 13, 29, 31, 43, 48, 71],
[97, 99, 116],
[6, 17, 45, 49, 64],
[18, 29, 59],
[6, 17, 33, 35, 47, 52, 75],
[101, 103, 120],
[10, 21, 49, 53, 68],
[22, 33, 63],
[10, 21, 37, 39, 51, 56, 79],
[105, 107, 124],
[14, 25, 53, 57, 72],
[26, 37, 67],
[14, 25, 41, 43, 55, 60, 83],
[0, 109, 111],
[18, 29, 57, 61, 76],
[30, 41, 71],
[18, 29, 45, 47, 59, 64, 87],
[4, 113, 115],
[22, 33, 61, 65, 80],
[34, 45, 75],
[22, 33, 49, 51, 63, 68, 91],
[8, 117, 119],
[26, 37, 65, 69, 84],
[38, 49, 79],
[26, 37, 53, 55, 67, 72, 95],
[12, 121, 123],
[30, 41, 69, 73, 88],
[42, 53, 83],
[30, 41, 57, 59, 71, 76, 99],
[16, 125, 127],
[34, 45, 73, 77, 92],
[46, 57, 87],
[34, 45, 61, 63, 75, 80, 103],
[1, 3, 20],
[38, 49, 77, 81, 96],
[50, 61, 91],
[38, 49, 65, 67, 79, 84, 107],
[5, 7, 24],
[42, 53, 81, 85, 100],
[54, 65, 95],
[42, 53, 69, 71, 83, 88, 111],
[9, 11, 28],
[46, 57, 85, 89, 104],
[58, 69, 99],
[46, 57, 73, 75, 87, 92, 115],
[13, 15, 32],
[50, 61, 89, 93, 108],
[62, 73, 103],
[50, 61, 77, 79, 91, 96, 119],
[17, 19, 36],
[54, 65, 93, 97, 112],
[66, 77, 107],
[54, 65, 81, 83, 95, 100, 123],
[21, 23, 40],
[58, 69, 97, 101, 116],
[70, 81, 111],
[58, 69, 85, 87, 99, 104, 127],
[25, 27, 44],
[62, 73, 101, 105, 120],
[74, 85, 115],
[3, 62, 73, 89, 91, 103, 108],
[29, 31, 48],
[66, 77, 105, 109, 124],
[78, 89, 119],
[7, 66, 77, 93, 95, 107, 112],
[33, 35, 52],
[0, 70, 81, 109, 113],
[82, 93, 123],
[11, 70, 81, 97, 99, 111, 116],
[37, 39, 56],
[4, 74, 85, 113, 117],
[86, 97, 127],
[15, 74, 85, 101, 103, 115, 120],
[41, 43, 60],
[8, 78, 89, 117, 121],
[3, 90],
[19, 78, 89, 105, 107, 119, 124],
[45, 47, 64],
[12, 82, 93, 121, 125],
[7, 94],
[0, 23, 82, 93, 109, 111, 123],
[49, 51, 68],
[1, 16, 86, 97, 125],
[11, 98],
[4, 27, 86, 97, 113, 115, 127],
]
 
 
# --------------------------------------------------
# Handling command line arguments and stuff
 
help = """
# $Id: serpref.py,v 1.19 1998/09/02 21:28:02 fms Exp $
#
# Python reference implementation of Serpent.
#
# Written by Frank Stajano,
# Olivetti Oracle Research Laboratory <http://www.orl.co.uk/~fms/> and
# Cambridge University Computer Laboratory <http://www.cl.cam.ac.uk/~fms27/>.
#
# (c) 1998 Olivetti Oracle Research Laboratory (ORL)
#
# Original (Python) Serpent reference development started on 1998 02 12.
# C implementation development started on 1998 03 04.
#
# Serpent cipher invented by Ross Anderson, Eli Biham, Lars Knudsen.
# Serpent is a candidate for the Advanced Encryption Standard.
 
Encrypts or decrypts one block of data using the Serpent cipher and
optionally showing you what's going on inside at the various stages of
the computation.
 
SYNTAX: serpref mode [options]
 
MODE is one of the following:
-e -> encrypt
-d -> decrypt
-h -> help (the text you're reading right now)
 
OPTIONS are:
-p plainText -> The 128-bit value to be encrypted. Required in mode -e,
ignored otherwise. Short texts are zeropadded.
-c cipherText -> The 128-bit value to be decrypted. Required in mode -d,
ignored otherwise. Short texts are zeropadded.
-k key -> The value of the key (allowed lengths are from 64 to
256 bits, but must be a multiple of 32 bits). Keys
shorter than 256 bits are internally transformed into
the equivalent long keys (NOT the same as zeropadding!).
Required for -e and -d.
-t tagName -> Turn on the observer tag with that name. This means that
any observer messages associated with this tag will
now be displayed. This option may be specified several
times to add multiple tags.
The special tag ALL turns on all the messages.
 
-b -> Use the bitslice version instead of the traditional
version, which is otherwise used by default. Optional.
 
TAGS:
These are the tags of the quantities you can currently observe with
-t. Names are modelled on the paper's notation.
 
For the non-bitslice: BHati xored SHati BHatiPlus1 wi KHati
For the bitslice: Bi xored Si BiPlus1 wi Ki
Generic: plainText userKey cipherText testTitle fnTitle
 
 
I/O FORMAT:
All I/O is performed using hex numbers of the appropriate size, written
as sequences of hex digits, most significant digit first (big-endian),
without any leading or trailing markers such as 0x, &, h or whatever.
Example: the number ten is "a" in four bits or "000a" in sixteen bits.
 
 
USAGE EXAMPLES:
 
serpref -e -k 123456789abcdef -p 0
Encrypt the plaintext "all zeros" with the given key.
 
serpref -e -b -k 123456789abcdef -p 0
Same as above, but the extra -b requests bitslice operation. As
things are, we won't notice the difference, but see below...
 
serpref -e -b -k 123456789abcdef -p 0 -t Bi
Same as above, but the "-t Bi" prints out all the intermediate
results with a tag of Bi, allowing you to see what happens inside
the rounds. Compare this with the following...
 
serpref -e -k 123456789abcdef -p 0 -t BHati
Same as above except that we are back to the non-bitslice version
(there is no -b) and we are printing the items with the BHati tag
(which is the equivalent of Bi for the non-bitslice version).
 
serpref -e -k 123456789abcdef -p 0 -t xored -t SHati -t BHati
Same as above but we are requesting even more details, basically
looking at all the intermediate results of each round as well. (You
could use the single magic tag -t ALL if you didn't want to have to
find out the names of the individual tags.)
"""
 
 
def helpExit(message = None):
print help
if message:
print "ERROR:", message
sys.exit()
 
def convertToBitstring(input, numBits):
"""Take a string 'input', theoretically in std I/O format, but in
practice liable to contain any sort of crap since it's user supplied,
and return its bitstring representation, normalised to numBits
bits. Raise the appropriate variant of ValueError (with explanatory
message) if anything can't be done (this includes the case where the
'input', while otherwise syntactically correct, can't be represented in
'numBits' bits)."""
 
if re.match("^[0-9a-f]+$", input):
bitstring = hexstring2bitstring(input)
else:
raise ValueError, "%s is not a valid hexstring" % input
 
# assert: bitstring now contains the bitstring version of the input
 
if len(bitstring) > numBits:
# Last chance: maybe it's got some useless 0s...
if re.match("^0+$", bitstring[numBits:]):
bitstring = bitstring[:numBits]
else:
raise ValueError, "input too large to fit in %d bits" % numBits
else:
bitstring = bitstring + "0" * (numBits-len(bitstring))
 
return bitstring
 
 
def main():
 
optList, rest = getopt.getopt(sys.argv[1:], "edhbt:k:p:c:")
 
if rest:
helpExit("Sorry, can't make sense of this: '%s'" % rest)
 
# Transform the list of options into a more comfortable
# dictionary. This only works with non-repeated options, though, so
# tags (which are repeated) must be dealt with separately.
options = {}
for key, value in optList:
if key == "-t":
O.addTag(value)
else:
if key in options.keys():
helpExit("Multiple occurrences of " + key)
else:
options[string.strip(key)] = string.strip(value)
 
# Not more than one mode
mode = None
for k in options.keys():
if k in ["-e", "-d", "-h"]:
if mode:
helpExit("you can only specify one mode")
else:
mode = k
if not mode:
helpExit("No mode specified")
 
# Put plainText, userKey, cipherText in bitstring format.
plainText = userKey = cipherText = None
if options.has_key("-k"):
bitsInKey = keyLengthInBitsOf(options["-k"])
rawKey = convertToBitstring(options["-k"], bitsInKey)
userKey = makeLongKey(rawKey)
if options.has_key("-p"):
plainText = convertToBitstring(options["-p"], 128)
if options.has_key("-c"):
cipherText = convertToBitstring(options["-c"], 128)
if mode == "-e" or mode == "-d":
if not userKey:
helpExit("-k (key) required with -e (encrypt) or -d (decrypt)")
if mode == "-e":
if not plainText:
helpExit("-p (plaintext) is required when doing -e (encrypt)")
if mode == "-d":
if not cipherText:
helpExit("-c (ciphertext) is required when doing -d (decrypt)")
 
# Perform the action specified by the mode
# NOTE that the observer will automatically print the basic stuff such
# as plainText, userKey and cipherText (in the right format too), so we
# only need to perform the action, without adding any extra print
# statements here.
if mode == "-e":
if options.has_key("-b"):
cipherText = encryptBitslice(plainText, userKey)
else:
cipherText = encrypt(plainText, userKey)
elif mode == "-d":
if options.has_key("-b"):
plainText = decryptBitslice(cipherText, userKey)
else:
plainText = decrypt(cipherText, userKey)
elif mode == "-s":
O.addTag("testTitle", "fnTitle")
 
printTest(test1(plainText, userKey))
printTest(test2(plainText, userKey))
printTest(test3(plainText, userKey))
else:
helpExit()
 
 
if __name__ == "__main__":
main()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/CAST.py
0,0 → 1,57
from blockcipher import *
import Crypto.Cipher.CAST
 
def new(key,mode=MODE_ECB,IV=None,counter=None,segment_size=None):
"""Create a new cipher object
 
CAST using pycrypto for algo and pycryptoplus for ciphermode
 
key = raw string containing the keys
mode = python_AES.MODE_ECB/CBC/CFB/OFB/CTR/CMAC, default is ECB
IV = IV as a raw string, default is "all zero" IV
-> only needed for CBC mode
counter = counter object (CryptoPlus.Util.util.Counter)
-> only needed for CTR mode
segment_size = amount of bits to use from the keystream in each chain part
-> supported values: multiple of 8 between 8 and the blocksize
of the cipher (only per byte access possible), default is 8
-> only needed for CFB mode
 
EXAMPLES:
**********
IMPORTING:
-----------
>>> from CryptoPlus.Cipher import CAST
 
ECB example: http://www.rfc-editor.org/rfc/rfc2144.txt
-------------
128 bit key
 
>>> key = "0123456712345678234567893456789A".decode('hex')
>>> plaintext = "0123456789ABCDEF".decode('hex')
>>> cipher = CAST.new(key,CAST.MODE_ECB,)
>>> cipher.encrypt(plaintext).encode('hex')
'238b4fe5847e44b2'
 
40 bit key
>>> from CryptoPlus.Cipher import CAST
>>> key = "0123456712".decode('hex')
>>> plaintext = "0123456789ABCDEF".decode('hex')
>>> cipher = CAST.new(key,CAST.MODE_ECB,)
>>> cipher.encrypt(plaintext).encode('hex').upper()
'7AC816D16E9B302E'
"""
return CAST(key,mode,IV,counter,segment_size)
 
class CAST(BlockCipher):
def __init__(self,key,mode,IV,counter,segment_size):
cipher_module = Crypto.Cipher.CAST.new
self.blocksize = 8
BlockCipher.__init__(self,key,mode,IV,counter,cipher_module,segment_size)
 
def _test():
import doctest
doctest.testmod()
 
if __name__ == "__main__":
_test()
/relevation/branches/1.1-PyCryptoPlus/python-cryptoplus/src/CryptoPlus/Cipher/pytwofish.py
0,0 → 1,397
## twofish.py - pure Python implementation of the Twofish algorithm.
## Bjorn Edstrom <be@bjrn.se> 13 december 2007.
##
## Copyrights
## ==========
##
## This code is a derived from an implementation by Dr Brian Gladman
## (gladman@seven77.demon.co.uk) which is subject to the following license.
## This Python implementation is not subject to any other license.
##
##/* This is an independent implementation of the encryption algorithm: */
##/* */
##/* Twofish by Bruce Schneier and colleagues */
##/* */
##/* which is a candidate algorithm in the Advanced Encryption Standard */
##/* programme of the US National Institute of Standards and Technology. */
##/* */
##/* Copyright in this implementation is held by Dr B R Gladman but I */
##/* hereby give permission for its free direct or derivative use subject */
##/* to acknowledgment of its origin and compliance with any conditions */
##/* that the originators of t he algorithm place on its exploitation. */
##/* */
##/* My thanks to Doug Whiting and Niels Ferguson for comments that led */
##/* to improvements in this implementation. */
##/* */
##/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */
##
## The above copyright notice must not be removed.
##
## Information
## ===========
##
## Anyone thinking of using this code should reconsider. It's slow.
## Try python-mcrypt instead. In case a faster library is not installed
## on the target system, this code can be used as a portable fallback.
 
try:
import psyco
psyco.full()
except ImportError:
pass
 
block_size = 16
key_size = 32
 
class Twofish:
 
def __init__(self, key=None):
"""Twofish."""
 
if key:
self.set_key(key)
 
 
def set_key(self, key):
"""Init."""
 
key_len = len(key)
if key_len not in [16, 24, 32]:
# XXX: add padding?
raise KeyError, "key must be 16, 24 or 32 bytes"
if key_len % 4:
# XXX: add padding?
raise KeyError, "key not a multiple of 4"
if key_len > 32:
# XXX: prune?
raise KeyError, "key_len > 32"
 
self.context = TWI()
 
key_word32 = [0] * 32
i = 0
while key:
key_word32[i] = struct.unpack("<L", key[0:4])[0]
key = key[4:]
i += 1
 
set_key(self.context, key_word32, key_len)
 
 
def decrypt(self, block):
"""Decrypt blocks."""
 
if len(block) % 16:
raise ValueError, "block size must be a multiple of 16"
 
plaintext = ''
 
while block:
a, b, c, d = struct.unpack("<4L", block[:16])
temp = [a, b, c, d]
decrypt(self.context, temp)
plaintext += struct.pack("<4L", *temp)
block = block[16:]
 
return plaintext
 
 
def encrypt(self, block):
"""Encrypt blocks."""
 
if len(block) % 16:
raise ValueError, "block size must be a multiple of 16"
 
ciphertext = ''
 
while block:
a, b, c, d = struct.unpack("<4L", block[0:16])
temp = [a, b, c, d]
encrypt(self.context, temp)
ciphertext += struct.pack("<4L", *temp)
block = block[16:]
 
return ciphertext
 
 
def get_name(self):
"""Return the name of the cipher."""
 
return "Twofish"
 
 
def get_block_size(self):
"""Get cipher block size in bytes."""
 
return 16
 
 
def get_key_size(self):
"""Get cipher key size in bytes."""
 
return 32
 
 
#
# Private.
#
 
import struct
import sys
 
WORD_BIGENDIAN = 0
if sys.byteorder == 'big':
WORD_BIGENDIAN = 1
 
def rotr32(x, n):
return (x >> n) | ((x << (32 - n)) & 0xFFFFFFFF)
 
def rotl32(x, n):
return ((x << n) & 0xFFFFFFFF) | (x >> (32 - n))
 
def byteswap32(x):
return ((x & 0xff) << 24) | (((x >> 8) & 0xff) << 16) | \
(((x >> 16) & 0xff) << 8) | ((x >> 24) & 0xff)
 
class TWI:
def __init__(self):
self.k_len = 0 # word32
self.l_key = [0]*40 # word32
self.s_key = [0]*4 # word32
self.qt_gen = 0 # word32
self.q_tab = [[0]*256, [0]*256] # byte
self.mt_gen = 0 # word32
self.m_tab = [[0]*256, [0]*256, [0]*256, [0]*256] # word32
self.mk_tab = [[0]*256, [0]*256, [0]*256, [0]*256] # word32
 
def byte(x, n):
return (x >> (8 * n)) & 0xff
 
tab_5b = [0, 90, 180, 238]
tab_ef = [0, 238, 180, 90]
ror4 = [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]
ashx = [0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7]
qt0 = [[8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4],
[2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5]]
qt1 = [[14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13],
[1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8]]
qt2 = [[11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1],
[4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15]]
qt3 = [[13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10],
[11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10]]
 
def qp(n, x): # word32, byte
n %= 0x100000000
x %= 0x100
a0 = x >> 4;
b0 = x & 15;
a1 = a0 ^ b0;
b1 = ror4[b0] ^ ashx[a0];
a2 = qt0[n][a1];
b2 = qt1[n][b1];
a3 = a2 ^ b2;
b3 = ror4[b2] ^ ashx[a2];
a4 = qt2[n][a3];
b4 = qt3[n][b3];
return (b4 << 4) | a4;
 
def gen_qtab(pkey):
for i in xrange(256):
pkey.q_tab[0][i] = qp(0, i)
pkey.q_tab[1][i] = qp(1, i)
 
def gen_mtab(pkey):
for i in xrange(256):
f01 = pkey.q_tab[1][i]
f01 = pkey.q_tab[1][i];
f5b = ((f01) ^ ((f01) >> 2) ^ tab_5b[(f01) & 3]);
fef = ((f01) ^ ((f01) >> 1) ^ ((f01) >> 2) ^ tab_ef[(f01) & 3]);
pkey.m_tab[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24);
pkey.m_tab[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24);
 
f01 = pkey.q_tab[0][i];
f5b = ((f01) ^ ((f01) >> 2) ^ tab_5b[(f01) & 3]);
fef = ((f01) ^ ((f01) >> 1) ^ ((f01) >> 2) ^ tab_ef[(f01) & 3]);
pkey.m_tab[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24);
pkey.m_tab[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24);
 
def gen_mk_tab(pkey, key):
if pkey.k_len == 2:
for i in xrange(256):
by = i % 0x100
pkey.mk_tab[0][i] = pkey.m_tab[0][pkey.q_tab[0][pkey.q_tab[0][by] ^ byte(key[1],0)] ^ byte(key[0],0)];
pkey.mk_tab[1][i] = pkey.m_tab[1][pkey.q_tab[0][pkey.q_tab[1][by] ^ byte(key[1],1)] ^ byte(key[0],1)];
pkey.mk_tab[2][i] = pkey.m_tab[2][pkey.q_tab[1][pkey.q_tab[0][by] ^ byte(key[1],2)] ^ byte(key[0],2)];
pkey.mk_tab[3][i] = pkey.m_tab[3][pkey.q_tab[1][pkey.q_tab[1][by] ^ byte(key[1],3)] ^ byte(key[0],3)];
if pkey.k_len == 3:
for i in xrange(256):
by = i % 0x100
pkey.mk_tab[0][i] = pkey.m_tab[0][pkey.q_tab[0][pkey.q_tab[0][pkey.q_tab[1][by] ^ byte(key[2], 0)] ^ byte(key[1], 0)] ^ byte(key[0], 0)];
pkey.mk_tab[1][i] = pkey.m_tab[1][pkey.q_tab[0][pkey.q_tab[1][pkey.q_tab[1][by] ^ byte(key[2], 1)] ^ byte(key[1], 1)] ^ byte(key[0], 1)];
pkey.mk_tab[2][i] = pkey.m_tab[2][pkey.q_tab[1][pkey.q_tab[0][pkey.q_tab[0][by] ^ byte(key[2], 2)] ^ byte(key[1], 2)] ^ byte(key[0], 2)];
pkey.mk_tab[3][i] = pkey.m_tab[3][pkey.q_tab[1][pkey.q_tab[1][pkey.q_tab[0][by] ^ byte(key[2], 3)] ^ byte(key[1], 3)] ^ byte(key[0], 3)];
if pkey.k_len == 4:
for i in xrange(256):
by = i % 0x100
pkey.mk_tab[0][i] = pkey.m_tab[0][pkey.q_tab[0][pkey.q_tab[0][pkey.q_tab[1][pkey.q_tab[1][by] ^ byte(key[3], 0)] ^ byte(key[2], 0)] ^ byte(key[1], 0)] ^ byte(key[0], 0)];
pkey.mk_tab[1][i] = pkey.m_tab[1][pkey.q_tab[0][pkey.q_tab[1][pkey.q_tab[1][pkey.q_tab[0][by] ^ byte(key[3], 1)] ^ byte(key[2], 1)] ^ byte(key[1], 1)] ^ byte(key[0], 1)];
pkey.mk_tab[2][i] = pkey.m_tab[2][pkey.q_tab[1][pkey.q_tab[0][pkey.q_tab[0][pkey.q_tab[0][by] ^ byte(key[3], 2)] ^ byte(key[2], 2)] ^ byte(key[1], 2)] ^ byte(key[0], 2)];
pkey.mk_tab[3][i] = pkey.m_tab[3][pkey.q_tab[1][pkey.q_tab[1][pkey.q_tab[0][pkey.q_tab[1][by] ^ byte(key[3], 3)] ^ byte(key[2], 3)] ^ byte(key[1], 3)] ^ byte(key[0], 3)];
 
def h_fun(pkey, x, key):
b0 = byte(x, 0);
b1 = byte(x, 1);
b2 = byte(x, 2);
b3 = byte(x, 3);
if pkey.k_len >= 4:
b0 = pkey.q_tab[1][b0] ^ byte(key[3], 0);
b1 = pkey.q_tab[0][b1] ^ byte(key[3], 1);
b2 = pkey.q_tab[0][b2] ^ byte(key[3], 2);
b3 = pkey.q_tab[1][b3] ^ byte(key[3], 3);
if pkey.k_len >= 3:
b0 = pkey.q_tab[1][b0] ^ byte(key[2], 0);
b1 = pkey.q_tab[1][b1] ^ byte(key[2], 1);
b2 = pkey.q_tab[0][b2] ^ byte(key[2], 2);
b3 = pkey.q_tab[0][b3] ^ byte(key[2], 3);
if pkey.k_len >= 2:
b0 = pkey.q_tab[0][pkey.q_tab[0][b0] ^ byte(key[1], 0)] ^ byte(key[0], 0);
b1 = pkey.q_tab[0][pkey.q_tab[1][b1] ^ byte(key[1], 1)] ^ byte(key[0], 1);
b2 = pkey.q_tab[1][pkey.q_tab[0][b2] ^ byte(key[1], 2)] ^ byte(key[0], 2);
b3 = pkey.q_tab[1][pkey.q_tab[1][b3] ^ byte(key[1], 3)] ^ byte(key[0], 3);
return pkey.m_tab[0][b0] ^ pkey.m_tab[1][b1] ^ pkey.m_tab[2][b2] ^ pkey.m_tab[3][b3];
 
def mds_rem(p0, p1):
i, t, u = 0, 0, 0
for i in xrange(8):
t = p1 >> 24
p1 = ((p1 << 8) & 0xffffffff) | (p0 >> 24)
p0 = (p0 << 8) & 0xffffffff
u = (t << 1) & 0xffffffff
if t & 0x80:
u ^= 0x0000014d
p1 ^= t ^ ((u << 16) & 0xffffffff)
u ^= (t >> 1)
if t & 0x01:
u ^= 0x0000014d >> 1
p1 ^= ((u << 24) & 0xffffffff) | ((u << 8) & 0xffffffff)
return p1
 
def set_key(pkey, in_key, key_len):
pkey.qt_gen = 0
if not pkey.qt_gen:
gen_qtab(pkey)
pkey.qt_gen = 1
pkey.mt_gen = 0
if not pkey.mt_gen:
gen_mtab(pkey)
pkey.mt_gen = 1
pkey.k_len = (key_len * 8) / 64
 
a = 0
b = 0
me_key = [0,0,0,0]
mo_key = [0,0,0,0]
for i in xrange(pkey.k_len):
if WORD_BIGENDIAN:
a = byteswap32(in_key[i + 1])
me_key[i] = a
b = byteswap32(in_key[i + i + 1])
else:
a = in_key[i + i]
me_key[i] = a
b = in_key[i + i + 1]
mo_key[i] = b
pkey.s_key[pkey.k_len - i - 1] = mds_rem(a, b);
for i in xrange(0, 40, 2):
a = (0x01010101 * i) % 0x100000000;
b = (a + 0x01010101) % 0x100000000;
a = h_fun(pkey, a, me_key);
b = rotl32(h_fun(pkey, b, mo_key), 8);
pkey.l_key[i] = (a + b) % 0x100000000;
pkey.l_key[i + 1] = rotl32((a + 2 * b) % 0x100000000, 9);
gen_mk_tab(pkey, pkey.s_key)
 
def encrypt(pkey, in_blk):
blk = [0, 0, 0, 0]
 
if WORD_BIGENDIAN:
blk[0] = byteswap32(in_blk[0]) ^ pkey.l_key[0];
blk[1] = byteswap32(in_blk[1]) ^ pkey.l_key[1];
blk[2] = byteswap32(in_blk[2]) ^ pkey.l_key[2];
blk[3] = byteswap32(in_blk[3]) ^ pkey.l_key[3];
else:
blk[0] = in_blk[0] ^ pkey.l_key[0];
blk[1] = in_blk[1] ^ pkey.l_key[1];
blk[2] = in_blk[2] ^ pkey.l_key[2];
blk[3] = in_blk[3] ^ pkey.l_key[3];
 
for i in xrange(8):
t1 = ( pkey.mk_tab[0][byte(blk[1],3)] ^ pkey.mk_tab[1][byte(blk[1],0)] ^ pkey.mk_tab[2][byte(blk[1],1)] ^ pkey.mk_tab[3][byte(blk[1],2)] );
t0 = ( pkey.mk_tab[0][byte(blk[0],0)] ^ pkey.mk_tab[1][byte(blk[0],1)] ^ pkey.mk_tab[2][byte(blk[0],2)] ^ pkey.mk_tab[3][byte(blk[0],3)] );
 
blk[2] = rotr32(blk[2] ^ ((t0 + t1 + pkey.l_key[4 * (i) + 8]) % 0x100000000), 1);
blk[3] = rotl32(blk[3], 1) ^ ((t0 + 2 * t1 + pkey.l_key[4 * (i) + 9]) % 0x100000000);
 
t1 = ( pkey.mk_tab[0][byte(blk[3],3)] ^ pkey.mk_tab[1][byte(blk[3],0)] ^ pkey.mk_tab[2][byte(blk[3],1)] ^ pkey.mk_tab[3][byte(blk[3],2)] );
t0 = ( pkey.mk_tab[0][byte(blk[2],0)] ^ pkey.mk_tab[1][byte(blk[2],1)] ^ pkey.mk_tab[2][byte(blk[2],2)] ^ pkey.mk_tab[3][byte(blk[2],3)] );
 
blk[0] = rotr32(blk[0] ^ ((t0 + t1 + pkey.l_key[4 * (i) + 10]) % 0x100000000), 1);
blk[1] = rotl32(blk[1], 1) ^ ((t0 + 2 * t1 + pkey.l_key[4 * (i) + 11]) % 0x100000000);
 
if WORD_BIGENDIAN:
in_blk[0] = byteswap32(blk[2] ^ pkey.l_key[4]);
in_blk[1] = byteswap32(blk[3] ^ pkey.l_key[5]);
in_blk[2] = byteswap32(blk[0] ^ pkey.l_key[6]);
in_blk[3] = byteswap32(blk[1] ^ pkey.l_key[7]);
else:
in_blk[0] = blk[2] ^ pkey.l_key[4];
in_blk[1] = blk[3] ^ pkey.l_key[5];
in_blk[2] = blk[0] ^ pkey.l_key[6];
in_blk[3] = blk[1] ^ pkey.l_key[7];
 
return
 
def decrypt(pkey, in_blk):
blk = [0, 0, 0, 0]
 
if WORD_BIGENDIAN:
blk[0] = byteswap32(in_blk[0]) ^ pkey.l_key[4];
blk[1] = byteswap32(in_blk[1]) ^ pkey.l_key[5];
blk[2] = byteswap32(in_blk[2]) ^ pkey.l_key[6];
blk[3] = byteswap32(in_blk[3]) ^ pkey.l_key[7];
else:
blk[0] = in_blk[0] ^ pkey.l_key[4];
blk[1] = in_blk[1] ^ pkey.l_key[5];
blk[2] = in_blk[2] ^ pkey.l_key[6];
blk[3] = in_blk[3] ^ pkey.l_key[7];
 
for i in xrange(7, -1, -1):
t1 = ( pkey.mk_tab[0][byte(blk[1],3)] ^ pkey.mk_tab[1][byte(blk[1],0)] ^ pkey.mk_tab[2][byte(blk[1],1)] ^ pkey.mk_tab[3][byte(blk[1],2)] )
t0 = ( pkey.mk_tab[0][byte(blk[0],0)] ^ pkey.mk_tab[1][byte(blk[0],1)] ^ pkey.mk_tab[2][byte(blk[0],2)] ^ pkey.mk_tab[3][byte(blk[0],3)] )
 
blk[2] = rotl32(blk[2], 1) ^ ((t0 + t1 + pkey.l_key[4 * (i) + 10]) % 0x100000000)
blk[3] = rotr32(blk[3] ^ ((t0 + 2 * t1 + pkey.l_key[4 * (i) + 11]) % 0x100000000), 1)
 
t1 = ( pkey.mk_tab[0][byte(blk[3],3)] ^ pkey.mk_tab[1][byte(blk[3],0)] ^ pkey.mk_tab[2][byte(blk[3],1)] ^ pkey.mk_tab[3][byte(blk[3],2)] )
t0 = ( pkey.mk_tab[0][byte(blk[2],0)] ^ pkey.mk_tab[1][byte(blk[2],1)] ^ pkey.mk_tab[2][byte(blk[2],2)] ^ pkey.mk_tab[3][byte(blk[2],3)] )
 
blk[0] = rotl32(blk[0], 1) ^ ((t0 + t1 + pkey.l_key[4 * (i) + 8]) % 0x100000000)
blk[1] = rotr32(blk[1] ^ ((t0 + 2 * t1 + pkey.l_key[4 * (i) + 9]) % 0x100000000), 1)
 
if WORD_BIGENDIAN:
in_blk[0] = byteswap32(blk[2] ^ pkey.l_key[0]);
in_blk[1] = byteswap32(blk[3] ^ pkey.l_key[1]);
in_blk[2] = byteswap32(blk[0] ^ pkey.l_key[2]);
in_blk[3] = byteswap32(blk[1] ^ pkey.l_key[3]);
else:
in_blk[0] = blk[2] ^ pkey.l_key[0];
in_blk[1] = blk[3] ^ pkey.l_key[1];
in_blk[2] = blk[0] ^ pkey.l_key[2];
in_blk[3] = blk[1] ^ pkey.l_key[3];
return
 
__testkey = '\xD4\x3B\xB7\x55\x6E\xA3\x2E\x46\xF2\xA2\x82\xB7\xD4\x5B\x4E\x0D\x57\xFF\x73\x9D\x4D\xC9\x2C\x1B\xD7\xFC\x01\x70\x0C\xC8\x21\x6F'
__testdat = '\x90\xAF\xE9\x1B\xB2\x88\x54\x4F\x2C\x32\xDC\x23\x9B\x26\x35\xE6'
assert 'l\xb4V\x1c@\xbf\n\x97\x05\x93\x1c\xb6\xd4\x08\xe7\xfa' == Twofish(__testkey).encrypt(__testdat)
assert __testdat == Twofish(__testkey).decrypt('l\xb4V\x1c@\xbf\n\x97\x05\x93\x1c\xb6\xd4\x08\xe7\xfa')