Tutorial¶
PEP-272 compliant TEA cipher
Note
Before starting, first things first: This library is for creating block cipher implementations only! It does not contain or implement any ciphers by itself.
0. The TEA block cipher¶
In this tutorial the TEA block cipher will be used as the underlying block cipher and give it a PEP-272 interface.
TEA uses 128-bit (16 bytes) keys and 64-bit (8 bytes) blocks.
In Python, an unoptimized version of TEA can be written like following:
import struct
def encrypt_tea(value, key, endian="!", rounds=64):
v0, v1 = struct.unpack(endian + "2L", value)
k = struct.unpack(endian + "4L", key)
# mask is an uint32 helper
delta, mask, sum = 0x9e3779b9, 0xffffffff, 0
for i in range(rounds//2):
sum = (sum + delta) & mask
v0 = v0 + ( ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1]) ) & mask
v1 = v1 + ( ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3]) ) & mask
return struct.pack(endian + "2L", v0, v1)
def decrypt_tea(value, key, endian="!", rounds=64):
v0, v1 = struct.unpack(endian + "2L", value)
k = struct.unpack(endian + "4L", key)
# mask is an uint32 helper
delta, mask = 0x9e3779b9, 0xffffffff
sum = (delta * rounds // 2) & mask
for i in range(rounds//2):
v1 = v1 - ( ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3]) ) & mask
v0 = v0 - ( ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1]) ) & mask
sum = (sum - delta) & mask
return struct.pack(endian + "2L", v0, v1)
(It runs slow because integers can get quite big before the mask is applied.)
1. Project skeleton¶
To begin, import the pep272-encryption module:
from pep272_encryption import PEP272Cipher, MODE_ECB, MODE_CBC, \
MODE_CFB, MODE_OFB, \
MODE_CTR
2. Setting parameters¶
Next define some module level constants, as defined per PEP-272:
block_size = 8 # 64-bit blocks
key_size = 16 # 128-bit keys
3. Subclassing¶
Subclass the PEP272Cipher class, setting the block size parameter and override encrypt_block and decrypt_block methods:
class TEACipher(PEP272Cipher):
block_size = block_size
def encrypt_block(self, key, block, **kwargs):
return encrypt_tea(block, key,
kwargs.get('endian', '!'),
kwargs.get('rounds', 64))
def decrypt_block(self, key, block, **kwargs):
return decrypt_tea(block, key,
kwargs.get('endian', '!'),
kwargs.get('rounds', 64))
4. Alternative constructor (new-method)¶
An alternative constructor is usefull for interoperbility:
def new(*args, **kwargs):
return TEACipher(*args, **kwargs)
5. Full example code¶
Below is the full example code with all snippets combined: A PEP-272 compliant implementation of the TEA block cipher in pure python, that is interchangeble with other ciphers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | import struct
from pep272_encryption import PEP272Cipher
from pep272_encryption import MODE_ECB, MODE_CBC, MODE_CFB, MODE_OFB, \
MODE_CTR
block_size = 8 # 64-bit blocks
key_size = 16 # 128-bit keys
def new(*args, **kwargs):
return TEACipher(*args, **kwargs)
class TEACipher(PEP272Cipher):
block_size = block_size
def encrypt_block(self, key, block, **kwargs):
return encrypt_tea(block, key,
kwargs.get('endian', '!'),
kwargs.get('rounds', 64))
def decrypt_block(self, key, block, **kwargs):
return decrypt_tea(block, key,
kwargs.get('endian', '!'),
kwargs.get('rounds', 64))
def encrypt_tea(value, key, endian="!", rounds=64):
v0, v1 = struct.unpack(endian + "2L", value)
k = struct.unpack(endian + "4L", key)
# mask is an uint32 helper
delta, mask, sum = 0x9e3779b9, 0xffffffff, 0
for i in range(rounds//2):
sum = (sum + delta) & mask
v0 = v0 + ( ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1]) ) & mask
v1 = v1 + ( ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3]) ) & mask
return struct.pack(endian + "2L", v0, v1)
def decrypt_tea(value, key, endian="!", rounds=64):
v0, v1 = struct.unpack(endian + "2L", value)
k = struct.unpack(endian + "4L", key)
# mask is an uint32 helper
delta, mask = 0x9e3779b9, 0xffffffff
sum = (delta * rounds // 2) & mask
for i in range(rounds//2):
v1 = v1 - ( ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3]) ) & mask
v0 = v0 - ( ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1]) ) & mask
sum = (sum - delta) & mask
return struct.pack(endian + "2L", v0, v1)
|
Download full example: tea.py
6. Usage¶
Now the newly created library can be used easily.
Example: Encrypt some data in OFB mode.
>>> import tea
>>> cipher = tea.new(b'16-bytes key 123', mode=tea.MODE_OFB, IV=b'\00'*8)
>>> cipher.encrypt(b'123456'*6)
b"k\xaf F\xfb*\xeb\x00'kP\x9c\xc9M\xb99\x1cy\xda\x99\xb1\xf0H\x14\x9c\xae@\xddxe`\x01\x85\xc9p\x85"