remove pyaes from src/lib
it's now a standard dependency
This commit is contained in:
parent
1d8aedce85
commit
1e6bb43ac0
6 changed files with 0 additions and 1314 deletions
|
@ -1,22 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Richard Moore
|
||||
|
||||
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.
|
||||
|
|
@ -1,363 +0,0 @@
|
|||
pyaes
|
||||
=====
|
||||
|
||||
A pure-Python implementation of the AES block cipher algorithm and the common modes of operation (CBC, CFB, CTR, ECB and OFB).
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Supports all AES key sizes
|
||||
* Supports all AES common modes
|
||||
* Pure-Python (no external dependencies)
|
||||
* BlockFeeder API allows streams to easily be encrypted and decrypted
|
||||
* Python 2.x and 3.x support (make sure you pass in bytes(), not strings for Python 3)
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
All keys may be 128 bits (16 bytes), 192 bits (24 bytes) or 256 bits (32 bytes) long.
|
||||
|
||||
To generate a random key use:
|
||||
```python
|
||||
import os
|
||||
|
||||
# 128 bit, 192 bit and 256 bit keys
|
||||
key_128 = os.urandom(16)
|
||||
key_192 = os.urandom(24)
|
||||
key_256 = os.urandom(32)
|
||||
```
|
||||
|
||||
To generate keys from simple-to-remember passwords, consider using a _password-based key-derivation function_ such as [scrypt](https://github.com/ricmoo/pyscrypt).
|
||||
|
||||
|
||||
### Common Modes of Operation
|
||||
|
||||
There are many modes of operations, each with various pros and cons. In general though, the **CBC** and **CTR** modes are recommended. The **ECB is NOT recommended.**, and is included primarily for completeness.
|
||||
|
||||
Each of the following examples assumes the following key:
|
||||
```python
|
||||
import pyaes
|
||||
|
||||
# A 256 bit (32 byte) key
|
||||
key = "This_key_for_demo_purposes_only!"
|
||||
|
||||
# For some modes of operation we need a random initialization vector
|
||||
# of 16 bytes
|
||||
iv = "InitializationVe"
|
||||
```
|
||||
|
||||
|
||||
#### Counter Mode of Operation (recommended)
|
||||
|
||||
```python
|
||||
aes = pyaes.AESModeOfOperationCTR(key)
|
||||
plaintext = "Text may be any length you wish, no padding is required"
|
||||
ciphertext = aes.encrypt(plaintext)
|
||||
|
||||
# '''\xb6\x99\x10=\xa4\x96\x88\xd1\x89\x1co\xe6\x1d\xef;\x11\x03\xe3\xee
|
||||
# \xa9V?wY\xbfe\xcdO\xe3\xdf\x9dV\x19\xe5\x8dk\x9fh\xb87>\xdb\xa3\xd6
|
||||
# \x86\xf4\xbd\xb0\x97\xf1\t\x02\xe9 \xed'''
|
||||
print repr(ciphertext)
|
||||
|
||||
# The counter mode of operation maintains state, so decryption requires
|
||||
# a new instance be created
|
||||
aes = pyaes.AESModeOfOperationCTR(key)
|
||||
decrypted = aes.decrypt(ciphertext)
|
||||
|
||||
# True
|
||||
print decrypted == plaintext
|
||||
|
||||
# To use a custom initial value
|
||||
counter = pyaes.Counter(initial_value = 100)
|
||||
aes = pyaes.AESModeOfOperationCTR(key, counter = counter)
|
||||
ciphertext = aes.encrypt(plaintext)
|
||||
|
||||
# '''WZ\x844\x02\xbfoY\x1f\x12\xa6\xce\x03\x82Ei)\xf6\x97mX\x86\xe3\x9d
|
||||
# _1\xdd\xbd\x87\xb5\xccEM_4\x01$\xa6\x81\x0b\xd5\x04\xd7Al\x07\xe5
|
||||
# \xb2\x0e\\\x0f\x00\x13,\x07'''
|
||||
print repr(ciphertext)
|
||||
```
|
||||
|
||||
|
||||
#### Cipher-Block Chaining (recommended)
|
||||
|
||||
```python
|
||||
aes = pyaes.AESModeOfOperationCBC(key, iv = iv)
|
||||
plaintext = "TextMustBe16Byte"
|
||||
ciphertext = aes.encrypt(plaintext)
|
||||
|
||||
# '\xd6:\x18\xe6\xb1\xb3\xc3\xdc\x87\xdf\xa7|\x08{k\xb6'
|
||||
print repr(ciphertext)
|
||||
|
||||
|
||||
# The cipher-block chaining mode of operation maintains state, so
|
||||
# decryption requires a new instance be created
|
||||
aes = pyaes.AESModeOfOperationCBC(key, iv = iv)
|
||||
decrypted = aes.decrypt(ciphertext)
|
||||
|
||||
# True
|
||||
print decrypted == plaintext
|
||||
```
|
||||
|
||||
|
||||
#### Cipher Feedback
|
||||
|
||||
```python
|
||||
# Each block into the mode of operation must be a multiple of the segment
|
||||
# size. For this example we choose 8 bytes.
|
||||
aes = pyaes.AESModeOfOperationCFB(key, iv = iv, segment_size = 8)
|
||||
plaintext = "TextMustBeAMultipleOfSegmentSize"
|
||||
ciphertext = aes.encrypt(plaintext)
|
||||
|
||||
# '''v\xa9\xc1w"\x8aL\x93\xcb\xdf\xa0/\xf8Y\x0b\x8d\x88i\xcb\x85rmp
|
||||
# \x85\xfe\xafM\x0c)\xd5\xeb\xaf'''
|
||||
print repr(ciphertext)
|
||||
|
||||
|
||||
# The cipher-block chaining mode of operation maintains state, so
|
||||
# decryption requires a new instance be created
|
||||
aes = pyaes.AESModeOfOperationCFB(key, iv = iv, segment_size = 8)
|
||||
decrypted = aes.decrypt(ciphertext)
|
||||
|
||||
# True
|
||||
print decrypted == plaintext
|
||||
```
|
||||
|
||||
|
||||
#### Output Feedback Mode of Operation
|
||||
|
||||
```python
|
||||
aes = pyaes.AESModeOfOperationOFB(key, iv = iv)
|
||||
plaintext = "Text may be any length you wish, no padding is required"
|
||||
ciphertext = aes.encrypt(plaintext)
|
||||
|
||||
# '''v\xa9\xc1wO\x92^\x9e\rR\x1e\xf7\xb1\xa2\x9d"l1\xc7\xe7\x9d\x87(\xc26s
|
||||
# \xdd8\xc8@\xb6\xd9!\xf5\x0cM\xaa\x9b\xc4\xedLD\xe4\xb9\xd8\xdf\x9e\xac
|
||||
# \xa1\xb8\xea\x0f\x8ev\xb5'''
|
||||
print repr(ciphertext)
|
||||
|
||||
# The counter mode of operation maintains state, so decryption requires
|
||||
# a new instance be created
|
||||
aes = pyaes.AESModeOfOperationOFB(key, iv = iv)
|
||||
decrypted = aes.decrypt(ciphertext)
|
||||
|
||||
# True
|
||||
print decrypted == plaintext
|
||||
```
|
||||
|
||||
|
||||
#### Electronic Codebook (NOT recommended)
|
||||
|
||||
```python
|
||||
aes = pyaes.AESModeOfOperationECB(key)
|
||||
plaintext = "TextMustBe16Byte"
|
||||
ciphertext = aes.encrypt(plaintext)
|
||||
|
||||
# 'L6\x95\x85\xe4\xd9\xf1\x8a\xfb\xe5\x94X\x80|\x19\xc3'
|
||||
print repr(ciphertext)
|
||||
|
||||
# Since there is no state stored in this mode of operation, it
|
||||
# is not necessary to create a new aes object for decryption.
|
||||
#aes = pyaes.AESModeOfOperationECB(key)
|
||||
decrypted = aes.decrypt(ciphertext)
|
||||
|
||||
# True
|
||||
print decrypted == plaintext
|
||||
```
|
||||
|
||||
|
||||
### BlockFeeder
|
||||
|
||||
Since most of the modes of operations require data in specific block-sized or segment-sized blocks, it can be difficult when working with large arbitrary streams or strings of data.
|
||||
|
||||
The BlockFeeder class is meant to make life easier for you, by buffering bytes across multiple calls and returning bytes as they are available, as well as padding or stripping the output when finished, if necessary.
|
||||
|
||||
```python
|
||||
import pyaes
|
||||
|
||||
# Any mode of operation can be used; for this example CBC
|
||||
key = "This_key_for_demo_purposes_only!"
|
||||
iv = "InitializationVe"
|
||||
|
||||
ciphertext = ''
|
||||
|
||||
# We can encrypt one line at a time, regardles of length
|
||||
encrypter = pyaes.Encrypter(pyaes.AESModeOfOperationCBC(key, iv))
|
||||
for line in file('/etc/passwd'):
|
||||
ciphertext += encrypter.feed(line)
|
||||
|
||||
# Make a final call to flush any remaining bytes and add paddin
|
||||
ciphertext += encrypter.feed()
|
||||
|
||||
# We can decrypt the cipher text in chunks (here we split it in half)
|
||||
decrypter = pyaes.Decrypter(pyaes.AESModeOfOperationCBC(key, iv))
|
||||
decrypted = decrypter.feed(ciphertext[:len(ciphertext) / 2])
|
||||
decrypted += decrypter.feed(ciphertext[len(ciphertext) / 2:])
|
||||
|
||||
# Again, make a final call to flush any remaining bytes and strip padding
|
||||
decrypted += decrypter.feed()
|
||||
|
||||
print file('/etc/passwd').read() == decrypted
|
||||
```
|
||||
|
||||
### Stream Feeder
|
||||
|
||||
This is meant to make it even easier to encrypt and decrypt streams and large files.
|
||||
|
||||
```python
|
||||
import pyaes
|
||||
|
||||
# Any mode of operation can be used; for this example CTR
|
||||
key = "This_key_for_demo_purposes_only!"
|
||||
|
||||
# Create the mode of operation to encrypt with
|
||||
mode = pyaes.AESModeOfOperationCTR(key)
|
||||
|
||||
# The input and output files
|
||||
file_in = file('/etc/passwd')
|
||||
file_out = file('/tmp/encrypted.bin', 'wb')
|
||||
|
||||
# Encrypt the data as a stream, the file is read in 8kb chunks, be default
|
||||
pyaes.encrypt_stream(mode, file_in, file_out)
|
||||
|
||||
# Close the files
|
||||
file_in.close()
|
||||
file_out.close()
|
||||
```
|
||||
|
||||
Decrypting is identical, except you would use `pyaes.decrypt_stream`, and the encrypted file would be the `file_in` and target for decryption the `file_out`.
|
||||
|
||||
### AES block cipher
|
||||
|
||||
Generally you should use one of the modes of operation above. This may however be useful for experimenting with a custom mode of operation or dealing with encrypted blocks.
|
||||
|
||||
The block cipher requires exactly one block of data to encrypt or decrypt, and each block should be an array with each element an integer representation of a byte.
|
||||
|
||||
```python
|
||||
import pyaes
|
||||
|
||||
# 16 byte block of plain text
|
||||
plaintext = "Hello World!!!!!"
|
||||
plaintext_bytes = [ ord(c) for c in plaintext ]
|
||||
|
||||
# 32 byte key (256 bit)
|
||||
key = "This_key_for_demo_purposes_only!"
|
||||
|
||||
# Our AES instance
|
||||
aes = pyaes.AES(key)
|
||||
|
||||
# Encrypt!
|
||||
ciphertext = aes.encrypt(plaintext_bytes)
|
||||
|
||||
# [55, 250, 182, 25, 185, 208, 186, 95, 206, 115, 50, 115, 108, 58, 174, 115]
|
||||
print repr(ciphertext)
|
||||
|
||||
# Decrypt!
|
||||
decrypted = aes.decrypt(ciphertext)
|
||||
|
||||
# True
|
||||
print decrypted == plaintext_bytes
|
||||
```
|
||||
|
||||
What is a key?
|
||||
--------------
|
||||
|
||||
This seems to be a point of confusion for many people new to using encryption. You can think of the key as the *"password"*. However, these algorithms require the *"password"* to be a specific length.
|
||||
|
||||
With AES, there are three possible key lengths, 16-bytes, 24-bytes or 32-bytes. When you create an AES object, the key size is automatically detected, so it is important to pass in a key of the correct length.
|
||||
|
||||
Often, you wish to provide a password of arbitrary length, for example, something easy to remember or write down. In these cases, you must come up with a way to transform the password into a key, of a specific length. A **Password-Based Key Derivation Function** (PBKDF) is an algorithm designed for this exact purpose.
|
||||
|
||||
Here is an example, using the popular (possibly obsolete?) *crypt* PBKDF:
|
||||
|
||||
```
|
||||
# See: https://www.dlitz.net/software/python-pbkdf2/
|
||||
import pbkdf2
|
||||
|
||||
password = "HelloWorld"
|
||||
|
||||
# The crypt PBKDF returns a 48-byte string
|
||||
key = pbkdf2.crypt(password)
|
||||
|
||||
# A 16-byte, 24-byte and 32-byte key, respectively
|
||||
key_16 = key[:16]
|
||||
key_24 = key[:24]
|
||||
key_32 = key[:32]
|
||||
```
|
||||
|
||||
The [scrypt](https://github.com/ricmoo/pyscrypt) PBKDF is intentionally slow, to make it more difficult to brute-force guess a password:
|
||||
|
||||
```
|
||||
# See: https://github.com/ricmoo/pyscrypt
|
||||
import pyscrypt
|
||||
|
||||
password = "HelloWorld"
|
||||
|
||||
# Salt is required, and prevents Rainbow Table attacks
|
||||
salt = "SeaSalt"
|
||||
|
||||
# N, r, and p are parameters to specify how difficult it should be to
|
||||
# generate a key; bigger numbers take longer and more memory
|
||||
N = 1024
|
||||
r = 1
|
||||
p = 1
|
||||
|
||||
# A 16-byte, 24-byte and 32-byte key, respectively; the scrypt algorithm takes
|
||||
# a 6-th parameter, indicating key length
|
||||
key_16 = pyscrypt.hash(password, salt, N, r, p, 16)
|
||||
key_24 = pyscrypt.hash(password, salt, N, r, p, 24)
|
||||
key_32 = pyscrypt.hash(password, salt, N, r, p, 32)
|
||||
```
|
||||
|
||||
Another possibility, is to use a hashing function, such as SHA256 to hash the password, but this method may be vulnerable to [Rainbow Attacks](http://en.wikipedia.org/wiki/Rainbow_table), unless you use a [salt](http://en.wikipedia.org/wiki/Salt_(cryptography)).
|
||||
|
||||
```python
|
||||
import hashlib
|
||||
|
||||
password = "HelloWorld"
|
||||
|
||||
# The SHA256 hash algorithm returns a 32-byte string
|
||||
hashed = hashlib.sha256(password).digest()
|
||||
|
||||
# A 16-byte, 24-byte and 32-byte key, respectively
|
||||
key_16 = hashed[:16]
|
||||
key_24 = hashed[:24]
|
||||
key_32 = hashed
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
Performance
|
||||
-----------
|
||||
|
||||
There is a test case provided in _/tests/test-aes.py_ which does some basic performance testing (its primary purpose is moreso as a regression test).
|
||||
|
||||
Based on that test, in **CPython**, this library is about 30x slower than [PyCrypto](https://www.dlitz.net/software/pycrypto/) for CBC, ECB and OFB; about 80x slower for CFB; and 300x slower for CTR.
|
||||
|
||||
Based on that same test, in **Pypy**, this library is about 4x slower than [PyCrypto](https://www.dlitz.net/software/pycrypto/) for CBC, ECB and OFB; about 12x slower for CFB; and 19x slower for CTR.
|
||||
|
||||
The PyCrypto documentation makes reference to the counter call being responsible for the speed problems of the counter (CTR) mode of operation, which is why they use a specially optimized counter. I will investigate this problem further in the future.
|
||||
|
||||
|
||||
FAQ
|
||||
---
|
||||
|
||||
#### Why do this?
|
||||
|
||||
The short answer, *why not?*
|
||||
|
||||
The longer answer, is for my [pyscrypt](https://github.com/ricmoo/pyscrypt) library. I required a pure-Python AES implementation that supported 256-bit keys with the counter (CTR) mode of operation. After searching, I found several implementations, but all were missing CTR or only supported 128 bit keys. After all the work of learning AES inside and out to implement the library, it was only a marginal amount of extra work to library-ify a more general solution. So, *why not?*
|
||||
|
||||
#### How do I get a question I have added?
|
||||
|
||||
E-mail me at pyaes@ricmoo.com with any questions, suggestions, comments, et cetera.
|
||||
|
||||
|
||||
#### Can I give you my money?
|
||||
|
||||
Umm... Ok? :-)
|
||||
|
||||
_Bitcoin_ - `18UDs4qV1shu2CgTS2tKojhCtM69kpnWg9`
|
|
@ -1,53 +0,0 @@
|
|||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2014 Richard Moore
|
||||
#
|
||||
# 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.
|
||||
|
||||
# This is a pure-Python implementation of the AES algorithm and AES common
|
||||
# modes of operation.
|
||||
|
||||
# See: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
|
||||
# See: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
|
||||
|
||||
|
||||
# Supported key sizes:
|
||||
# 128-bit
|
||||
# 192-bit
|
||||
# 256-bit
|
||||
|
||||
|
||||
# Supported modes of operation:
|
||||
# ECB - Electronic Codebook
|
||||
# CBC - Cipher-Block Chaining
|
||||
# CFB - Cipher Feedback
|
||||
# OFB - Output Feedback
|
||||
# CTR - Counter
|
||||
|
||||
# See the README.md for API details and general information.
|
||||
|
||||
# Also useful, PyCrypto, a crypto library implemented in C with Python bindings:
|
||||
# https://www.dlitz.net/software/pycrypto/
|
||||
|
||||
|
||||
VERSION = [1, 3, 0]
|
||||
|
||||
from .aes import AES, AESModeOfOperationCTR, AESModeOfOperationCBC, AESModeOfOperationCFB, AESModeOfOperationECB, AESModeOfOperationOFB, AESModesOfOperation, Counter
|
||||
from .blockfeeder import decrypt_stream, Decrypter, encrypt_stream, Encrypter
|
||||
from .blockfeeder import PADDING_NONE, PADDING_DEFAULT
|
|
@ -1,589 +0,0 @@
|
|||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2014 Richard Moore
|
||||
#
|
||||
# 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.
|
||||
|
||||
# This is a pure-Python implementation of the AES algorithm and AES common
|
||||
# modes of operation.
|
||||
|
||||
# See: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
|
||||
|
||||
# Honestly, the best description of the modes of operations are the wonderful
|
||||
# diagrams on Wikipedia. They explain in moments what my words could never
|
||||
# achieve. Hence the inline documentation here is sparer than I'd prefer.
|
||||
# See: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
|
||||
|
||||
# Also useful, PyCrypto, a crypto library implemented in C with Python bindings:
|
||||
# https://www.dlitz.net/software/pycrypto/
|
||||
|
||||
|
||||
# Supported key sizes:
|
||||
# 128-bit
|
||||
# 192-bit
|
||||
# 256-bit
|
||||
|
||||
|
||||
# Supported modes of operation:
|
||||
# ECB - Electronic Codebook
|
||||
# CBC - Cipher-Block Chaining
|
||||
# CFB - Cipher Feedback
|
||||
# OFB - Output Feedback
|
||||
# CTR - Counter
|
||||
|
||||
|
||||
# See the README.md for API details and general information.
|
||||
|
||||
|
||||
import copy
|
||||
import struct
|
||||
|
||||
__all__ = ["AES", "AESModeOfOperationCTR", "AESModeOfOperationCBC", "AESModeOfOperationCFB",
|
||||
"AESModeOfOperationECB", "AESModeOfOperationOFB", "AESModesOfOperation", "Counter"]
|
||||
|
||||
|
||||
def _compact_word(word):
|
||||
return (word[0] << 24) | (word[1] << 16) | (word[2] << 8) | word[3]
|
||||
|
||||
def _string_to_bytes(text):
|
||||
return list(ord(c) for c in text)
|
||||
|
||||
def _bytes_to_string(binary):
|
||||
return "".join(chr(b) for b in binary)
|
||||
|
||||
def _concat_list(a, b):
|
||||
return a + b
|
||||
|
||||
|
||||
# Python 3 compatibility
|
||||
try:
|
||||
xrange
|
||||
except Exception:
|
||||
xrange = range
|
||||
|
||||
# Python 3 supports bytes, which is already an array of integers
|
||||
def _string_to_bytes(text):
|
||||
if isinstance(text, bytes):
|
||||
return text
|
||||
return [ord(c) for c in text]
|
||||
|
||||
# In Python 3, we return bytes
|
||||
def _bytes_to_string(binary):
|
||||
return bytes(binary)
|
||||
|
||||
# Python 3 cannot concatenate a list onto a bytes, so we bytes-ify it first
|
||||
def _concat_list(a, b):
|
||||
return a + bytes(b)
|
||||
|
||||
|
||||
# Based *largely* on the Rijndael implementation
|
||||
# See: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
class AES(object):
|
||||
'''Encapsulates the AES block cipher.
|
||||
|
||||
You generally should not need this. Use the AESModeOfOperation classes
|
||||
below instead.'''
|
||||
|
||||
# Number of rounds by keysize
|
||||
number_of_rounds = {16: 10, 24: 12, 32: 14}
|
||||
|
||||
# Round constant words
|
||||
rcon = [ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 ]
|
||||
|
||||
# S-box and Inverse S-box (S is for Substitution)
|
||||
S = [ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 ]
|
||||
Si =[ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d ]
|
||||
|
||||
# Transformations for encryption
|
||||
T1 = [ 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a ]
|
||||
T2 = [ 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616 ]
|
||||
T3 = [ 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16 ]
|
||||
T4 = [ 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c ]
|
||||
|
||||
# Transformations for decryption
|
||||
T5 = [ 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742 ]
|
||||
T6 = [ 0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857 ]
|
||||
T7 = [ 0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8 ]
|
||||
T8 = [ 0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0 ]
|
||||
|
||||
# Transformations for decryption key expansion
|
||||
U1 = [ 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3 ]
|
||||
U2 = [ 0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, 0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, 0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, 0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697 ]
|
||||
U3 = [ 0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, 0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, 0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, 0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46 ]
|
||||
U4 = [ 0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, 0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, 0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, 0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d ]
|
||||
|
||||
def __init__(self, key):
|
||||
|
||||
if len(key) not in (16, 24, 32):
|
||||
raise ValueError('Invalid key size')
|
||||
|
||||
rounds = self.number_of_rounds[len(key)]
|
||||
|
||||
# Encryption round keys
|
||||
self._Ke = [[0] * 4 for i in xrange(rounds + 1)]
|
||||
|
||||
# Decryption round keys
|
||||
self._Kd = [[0] * 4 for i in xrange(rounds + 1)]
|
||||
|
||||
round_key_count = (rounds + 1) * 4
|
||||
KC = len(key) // 4
|
||||
|
||||
# Convert the key into ints
|
||||
tk = [ struct.unpack('>i', key[i:i + 4])[0] for i in xrange(0, len(key), 4) ]
|
||||
|
||||
# Copy values into round key arrays
|
||||
for i in xrange(0, KC):
|
||||
self._Ke[i // 4][i % 4] = tk[i]
|
||||
self._Kd[rounds - (i // 4)][i % 4] = tk[i]
|
||||
|
||||
# Key expansion (fips-197 section 5.2)
|
||||
rconpointer = 0
|
||||
t = KC
|
||||
while t < round_key_count:
|
||||
|
||||
tt = tk[KC - 1]
|
||||
tk[0] ^= ((self.S[(tt >> 16) & 0xFF] << 24) ^
|
||||
(self.S[(tt >> 8) & 0xFF] << 16) ^
|
||||
(self.S[ tt & 0xFF] << 8) ^
|
||||
self.S[(tt >> 24) & 0xFF] ^
|
||||
(self.rcon[rconpointer] << 24))
|
||||
rconpointer += 1
|
||||
|
||||
if KC != 8:
|
||||
for i in xrange(1, KC):
|
||||
tk[i] ^= tk[i - 1]
|
||||
|
||||
# Key expansion for 256-bit keys is "slightly different" (fips-197)
|
||||
else:
|
||||
for i in xrange(1, KC // 2):
|
||||
tk[i] ^= tk[i - 1]
|
||||
tt = tk[KC // 2 - 1]
|
||||
|
||||
tk[KC // 2] ^= (self.S[ tt & 0xFF] ^
|
||||
(self.S[(tt >> 8) & 0xFF] << 8) ^
|
||||
(self.S[(tt >> 16) & 0xFF] << 16) ^
|
||||
(self.S[(tt >> 24) & 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:
|
||||
self._Ke[t // 4][t % 4] = tk[j]
|
||||
self._Kd[rounds - (t // 4)][t % 4] = tk[j]
|
||||
j += 1
|
||||
t += 1
|
||||
|
||||
# Inverse-Cipher-ify the decryption round key (fips-197 section 5.3)
|
||||
for r in xrange(1, rounds):
|
||||
for j in xrange(0, 4):
|
||||
tt = self._Kd[r][j]
|
||||
self._Kd[r][j] = (self.U1[(tt >> 24) & 0xFF] ^
|
||||
self.U2[(tt >> 16) & 0xFF] ^
|
||||
self.U3[(tt >> 8) & 0xFF] ^
|
||||
self.U4[ tt & 0xFF])
|
||||
|
||||
def encrypt(self, plaintext):
|
||||
'Encrypt a block of plain text using the AES block cipher.'
|
||||
|
||||
if len(plaintext) != 16:
|
||||
raise ValueError('wrong block length')
|
||||
|
||||
rounds = len(self._Ke) - 1
|
||||
(s1, s2, s3) = [1, 2, 3]
|
||||
a = [0, 0, 0, 0]
|
||||
|
||||
# Convert plaintext to (ints ^ key)
|
||||
t = [(_compact_word(plaintext[4 * i:4 * i + 4]) ^ self._Ke[0][i]) for i in xrange(0, 4)]
|
||||
|
||||
# Apply round transforms
|
||||
for r in xrange(1, rounds):
|
||||
for i in xrange(0, 4):
|
||||
a[i] = (self.T1[(t[ i ] >> 24) & 0xFF] ^
|
||||
self.T2[(t[(i + s1) % 4] >> 16) & 0xFF] ^
|
||||
self.T3[(t[(i + s2) % 4] >> 8) & 0xFF] ^
|
||||
self.T4[ t[(i + s3) % 4] & 0xFF] ^
|
||||
self._Ke[r][i])
|
||||
t = copy.copy(a)
|
||||
|
||||
# The last round is special
|
||||
result = [ ]
|
||||
for i in xrange(0, 4):
|
||||
tt = self._Ke[rounds][i]
|
||||
result.append((self.S[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
|
||||
result.append((self.S[(t[(i + s1) % 4] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
|
||||
result.append((self.S[(t[(i + s2) % 4] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
|
||||
result.append((self.S[ t[(i + s3) % 4] & 0xFF] ^ tt ) & 0xFF)
|
||||
|
||||
return result
|
||||
|
||||
def decrypt(self, ciphertext):
|
||||
'Decrypt a block of cipher text using the AES block cipher.'
|
||||
|
||||
if len(ciphertext) != 16:
|
||||
raise ValueError('wrong block length')
|
||||
|
||||
rounds = len(self._Kd) - 1
|
||||
(s1, s2, s3) = [3, 2, 1]
|
||||
a = [0, 0, 0, 0]
|
||||
|
||||
# Convert ciphertext to (ints ^ key)
|
||||
t = [(_compact_word(ciphertext[4 * i:4 * i + 4]) ^ self._Kd[0][i]) for i in xrange(0, 4)]
|
||||
|
||||
# Apply round transforms
|
||||
for r in xrange(1, rounds):
|
||||
for i in xrange(0, 4):
|
||||
a[i] = (self.T5[(t[ i ] >> 24) & 0xFF] ^
|
||||
self.T6[(t[(i + s1) % 4] >> 16) & 0xFF] ^
|
||||
self.T7[(t[(i + s2) % 4] >> 8) & 0xFF] ^
|
||||
self.T8[ t[(i + s3) % 4] & 0xFF] ^
|
||||
self._Kd[r][i])
|
||||
t = copy.copy(a)
|
||||
|
||||
# The last round is special
|
||||
result = [ ]
|
||||
for i in xrange(0, 4):
|
||||
tt = self._Kd[rounds][i]
|
||||
result.append((self.Si[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
|
||||
result.append((self.Si[(t[(i + s1) % 4] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
|
||||
result.append((self.Si[(t[(i + s2) % 4] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
|
||||
result.append((self.Si[ t[(i + s3) % 4] & 0xFF] ^ tt ) & 0xFF)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class Counter(object):
|
||||
'''A counter object for the Counter (CTR) mode of operation.
|
||||
|
||||
To create a custom counter, you can usually just override the
|
||||
increment method.'''
|
||||
|
||||
def __init__(self, initial_value = 1):
|
||||
|
||||
# Convert the value into an array of bytes long
|
||||
self._counter = [ ((initial_value >> i) % 256) for i in xrange(128 - 8, -1, -8) ]
|
||||
|
||||
value = property(lambda s: s._counter)
|
||||
|
||||
def increment(self):
|
||||
'''Increment the counter (overflow rolls back to 0).'''
|
||||
|
||||
for i in xrange(len(self._counter) - 1, -1, -1):
|
||||
self._counter[i] += 1
|
||||
|
||||
if self._counter[i] < 256: break
|
||||
|
||||
# Carry the one
|
||||
self._counter[i] = 0
|
||||
|
||||
# Overflow
|
||||
else:
|
||||
self._counter = [ 0 ] * len(self._counter)
|
||||
|
||||
|
||||
class AESBlockModeOfOperation(object):
|
||||
'''Super-class for AES modes of operation that require blocks.'''
|
||||
def __init__(self, key):
|
||||
self._aes = AES(key)
|
||||
|
||||
def decrypt(self, ciphertext):
|
||||
raise Exception('not implemented')
|
||||
|
||||
def encrypt(self, plaintext):
|
||||
raise Exception('not implemented')
|
||||
|
||||
|
||||
class AESStreamModeOfOperation(AESBlockModeOfOperation):
|
||||
'''Super-class for AES modes of operation that are stream-ciphers.'''
|
||||
|
||||
class AESSegmentModeOfOperation(AESStreamModeOfOperation):
|
||||
'''Super-class for AES modes of operation that segment data.'''
|
||||
|
||||
segment_bytes = 16
|
||||
|
||||
|
||||
|
||||
class AESModeOfOperationECB(AESBlockModeOfOperation):
|
||||
'''AES Electronic Codebook Mode of Operation.
|
||||
|
||||
o Block-cipher, so data must be padded to 16 byte boundaries
|
||||
|
||||
Security Notes:
|
||||
o This mode is not recommended
|
||||
o Any two identical blocks produce identical encrypted values,
|
||||
exposing data patterns. (See the image of Tux on wikipedia)
|
||||
|
||||
Also see:
|
||||
o https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29
|
||||
o See NIST SP800-38A (http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf); section 6.1'''
|
||||
|
||||
|
||||
name = "Electronic Codebook (ECB)"
|
||||
|
||||
def encrypt(self, plaintext):
|
||||
if len(plaintext) != 16:
|
||||
raise ValueError('plaintext block must be 16 bytes')
|
||||
|
||||
plaintext = _string_to_bytes(plaintext)
|
||||
return _bytes_to_string(self._aes.encrypt(plaintext))
|
||||
|
||||
def decrypt(self, ciphertext):
|
||||
if len(ciphertext) != 16:
|
||||
raise ValueError('ciphertext block must be 16 bytes')
|
||||
|
||||
ciphertext = _string_to_bytes(ciphertext)
|
||||
return _bytes_to_string(self._aes.decrypt(ciphertext))
|
||||
|
||||
|
||||
|
||||
class AESModeOfOperationCBC(AESBlockModeOfOperation):
|
||||
'''AES Cipher-Block Chaining Mode of Operation.
|
||||
|
||||
o The Initialization Vector (IV)
|
||||
o Block-cipher, so data must be padded to 16 byte boundaries
|
||||
o An incorrect initialization vector will only cause the first
|
||||
block to be corrupt; all other blocks will be intact
|
||||
o A corrupt bit in the cipher text will cause a block to be
|
||||
corrupted, and the next block to be inverted, but all other
|
||||
blocks will be intact.
|
||||
|
||||
Security Notes:
|
||||
o This method (and CTR) ARE recommended.
|
||||
|
||||
Also see:
|
||||
o https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher-block_chaining_.28CBC.29
|
||||
o See NIST SP800-38A (http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf); section 6.2'''
|
||||
|
||||
|
||||
name = "Cipher-Block Chaining (CBC)"
|
||||
|
||||
def __init__(self, key, iv = None):
|
||||
if iv is None:
|
||||
self._last_cipherblock = [ 0 ] * 16
|
||||
elif len(iv) != 16:
|
||||
raise ValueError('initialization vector must be 16 bytes')
|
||||
else:
|
||||
self._last_cipherblock = _string_to_bytes(iv)
|
||||
|
||||
AESBlockModeOfOperation.__init__(self, key)
|
||||
|
||||
def encrypt(self, plaintext):
|
||||
if len(plaintext) != 16:
|
||||
raise ValueError('plaintext block must be 16 bytes')
|
||||
|
||||
plaintext = _string_to_bytes(plaintext)
|
||||
precipherblock = [ (p ^ l) for (p, l) in zip(plaintext, self._last_cipherblock) ]
|
||||
self._last_cipherblock = self._aes.encrypt(precipherblock)
|
||||
|
||||
return _bytes_to_string(self._last_cipherblock)
|
||||
|
||||
def decrypt(self, ciphertext):
|
||||
if len(ciphertext) != 16:
|
||||
raise ValueError('ciphertext block must be 16 bytes')
|
||||
|
||||
cipherblock = _string_to_bytes(ciphertext)
|
||||
plaintext = [ (p ^ l) for (p, l) in zip(self._aes.decrypt(cipherblock), self._last_cipherblock) ]
|
||||
self._last_cipherblock = cipherblock
|
||||
|
||||
return _bytes_to_string(plaintext)
|
||||
|
||||
|
||||
|
||||
class AESModeOfOperationCFB(AESSegmentModeOfOperation):
|
||||
'''AES Cipher Feedback Mode of Operation.
|
||||
|
||||
o A stream-cipher, so input does not need to be padded to blocks,
|
||||
but does need to be padded to segment_size
|
||||
|
||||
Also see:
|
||||
o https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_feedback_.28CFB.29
|
||||
o See NIST SP800-38A (http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf); section 6.3'''
|
||||
|
||||
|
||||
name = "Cipher Feedback (CFB)"
|
||||
|
||||
def __init__(self, key, iv, segment_size = 1):
|
||||
if segment_size == 0: segment_size = 1
|
||||
|
||||
if iv is None:
|
||||
self._shift_register = [ 0 ] * 16
|
||||
elif len(iv) != 16:
|
||||
raise ValueError('initialization vector must be 16 bytes')
|
||||
else:
|
||||
self._shift_register = _string_to_bytes(iv)
|
||||
|
||||
self._segment_bytes = segment_size
|
||||
|
||||
AESBlockModeOfOperation.__init__(self, key)
|
||||
|
||||
segment_bytes = property(lambda s: s._segment_bytes)
|
||||
|
||||
def encrypt(self, plaintext):
|
||||
if len(plaintext) % self._segment_bytes != 0:
|
||||
raise ValueError('plaintext block must be a multiple of segment_size')
|
||||
|
||||
plaintext = _string_to_bytes(plaintext)
|
||||
|
||||
# Break block into segments
|
||||
encrypted = [ ]
|
||||
for i in xrange(0, len(plaintext), self._segment_bytes):
|
||||
plaintext_segment = plaintext[i: i + self._segment_bytes]
|
||||
xor_segment = self._aes.encrypt(self._shift_register)[:len(plaintext_segment)]
|
||||
cipher_segment = [ (p ^ x) for (p, x) in zip(plaintext_segment, xor_segment) ]
|
||||
|
||||
# Shift the top bits out and the ciphertext in
|
||||
self._shift_register = _concat_list(self._shift_register[len(cipher_segment):], cipher_segment)
|
||||
|
||||
encrypted.extend(cipher_segment)
|
||||
|
||||
return _bytes_to_string(encrypted)
|
||||
|
||||
def decrypt(self, ciphertext):
|
||||
if len(ciphertext) % self._segment_bytes != 0:
|
||||
raise ValueError('ciphertext block must be a multiple of segment_size')
|
||||
|
||||
ciphertext = _string_to_bytes(ciphertext)
|
||||
|
||||
# Break block into segments
|
||||
decrypted = [ ]
|
||||
for i in xrange(0, len(ciphertext), self._segment_bytes):
|
||||
cipher_segment = ciphertext[i: i + self._segment_bytes]
|
||||
xor_segment = self._aes.encrypt(self._shift_register)[:len(cipher_segment)]
|
||||
plaintext_segment = [ (p ^ x) for (p, x) in zip(cipher_segment, xor_segment) ]
|
||||
|
||||
# Shift the top bits out and the ciphertext in
|
||||
self._shift_register = _concat_list(self._shift_register[len(cipher_segment):], cipher_segment)
|
||||
|
||||
decrypted.extend(plaintext_segment)
|
||||
|
||||
return _bytes_to_string(decrypted)
|
||||
|
||||
|
||||
|
||||
class AESModeOfOperationOFB(AESStreamModeOfOperation):
|
||||
'''AES Output Feedback Mode of Operation.
|
||||
|
||||
o A stream-cipher, so input does not need to be padded to blocks,
|
||||
allowing arbitrary length data.
|
||||
o A bit twiddled in the cipher text, twiddles the same bit in the
|
||||
same bit in the plain text, which can be useful for error
|
||||
correction techniques.
|
||||
|
||||
Also see:
|
||||
o https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Output_feedback_.28OFB.29
|
||||
o See NIST SP800-38A (http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf); section 6.4'''
|
||||
|
||||
|
||||
name = "Output Feedback (OFB)"
|
||||
|
||||
def __init__(self, key, iv = None):
|
||||
if iv is None:
|
||||
self._last_precipherblock = [ 0 ] * 16
|
||||
elif len(iv) != 16:
|
||||
raise ValueError('initialization vector must be 16 bytes')
|
||||
else:
|
||||
self._last_precipherblock = _string_to_bytes(iv)
|
||||
|
||||
self._remaining_block = [ ]
|
||||
|
||||
AESBlockModeOfOperation.__init__(self, key)
|
||||
|
||||
def encrypt(self, plaintext):
|
||||
encrypted = [ ]
|
||||
for p in _string_to_bytes(plaintext):
|
||||
if len(self._remaining_block) == 0:
|
||||
self._remaining_block = self._aes.encrypt(self._last_precipherblock)
|
||||
self._last_precipherblock = [ ]
|
||||
precipherbyte = self._remaining_block.pop(0)
|
||||
self._last_precipherblock.append(precipherbyte)
|
||||
cipherbyte = p ^ precipherbyte
|
||||
encrypted.append(cipherbyte)
|
||||
|
||||
return _bytes_to_string(encrypted)
|
||||
|
||||
def decrypt(self, ciphertext):
|
||||
# AES-OFB is symetric
|
||||
return self.encrypt(ciphertext)
|
||||
|
||||
|
||||
|
||||
class AESModeOfOperationCTR(AESStreamModeOfOperation):
|
||||
'''AES Counter Mode of Operation.
|
||||
|
||||
o A stream-cipher, so input does not need to be padded to blocks,
|
||||
allowing arbitrary length data.
|
||||
o The counter must be the same size as the key size (ie. len(key))
|
||||
o Each block independant of the other, so a corrupt byte will not
|
||||
damage future blocks.
|
||||
o Each block has a uniue counter value associated with it, which
|
||||
contributes to the encrypted value, so no data patterns are
|
||||
leaked.
|
||||
o Also known as: Counter Mode (CM), Integer Counter Mode (ICM) and
|
||||
Segmented Integer Counter (SIC
|
||||
|
||||
Security Notes:
|
||||
o This method (and CBC) ARE recommended.
|
||||
o Each message block is associated with a counter value which must be
|
||||
unique for ALL messages with the same key. Otherwise security may be
|
||||
compromised.
|
||||
|
||||
Also see:
|
||||
|
||||
o https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_.28CTR.29
|
||||
o See NIST SP800-38A (http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf); section 6.5
|
||||
and Appendix B for managing the initial counter'''
|
||||
|
||||
|
||||
name = "Counter (CTR)"
|
||||
|
||||
def __init__(self, key, counter = None):
|
||||
AESBlockModeOfOperation.__init__(self, key)
|
||||
|
||||
if counter is None:
|
||||
counter = Counter()
|
||||
|
||||
self._counter = counter
|
||||
self._remaining_counter = [ ]
|
||||
|
||||
def encrypt(self, plaintext):
|
||||
while len(self._remaining_counter) < len(plaintext):
|
||||
self._remaining_counter += self._aes.encrypt(self._counter.value)
|
||||
self._counter.increment()
|
||||
|
||||
plaintext = _string_to_bytes(plaintext)
|
||||
|
||||
encrypted = [ (p ^ c) for (p, c) in zip(plaintext, self._remaining_counter) ]
|
||||
self._remaining_counter = self._remaining_counter[len(encrypted):]
|
||||
|
||||
return _bytes_to_string(encrypted)
|
||||
|
||||
def decrypt(self, crypttext):
|
||||
# AES-CTR is symetric
|
||||
return self.encrypt(crypttext)
|
||||
|
||||
|
||||
# Simple lookup table for each mode
|
||||
AESModesOfOperation = dict(
|
||||
ctr = AESModeOfOperationCTR,
|
||||
cbc = AESModeOfOperationCBC,
|
||||
cfb = AESModeOfOperationCFB,
|
||||
ecb = AESModeOfOperationECB,
|
||||
ofb = AESModeOfOperationOFB,
|
||||
)
|
|
@ -1,227 +0,0 @@
|
|||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2014 Richard Moore
|
||||
#
|
||||
# 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 .aes import AESBlockModeOfOperation, AESSegmentModeOfOperation, AESStreamModeOfOperation
|
||||
from .util import append_PKCS7_padding, strip_PKCS7_padding, to_bufferable
|
||||
|
||||
|
||||
# First we inject three functions to each of the modes of operations
|
||||
#
|
||||
# _can_consume(size)
|
||||
# - Given a size, determine how many bytes could be consumed in
|
||||
# a single call to either the decrypt or encrypt method
|
||||
#
|
||||
# _final_encrypt(data, padding = PADDING_DEFAULT)
|
||||
# - call and return encrypt on this (last) chunk of data,
|
||||
# padding as necessary; this will always be at least 16
|
||||
# bytes unless the total incoming input was less than 16
|
||||
# bytes
|
||||
#
|
||||
# _final_decrypt(data, padding = PADDING_DEFAULT)
|
||||
# - same as _final_encrypt except for decrypt, for
|
||||
# stripping off padding
|
||||
#
|
||||
|
||||
PADDING_NONE = 'none'
|
||||
PADDING_DEFAULT = 'default'
|
||||
|
||||
# @TODO: Ciphertext stealing and explicit PKCS#7
|
||||
# PADDING_CIPHERTEXT_STEALING
|
||||
# PADDING_PKCS7
|
||||
|
||||
# ECB and CBC are block-only ciphers
|
||||
|
||||
def _block_can_consume(self, size):
|
||||
if size >= 16: return 16
|
||||
return 0
|
||||
|
||||
# After padding, we may have more than one block
|
||||
def _block_final_encrypt(self, data, padding = PADDING_DEFAULT):
|
||||
if padding == PADDING_DEFAULT:
|
||||
data = append_PKCS7_padding(data)
|
||||
|
||||
elif padding == PADDING_NONE:
|
||||
if len(data) != 16:
|
||||
raise Exception('invalid data length for final block')
|
||||
else:
|
||||
raise Exception('invalid padding option')
|
||||
|
||||
if len(data) == 32:
|
||||
return self.encrypt(data[:16]) + self.encrypt(data[16:])
|
||||
|
||||
return self.encrypt(data)
|
||||
|
||||
|
||||
def _block_final_decrypt(self, data, padding = PADDING_DEFAULT):
|
||||
if padding == PADDING_DEFAULT:
|
||||
return strip_PKCS7_padding(self.decrypt(data))
|
||||
|
||||
if padding == PADDING_NONE:
|
||||
if len(data) != 16:
|
||||
raise Exception('invalid data length for final block')
|
||||
return self.decrypt(data)
|
||||
|
||||
raise Exception('invalid padding option')
|
||||
|
||||
AESBlockModeOfOperation._can_consume = _block_can_consume
|
||||
AESBlockModeOfOperation._final_encrypt = _block_final_encrypt
|
||||
AESBlockModeOfOperation._final_decrypt = _block_final_decrypt
|
||||
|
||||
|
||||
|
||||
# CFB is a segment cipher
|
||||
|
||||
def _segment_can_consume(self, size):
|
||||
return self.segment_bytes * int(size // self.segment_bytes)
|
||||
|
||||
# CFB can handle a non-segment-sized block at the end using the remaining cipherblock
|
||||
def _segment_final_encrypt(self, data, padding = PADDING_DEFAULT):
|
||||
if padding != PADDING_DEFAULT:
|
||||
raise Exception('invalid padding option')
|
||||
|
||||
faux_padding = (chr(0) * (self.segment_bytes - (len(data) % self.segment_bytes)))
|
||||
padded = data + to_bufferable(faux_padding)
|
||||
return self.encrypt(padded)[:len(data)]
|
||||
|
||||
# CFB can handle a non-segment-sized block at the end using the remaining cipherblock
|
||||
def _segment_final_decrypt(self, data, padding = PADDING_DEFAULT):
|
||||
if padding != PADDING_DEFAULT:
|
||||
raise Exception('invalid padding option')
|
||||
|
||||
faux_padding = (chr(0) * (self.segment_bytes - (len(data) % self.segment_bytes)))
|
||||
padded = data + to_bufferable(faux_padding)
|
||||
return self.decrypt(padded)[:len(data)]
|
||||
|
||||
AESSegmentModeOfOperation._can_consume = _segment_can_consume
|
||||
AESSegmentModeOfOperation._final_encrypt = _segment_final_encrypt
|
||||
AESSegmentModeOfOperation._final_decrypt = _segment_final_decrypt
|
||||
|
||||
|
||||
|
||||
# OFB and CTR are stream ciphers
|
||||
|
||||
def _stream_can_consume(self, size):
|
||||
return size
|
||||
|
||||
def _stream_final_encrypt(self, data, padding = PADDING_DEFAULT):
|
||||
if padding not in [PADDING_NONE, PADDING_DEFAULT]:
|
||||
raise Exception('invalid padding option')
|
||||
|
||||
return self.encrypt(data)
|
||||
|
||||
def _stream_final_decrypt(self, data, padding = PADDING_DEFAULT):
|
||||
if padding not in [PADDING_NONE, PADDING_DEFAULT]:
|
||||
raise Exception('invalid padding option')
|
||||
|
||||
return self.decrypt(data)
|
||||
|
||||
AESStreamModeOfOperation._can_consume = _stream_can_consume
|
||||
AESStreamModeOfOperation._final_encrypt = _stream_final_encrypt
|
||||
AESStreamModeOfOperation._final_decrypt = _stream_final_decrypt
|
||||
|
||||
|
||||
|
||||
class BlockFeeder(object):
|
||||
'''The super-class for objects to handle chunking a stream of bytes
|
||||
into the appropriate block size for the underlying mode of operation
|
||||
and applying (or stripping) padding, as necessary.'''
|
||||
|
||||
def __init__(self, mode, feed, final, padding = PADDING_DEFAULT):
|
||||
self._mode = mode
|
||||
self._feed = feed
|
||||
self._final = final
|
||||
self._buffer = to_bufferable("")
|
||||
self._padding = padding
|
||||
|
||||
def feed(self, data = None):
|
||||
'''Provide bytes to encrypt (or decrypt), returning any bytes
|
||||
possible from this or any previous calls to feed.
|
||||
|
||||
Call with None or an empty string to flush the mode of
|
||||
operation and return any final bytes; no further calls to
|
||||
feed may be made.'''
|
||||
|
||||
if self._buffer is None:
|
||||
raise ValueError('already finished feeder')
|
||||
|
||||
# Finalize; process the spare bytes we were keeping
|
||||
if data is None:
|
||||
result = self._final(self._buffer, self._padding)
|
||||
self._buffer = None
|
||||
return result
|
||||
|
||||
self._buffer += to_bufferable(data)
|
||||
|
||||
# We keep 16 bytes around so we can determine padding
|
||||
result = to_bufferable('')
|
||||
while len(self._buffer) > 16:
|
||||
can_consume = self._mode._can_consume(len(self._buffer) - 16)
|
||||
if can_consume == 0: break
|
||||
result += self._feed(self._buffer[:can_consume])
|
||||
self._buffer = self._buffer[can_consume:]
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class Encrypter(BlockFeeder):
|
||||
'Accepts bytes of plaintext and returns encrypted ciphertext.'
|
||||
|
||||
def __init__(self, mode, padding = PADDING_DEFAULT):
|
||||
BlockFeeder.__init__(self, mode, mode.encrypt, mode._final_encrypt, padding)
|
||||
|
||||
|
||||
class Decrypter(BlockFeeder):
|
||||
'Accepts bytes of ciphertext and returns decrypted plaintext.'
|
||||
|
||||
def __init__(self, mode, padding = PADDING_DEFAULT):
|
||||
BlockFeeder.__init__(self, mode, mode.decrypt, mode._final_decrypt, padding)
|
||||
|
||||
|
||||
# 8kb blocks
|
||||
BLOCK_SIZE = (1 << 13)
|
||||
|
||||
def _feed_stream(feeder, in_stream, out_stream, block_size = BLOCK_SIZE):
|
||||
'Uses feeder to read and convert from in_stream and write to out_stream.'
|
||||
|
||||
while True:
|
||||
chunk = in_stream.read(block_size)
|
||||
if not chunk:
|
||||
break
|
||||
converted = feeder.feed(chunk)
|
||||
out_stream.write(converted)
|
||||
converted = feeder.feed()
|
||||
out_stream.write(converted)
|
||||
|
||||
|
||||
def encrypt_stream(mode, in_stream, out_stream, block_size = BLOCK_SIZE, padding = PADDING_DEFAULT):
|
||||
'Encrypts a stream of bytes from in_stream to out_stream using mode.'
|
||||
|
||||
encrypter = Encrypter(mode, padding = padding)
|
||||
_feed_stream(encrypter, in_stream, out_stream, block_size)
|
||||
|
||||
|
||||
def decrypt_stream(mode, in_stream, out_stream, block_size = BLOCK_SIZE, padding = PADDING_DEFAULT):
|
||||
'Decrypts a stream of bytes from in_stream to out_stream using mode.'
|
||||
|
||||
decrypter = Decrypter(mode, padding = padding)
|
||||
_feed_stream(decrypter, in_stream, out_stream, block_size)
|
|
@ -1,60 +0,0 @@
|
|||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2014 Richard Moore
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Why to_bufferable?
|
||||
# Python 3 is very different from Python 2.x when it comes to strings of text
|
||||
# and strings of bytes; in Python 3, strings of bytes do not exist, instead to
|
||||
# represent arbitrary binary data, we must use the "bytes" object. This method
|
||||
# ensures the object behaves as we need it to.
|
||||
|
||||
def to_bufferable(binary):
|
||||
return binary
|
||||
|
||||
def _get_byte(c):
|
||||
return ord(c)
|
||||
|
||||
try:
|
||||
xrange
|
||||
except:
|
||||
|
||||
def to_bufferable(binary):
|
||||
if isinstance(binary, bytes):
|
||||
return binary
|
||||
return bytes(ord(b) for b in binary)
|
||||
|
||||
def _get_byte(c):
|
||||
return c
|
||||
|
||||
def append_PKCS7_padding(data):
|
||||
pad = 16 - (len(data) % 16)
|
||||
return data + to_bufferable(chr(pad) * pad)
|
||||
|
||||
def strip_PKCS7_padding(data):
|
||||
if len(data) % 16 != 0:
|
||||
raise ValueError("invalid length")
|
||||
|
||||
pad = _get_byte(data[-1])
|
||||
|
||||
if pad > 16:
|
||||
raise ValueError("invalid padding byte")
|
||||
|
||||
return data[:-pad]
|
Loading…
Reference in a new issue