summaryrefslogtreecommitdiffstats
path: root/src/lib/tlslite/utils/rijndael.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/tlslite/utils/rijndael.py')
-rwxr-xr-xsrc/lib/tlslite/utils/rijndael.py392
1 files changed, 0 insertions, 392 deletions
diff --git a/src/lib/tlslite/utils/rijndael.py b/src/lib/tlslite/utils/rijndael.py
deleted file mode 100755
index cb2f54734..000000000
--- a/src/lib/tlslite/utils/rijndael.py
+++ /dev/null
@@ -1,392 +0,0 @@
-"""
-A pure python (slow) implementation of rijndael with a decent interface
-
-To include -
-
-from rijndael import rijndael
-
-To do a key setup -
-
-r = rijndael(key, block_size = 16)
-
-key must be a string of length 16, 24, or 32
-blocksize must be 16, 24, or 32. Default is 16
-
-To use -
-
-ciphertext = r.encrypt(plaintext)
-plaintext = r.decrypt(ciphertext)
-
-If any strings are of the wrong length a ValueError is thrown
-"""
-
-# ported from the Java reference code by Bram Cohen, bram@gawth.com, April 2001
-# this code is public domain, unless someone makes
-# an intellectual property claim against the reference
-# code, in which case it can be made public domain by
-# deleting all the comments and renaming all the variables
-
-import copy
-import string
-
-
-
-#-----------------------
-#TREV - ADDED BECAUSE THERE'S WARNINGS ABOUT INT OVERFLOW BEHAVIOR CHANGING IN
-#2.4.....
-import os
-if os.name != "java":
- import exceptions
- if hasattr(exceptions, "FutureWarning"):
- import warnings
- warnings.filterwarnings("ignore", category=FutureWarning, append=1)
-#-----------------------
-
-
-
-shifts = [[[0, 0], [1, 3], [2, 2], [3, 1]],
- [[0, 0], [1, 5], [2, 4], [3, 3]],
- [[0, 0], [1, 7], [3, 5], [4, 4]]]
-
-# [keysize][block_size]
-num_rounds = {16: {16: 10, 24: 12, 32: 14}, 24: {16: 12, 24: 12, 32: 14}, 32: {16: 14, 24: 14, 32: 14}}
-
-A = [[1, 1, 1, 1, 1, 0, 0, 0],
- [0, 1, 1, 1, 1, 1, 0, 0],
- [0, 0, 1, 1, 1, 1, 1, 0],
- [0, 0, 0, 1, 1, 1, 1, 1],
- [1, 0, 0, 0, 1, 1, 1, 1],
- [1, 1, 0, 0, 0, 1, 1, 1],
- [1, 1, 1, 0, 0, 0, 1, 1],
- [1, 1, 1, 1, 0, 0, 0, 1]]
-
-# produce log and alog tables, needed for multiplying in the
-# field GF(2^m) (generator = 3)
-alog = [1]
-for i in xrange(255):
- j = (alog[-1] << 1) ^ alog[-1]
- if j & 0x100 != 0:
- j ^= 0x11B
- alog.append(j)
-
-log = [0] * 256
-for i in xrange(1, 255):
- log[alog[i]] = i
-
-# multiply two elements of GF(2^m)
-def mul(a, b):
- if a == 0 or b == 0:
- return 0
- return alog[(log[a & 0xFF] + log[b & 0xFF]) % 255]
-
-# substitution box based on F^{-1}(x)
-box = [[0] * 8 for i in xrange(256)]
-box[1][7] = 1
-for i in xrange(2, 256):
- j = alog[255 - log[i]]
- for t in xrange(8):
- box[i][t] = (j >> (7 - t)) & 0x01
-
-B = [0, 1, 1, 0, 0, 0, 1, 1]
-
-# affine transform: box[i] <- B + A*box[i]
-cox = [[0] * 8 for i in xrange(256)]
-for i in xrange(256):
- for t in xrange(8):
- cox[i][t] = B[t]
- for j in xrange(8):
- cox[i][t] ^= A[t][j] * box[i][j]
-
-# S-boxes and inverse S-boxes
-S = [0] * 256
-Si = [0] * 256
-for i in xrange(256):
- S[i] = cox[i][0] << 7
- for t in xrange(1, 8):
- S[i] ^= cox[i][t] << (7-t)
- Si[S[i] & 0xFF] = i
-
-# T-boxes
-G = [[2, 1, 1, 3],
- [3, 2, 1, 1],
- [1, 3, 2, 1],
- [1, 1, 3, 2]]
-
-AA = [[0] * 8 for i in xrange(4)]
-
-for i in xrange(4):
- for j in xrange(4):
- AA[i][j] = G[i][j]
- AA[i][i+4] = 1
-
-for i in xrange(4):
- pivot = AA[i][i]
- if pivot == 0:
- t = i + 1
- while AA[t][i] == 0 and t < 4:
- t += 1
- assert t != 4, 'G matrix must be invertible'
- for j in xrange(8):
- AA[i][j], AA[t][j] = AA[t][j], AA[i][j]
- pivot = AA[i][i]
- for j in xrange(8):
- if AA[i][j] != 0:
- AA[i][j] = alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255]
- for t in xrange(4):
- if i != t:
- for j in xrange(i+1, 8):
- AA[t][j] ^= mul(AA[i][j], AA[t][i])
- AA[t][i] = 0
-
-iG = [[0] * 4 for i in xrange(4)]
-
-for i in xrange(4):
- for j in xrange(4):
- iG[i][j] = AA[i][j + 4]
-
-def mul4(a, bs):
- if a == 0:
- return 0
- r = 0
- for b in bs:
- r <<= 8
- if b != 0:
- r = r | mul(a, b)
- return r
-
-T1 = []
-T2 = []
-T3 = []
-T4 = []
-T5 = []
-T6 = []
-T7 = []
-T8 = []
-U1 = []
-U2 = []
-U3 = []
-U4 = []
-
-for t in xrange(256):
- s = S[t]
- T1.append(mul4(s, G[0]))
- T2.append(mul4(s, G[1]))
- T3.append(mul4(s, G[2]))
- T4.append(mul4(s, G[3]))
-
- s = Si[t]
- T5.append(mul4(s, iG[0]))
- T6.append(mul4(s, iG[1]))
- T7.append(mul4(s, iG[2]))
- T8.append(mul4(s, iG[3]))
-
- U1.append(mul4(t, iG[0]))
- U2.append(mul4(t, iG[1]))
- U3.append(mul4(t, iG[2]))
- U4.append(mul4(t, iG[3]))
-
-# round constants
-rcon = [1]
-r = 1
-for t in xrange(1, 30):
- r = mul(2, r)
- rcon.append(r)
-
-del A
-del AA
-del pivot
-del B
-del G
-del box
-del log
-del alog
-del i
-del j
-del r
-del s
-del t
-del mul
-del mul4
-del cox
-del iG
-
-class rijndael:
- def __init__(self, key, block_size = 16):
- if block_size != 16 and block_size != 24 and block_size != 32:
- raise ValueError('Invalid block size: ' + str(block_size))
- if len(key) != 16 and len(key) != 24 and len(key) != 32:
- raise ValueError('Invalid key size: ' + str(len(key)))
- self.block_size = block_size
-
- ROUNDS = num_rounds[len(key)][block_size]
- BC = block_size / 4
- # encryption round keys
- Ke = [[0] * BC for i in xrange(ROUNDS + 1)]
- # decryption round keys
- Kd = [[0] * BC for i in xrange(ROUNDS + 1)]
- ROUND_KEY_COUNT = (ROUNDS + 1) * BC
- KC = len(key) / 4
-
- # copy user material bytes into temporary ints
- tk = []
- for i in xrange(0, KC):
- tk.append((ord(key[i * 4]) << 24) | (ord(key[i * 4 + 1]) << 16) |
- (ord(key[i * 4 + 2]) << 8) | ord(key[i * 4 + 3]))
-
- # copy values into round key arrays
- t = 0
- j = 0
- while j < KC and t < ROUND_KEY_COUNT:
- Ke[t / BC][t % BC] = tk[j]
- Kd[ROUNDS - (t / BC)][t % BC] = tk[j]
- j += 1
- t += 1
- tt = 0
- rconpointer = 0
- while t < ROUND_KEY_COUNT:
- # extrapolate using phi (the round key evolution function)
- tt = tk[KC - 1]
- tk[0] ^= (S[(tt >> 16) & 0xFF] & 0xFF) << 24 ^ \
- (S[(tt >> 8) & 0xFF] & 0xFF) << 16 ^ \
- (S[ tt & 0xFF] & 0xFF) << 8 ^ \
- (S[(tt >> 24) & 0xFF] & 0xFF) ^ \
- (rcon[rconpointer] & 0xFF) << 24
- rconpointer += 1
- if KC != 8:
- for i in xrange(1, KC):
- tk[i] ^= tk[i-1]
- else:
- for i in xrange(1, KC / 2):
- tk[i] ^= tk[i-1]
- tt = tk[KC / 2 - 1]
- tk[KC / 2] ^= (S[ tt & 0xFF] & 0xFF) ^ \
- (S[(tt >> 8) & 0xFF] & 0xFF) << 8 ^ \
- (S[(tt >> 16) & 0xFF] & 0xFF) << 16 ^ \
- (S[(tt >> 24) & 0xFF] & 0xFF) << 24
- for i in xrange(KC / 2 + 1, KC):
- tk[i] ^= tk[i-1]
- # copy values into round key arrays
- j = 0
- while j < KC and t < ROUND_KEY_COUNT:
- Ke[t / BC][t % BC] = tk[j]
- Kd[ROUNDS - (t / BC)][t % BC] = tk[j]
- j += 1
- t += 1
- # inverse MixColumn where needed
- for r in xrange(1, ROUNDS):
- for j in xrange(BC):
- tt = Kd[r][j]
- Kd[r][j] = U1[(tt >> 24) & 0xFF] ^ \
- U2[(tt >> 16) & 0xFF] ^ \
- U3[(tt >> 8) & 0xFF] ^ \
- U4[ tt & 0xFF]
- self.Ke = Ke
- self.Kd = Kd
-
- def encrypt(self, plaintext):
- if len(plaintext) != self.block_size:
- raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(plaintext)))
- Ke = self.Ke
-
- BC = self.block_size / 4
- ROUNDS = len(Ke) - 1
- if BC == 4:
- SC = 0
- elif BC == 6:
- SC = 1
- else:
- SC = 2
- s1 = shifts[SC][1][0]
- s2 = shifts[SC][2][0]
- s3 = shifts[SC][3][0]
- a = [0] * BC
- # temporary work array
- t = []
- # plaintext to ints + key
- for i in xrange(BC):
- t.append((ord(plaintext[i * 4 ]) << 24 |
- ord(plaintext[i * 4 + 1]) << 16 |
- ord(plaintext[i * 4 + 2]) << 8 |
- ord(plaintext[i * 4 + 3]) ) ^ Ke[0][i])
- # apply round transforms
- for r in xrange(1, ROUNDS):
- for i in xrange(BC):
- a[i] = (T1[(t[ i ] >> 24) & 0xFF] ^
- T2[(t[(i + s1) % BC] >> 16) & 0xFF] ^
- T3[(t[(i + s2) % BC] >> 8) & 0xFF] ^
- T4[ t[(i + s3) % BC] & 0xFF] ) ^ Ke[r][i]
- t = copy.copy(a)
- # last round is special
- result = []
- for i in xrange(BC):
- tt = Ke[ROUNDS][i]
- result.append((S[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
- result.append((S[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
- result.append((S[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
- result.append((S[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF)
- return string.join(map(chr, result), '')
-
- def decrypt(self, ciphertext):
- if len(ciphertext) != self.block_size:
- raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(plaintext)))
- Kd = self.Kd
-
- BC = self.block_size / 4
- ROUNDS = len(Kd) - 1
- if BC == 4:
- SC = 0
- elif BC == 6:
- SC = 1
- else:
- SC = 2
- s1 = shifts[SC][1][1]
- s2 = shifts[SC][2][1]
- s3 = shifts[SC][3][1]
- a = [0] * BC
- # temporary work array
- t = [0] * BC
- # ciphertext to ints + key
- for i in xrange(BC):
- t[i] = (ord(ciphertext[i * 4 ]) << 24 |
- ord(ciphertext[i * 4 + 1]) << 16 |
- ord(ciphertext[i * 4 + 2]) << 8 |
- ord(ciphertext[i * 4 + 3]) ) ^ Kd[0][i]
- # apply round transforms
- for r in xrange(1, ROUNDS):
- for i in xrange(BC):
- a[i] = (T5[(t[ i ] >> 24) & 0xFF] ^
- T6[(t[(i + s1) % BC] >> 16) & 0xFF] ^
- T7[(t[(i + s2) % BC] >> 8) & 0xFF] ^
- T8[ t[(i + s3) % BC] & 0xFF] ) ^ Kd[r][i]
- t = copy.copy(a)
- # last round is special
- result = []
- for i in xrange(BC):
- tt = Kd[ROUNDS][i]
- result.append((Si[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
- result.append((Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
- result.append((Si[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
- result.append((Si[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF)
- return string.join(map(chr, result), '')
-
-def encrypt(key, block):
- return rijndael(key, len(block)).encrypt(block)
-
-def decrypt(key, block):
- return rijndael(key, len(block)).decrypt(block)
-
-def test():
- def t(kl, bl):
- b = 'b' * bl
- r = rijndael('a' * kl, bl)
- assert r.decrypt(r.encrypt(b)) == b
- t(16, 16)
- t(16, 24)
- t(16, 32)
- t(24, 16)
- t(24, 24)
- t(24, 32)
- t(32, 16)
- t(32, 24)
- t(32, 32)
-