aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pypride.py42
-rwxr-xr-xtest-vectors.py37
2 files changed, 39 insertions, 40 deletions
diff --git a/pypride.py b/pypride.py
index 8bca5a0..9655d44 100644
--- a/pypride.py
+++ b/pypride.py
@@ -56,6 +56,8 @@ This implementation is fully based on the report PRIDE was presented in (https:/
Test vectors can be found in test-vectors.py and were taken from appendix J of that paper.
"""
+import binascii, sys
+
class Pride:
def __init__(self,key):
@@ -64,9 +66,9 @@ class Pride:
Input: the key as a 128-bit raw string"""
if len(key) != 16:
- raise ValueError, "Key must be a 128-bit raw string"
+ raise ValueError("Key must be a 128-bit raw string")
self.whitening_key = string2number(key[:8])
- self.roundkeys = [roundKey(key[8:], i) for i in xrange(0,21)]
+ self.roundkeys = [roundKey(key[8:], i) for i in range(0,21)]
def encrypt(self,block):
"""Encrypt 1 block (8 bytes)
@@ -80,7 +82,7 @@ class Pride:
state = pLayer_dec(state)
state = addRoundKey(state, self.whitening_key)
# 19 rounds R
- for i in xrange (1,20):
+ for i in range (1,20):
state = addRoundKey(state, self.roundkeys[i])
state = sBoxLayer(state)
state = lLayer(state)
@@ -108,7 +110,7 @@ class Pride:
state = sBoxLayer_dec(state)
state = addRoundKey(state, self.roundkeys[20])
# 19 rounds R
- for i in xrange(19,0,-1):
+ for i in range(19,0,-1):
state = lLayer_dec(state)
state = sBoxLayer_dec(state)
state = addRoundKey(state, self.roundkeys[i])
@@ -120,11 +122,11 @@ class Pride:
# 4 to 4-bit S-Box and its inverse
Sbox= [0x0,0x4,0x8,0xf,0x1,0x5,0xe,0x9,0x2,0x7,0xa,0xc,0xb,0xd,0x6,0x3]
-Sbox_inv = [Sbox.index(x) for x in xrange(16)]
+Sbox_inv = [Sbox.index(x) for x in range(16)]
# 64-bit permutation P and its inverse
PBox = [0, 16, 32, 48, 1, 17, 33, 49, 2, 18, 34, 50, 3, 19, 35, 51, 4, 20, 36, 52, 5, 21, 37, 53, 6, 22, 38, 54, 7, 23, 39, 55, 8, 24, 40, 56, 9, 25, 41, 57, 10, 26, 42, 58, 11, 27, 43, 59, 12, 28, 44, 60, 13, 29, 45, 61, 14, 30, 46, 62, 15, 31, 47, 63]
-PBox_inv = [PBox.index(x) for x in xrange(64)]
+PBox_inv = [PBox.index(x) for x in range(64)]
def swap(byte):
"""Swap byte nibbles"""
@@ -187,16 +189,9 @@ def roundKey(key, i):
the round number
Output: the round key as raw string"""
- return pLayer_dec(string2number(
- key[0]
- + chr((ord(key[1]) + 193 * i) % 256)
- + key[2]
- + chr((ord(key[3]) + 165 * i) % 256)
- + key[4]
- + chr((ord(key[5]) + 81 * i) % 256)
- + key[6]
- + chr((ord(key[7]) + 197 * i) % 256)
- ))
+ key = string_bytes(key)
+ key_parts = [key[0], (key[1] + 193 * i) % 256, key[2], (key[3] + 165 * i) % 256, key[4], (key[5] + 81 * i) % 256, key[6], (key[7] + 197 * i) % 256]
+ return pLayer_dec(sum([(1 << (8 * (7-i))) * k for i, k in enumerate(key_parts)]))
def addRoundKey(state,roundkey):
return state ^ roundkey
@@ -207,7 +202,7 @@ def sBoxLayer(state):
Input: 64-bit integer
Output: 64-bit integer"""
- return sum([Sbox[( state >> (i * 4)) & 0xf] << (i * 4) for i in xrange(16)])
+ return sum([Sbox[( state >> (i * 4)) & 0xf] << (i * 4) for i in range(16)])
def sBoxLayer_dec(state):
"""Inverse SBox function for decryption
@@ -215,7 +210,7 @@ def sBoxLayer_dec(state):
Input: 64-bit integer
Output: 64-bit integer"""
- return sum([Sbox_inv[( state >> (i * 4)) & 0xf] << (i * 4) for i in xrange(16)])
+ return sum([Sbox_inv[( state >> (i * 4)) & 0xf] << (i * 4) for i in range(16)])
def pLayer(state):
"""Permutation layer for encryption
@@ -223,7 +218,7 @@ def pLayer(state):
Input: 64-bit integer
Output: 64-bit integer"""
- return sum ([((state >> i) & 1) << PBox[i] for i in xrange(64)])
+ return sum ([((state >> i) & 1) << PBox[i] for i in range(64)])
def pLayer_dec(state):
"""Permutation layer for decryption
@@ -231,7 +226,7 @@ def pLayer_dec(state):
Input: 64-bit integer
Output: 64-bit integer"""
- return sum ([((state >> i) & 1) << PBox_inv[i] for i in xrange(64)])
+ return sum ([((state >> i) & 1) << PBox_inv[i] for i in range(64)])
def lLayer(state):
"""Perform the L layer:
@@ -271,7 +266,7 @@ def string2number(i):
Input: string (big-endian)
Output: long or integer
"""
- return int(i.encode('hex'), 16)
+ return int(binascii.hexlify(i), 16)
def number2string_N(i, N):
"""Convert a number to a string of fixed size
@@ -281,4 +276,7 @@ def number2string_N(i, N):
Output: string (big-endian)
"""
s = '%0*x' % (N*2, i)
- return s.decode('hex')
+ return binascii.unhexlify(s)
+
+def string_bytes(s):
+ return [ord(c) for c in s] if sys.version_info.major == 2 else s \ No newline at end of file
diff --git a/test-vectors.py b/test-vectors.py
index 55e6a26..a6bcae8 100755
--- a/test-vectors.py
+++ b/test-vectors.py
@@ -22,14 +22,15 @@
from pypride import Pride
import time
+import binascii
def test():
test_vectors = [
- {'key': "00000000000000000000000000000000", 'plaintext': "0000000000000000", 'ciphertext': "82b4109fcc70bd1f"},
- {'key': "00000000000000000000000000000000", 'plaintext': "ffffffffffffffff", 'ciphertext': "d70e60680a17b956"},
- {'key': "ffffffffffffffff0000000000000000", 'plaintext': "0000000000000000", 'ciphertext': "28f19f97f5e846a9"},
- {'key': "0000000000000000ffffffffffffffff", 'plaintext': "0000000000000000", 'ciphertext': "d123ebaf368fce62"},
- {'key': "0000000000000000fedcba9876543210", 'plaintext': "0123456789abcdef", 'ciphertext': "d1372929712d336e"}
+ {'key': '00000000000000000000000000000000', 'plaintext': '0000000000000000', 'ciphertext': '82b4109fcc70bd1f'},
+ {'key': '00000000000000000000000000000000', 'plaintext': 'ffffffffffffffff', 'ciphertext': 'd70e60680a17b956'},
+ {'key': 'ffffffffffffffff0000000000000000', 'plaintext': '0000000000000000', 'ciphertext': '28f19f97f5e846a9'},
+ {'key': '0000000000000000ffffffffffffffff', 'plaintext': '0000000000000000', 'ciphertext': 'd123ebaf368fce62'},
+ {'key': '0000000000000000fedcba9876543210', 'plaintext': '0123456789abcdef', 'ciphertext': 'd1372929712d336e'}
]
time_cipher = 0
@@ -38,37 +39,37 @@ def test():
all_passed = True
- for _ in xrange(100):
+ for _ in range(100):
for v_i, vector in enumerate(test_vectors):
- key = vector['key'].decode('hex')
+ key = binascii.unhexlify(vector['key'])
start = time.time()
cipher = Pride(key)
time_cipher += time.time() - start
- plaintext = vector['plaintext'].decode('hex')
+ plaintext = binascii.unhexlify(vector['plaintext'])
start = time.time()
encryption = cipher.encrypt(plaintext)
time_encrypt += time.time() - start
- ciphertext = vector['ciphertext'].decode('hex')
+ ciphertext = binascii.unhexlify(vector['ciphertext'])
start = time.time()
decryption = cipher.decrypt(ciphertext)
time_decrypt += time.time() - start
- if encryption != vector['ciphertext'].decode('hex'):
- print "Encryption for vector", v_i, "failed: was", encryption.encode('hex'), "; should have been", vector['ciphertext']
+ if encryption != binascii.unhexlify(vector['ciphertext']):
+ print('Encryption for vector ' + str(v_i) + ' failed: was ' + str(binascii.hexlify(encryption)) + '; should have been ' + vector['ciphertext'])
all_passed = False
- if decryption != vector['plaintext'].decode('hex'):
- print "Decryption for vector", v_i, "failed: was", decryption.encode('hex'), "; should have been", vector['plaintext']
+ if decryption != binascii.unhexlify(vector['plaintext']):
+ print('Decryption for vector ' + str(v_i) + ' failed: was ' + str(binascii.hexlify(decryption)) + '; should have been ' + vector['plaintext'])
all_passed = False
if all_passed:
- print "All tests passed."
+ print('All tests passed.')
- print "Generating round keys:", str(time_cipher) + "s"
- print "Encryption: ", str(time_encrypt) + "s"
- print "Decryption: ", str(time_decrypt) + "s"
+ print('Generating round keys: ' + str(time_cipher) + 's')
+ print('Encryption: ' + str(time_encrypt) + 's')
+ print('Decryption: ' + str(time_decrypt) + 's')
import profile
-profile.run('test()') \ No newline at end of file
+profile.run('test()')