From e10de00d6b95e080e63c268698384076d6bc518c Mon Sep 17 00:00:00 2001 From: John Paraskevopoulos Date: Sun, 11 Oct 2015 00:22:27 +0300 Subject: [PATCH 1/5] pep8 fixes --- triplesec/crypto.py | 4 ++-- triplesec/utils.py | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/triplesec/crypto.py b/triplesec/crypto.py index 08b1385..0d89a82 100644 --- a/triplesec/crypto.py +++ b/triplesec/crypto.py @@ -40,7 +40,7 @@ def encrypt(cls, data, key): ctr = Counter.new(cls.block_size*8, initial_value=int(binascii.hexlify(iv), 16)) ciphertext = Crypto_AES.new(key, Crypto_AES.MODE_CTR, - counter=ctr).encrypt(data) + counter=ctr).encrypt(data) return iv + ciphertext @classmethod @@ -52,7 +52,7 @@ def decrypt(cls, data, key): ctr = Counter.new(cls.block_size*8, initial_value=int(binascii.hexlify(iv), 16)) return Crypto_AES.new(key, Crypto_AES.MODE_CTR, - counter=ctr).decrypt(data[cls.block_size:]) + counter=ctr).decrypt(data[cls.block_size:]) class Twofish: key_size = 32 diff --git a/triplesec/utils.py b/triplesec/utils.py index c214ac6..2ac2855 100644 --- a/triplesec/utils.py +++ b/triplesec/utils.py @@ -56,20 +56,25 @@ def _constant_time_compare(a, b): result = 0 for x, y in zip(six.iterbytes(a), six.iterbytes(b)): result |= x ^ y - return (result == 0) + return result == 0 class new_sha3_512: block_size = 72 digest_size = 64 + def __init__(self, string=b''): self._obj = hashlib.sha3_512() self._obj.update(string) + def digest(self): return self._obj.digest() + def hexdigest(self): return self._obj.hexdigest() + def update(self, string): return self._obj.update(string) + def copy(self): copy = new_sha3_512() copy._obj = self._obj.copy() From 4ea7b346c26bbd4691753fdf8a80585c32ab9a51 Mon Sep 17 00:00:00 2001 From: John Paraskevopoulos Date: Sun, 11 Oct 2015 00:23:25 +0300 Subject: [PATCH 2/5] Replace xrange with range xrange is range in python 3.x no real value for python 2.x (used only for args aka minor ranges) --- triplesec/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triplesec/utils.py b/triplesec/utils.py index 2ac2855..fb3057c 100644 --- a/triplesec/utils.py +++ b/triplesec/utils.py @@ -121,6 +121,6 @@ def win32_utf8_argv(): else: start = 0 return [argv[i].encode('utf-8') for i in - xrange(start, argc.value)] + range(start, argc.value)] except Exception: pass From b7672cab248442705b1c0b101449df0aba2c3c38 Mon Sep 17 00:00:00 2001 From: John Paraskevopoulos Date: Sun, 11 Oct 2015 00:35:13 +0300 Subject: [PATCH 3/5] refactored the key checking --- triplesec/crypto.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/triplesec/crypto.py b/triplesec/crypto.py index 0d89a82..ce119ec 100644 --- a/triplesec/crypto.py +++ b/triplesec/crypto.py @@ -27,14 +27,18 @@ sha3_512 ) +def validate_key_size(key, key_size, algorithm): + if len(key) != key_size: + raise TripleSecFailedAssertion(u"Wrong {algo} key size" + .format(algo=algorithm)) + class AES: key_size = 32 block_size = 16 @classmethod def encrypt(cls, data, key): - if len(key) != cls.key_size: - raise TripleSecFailedAssertion(u"Wrong AES key size") + validate_key_size(key, cls.key_size, "AES") iv = rndfile.read(cls.block_size) ctr = Counter.new(cls.block_size*8, initial_value=int(binascii.hexlify(iv), 16)) @@ -45,8 +49,7 @@ def encrypt(cls, data, key): @classmethod def decrypt(cls, data, key): - if len(key) != cls.key_size: - raise TripleSecFailedAssertion(u"Wrong AES key size") + validate_key_size(key, cls.key_size, "AES") iv = data[:cls.block_size] ctr = Counter.new(cls.block_size*8, initial_value=int(binascii.hexlify(iv), 16)) @@ -68,8 +71,7 @@ def _gen_keystream(cls, length, T, ctr): @classmethod def encrypt(cls, data, key): - if len(key) != cls.key_size: - raise TripleSecFailedAssertion(u"Wrong Twofish key size") + validate_key_size(key, cls.key_size, "Twofish") iv = rndfile.read(cls.block_size) ctr = Counter.new(cls.block_size*8, initial_value=int(binascii.hexlify(iv), 16)) @@ -80,8 +82,7 @@ def encrypt(cls, data, key): @classmethod def decrypt(cls, data, key): - if len(key) != cls.key_size: - raise TripleSecFailedAssertion(u"Wrong Twofish key size") + validate_key_size(key, cls.key_size, "Twofish") iv = data[:cls.block_size] ctr = Counter.new(cls.block_size*8, initial_value=int(binascii.hexlify(iv), 16)) @@ -95,8 +96,7 @@ class XSalsa20: @classmethod def encrypt(cls, data, key): - if len(key) != cls.key_size: - raise TripleSecFailedAssertion(u"Wrong XSalsa20 key size") + validate_key_size(key, cls.key_size, "XSalsa20") iv = rndfile.read(cls.iv_size) @@ -105,8 +105,7 @@ def encrypt(cls, data, key): @classmethod def decrypt(cls, data, key): - if len(key) != cls.key_size: - raise TripleSecFailedAssertion(u"Wrong XSalsa20 key size") + validate_key_size(key, cls.key_size, "XSalsa20") iv = data[:cls.iv_size] From d7f7022ce1f4353363e161ae77fbe7d858e7e3dc Mon Sep 17 00:00:00 2001 From: John Paraskevopoulos Date: Sun, 11 Oct 2015 00:55:44 +0300 Subject: [PATCH 4/5] refactoring for reusability --- triplesec/crypto.py | 55 ++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/triplesec/crypto.py b/triplesec/crypto.py index ce119ec..e758958 100644 --- a/triplesec/crypto.py +++ b/triplesec/crypto.py @@ -32,7 +32,30 @@ def validate_key_size(key, key_size, algorithm): raise TripleSecFailedAssertion(u"Wrong {algo} key size" .format(algo=algorithm)) -class AES: +class BlockCipher(object): + + @classmethod + def generate_counter(cls, block_size, iv): + ctr = Counter.new(block_size * 8, + initial_value=int(binascii.hexlify(iv), 16)) + return ctr + + @classmethod + def generate_encrypt_iv_counter(cls, block_size): + iv = rndfile.read(block_size) + ctr = cls.generate_counter(block_size, iv) + + return iv, ctr + + @classmethod + def generate_decrypt_counter(cls, data, block_size): + iv = data[:block_size] + ctr = cls.generate_counter(block_size, iv) + + return ctr + + +class AES(object): key_size = 32 block_size = 16 @@ -40,9 +63,7 @@ class AES: def encrypt(cls, data, key): validate_key_size(key, cls.key_size, "AES") - iv = rndfile.read(cls.block_size) - ctr = Counter.new(cls.block_size*8, initial_value=int(binascii.hexlify(iv), 16)) - + iv, ctr = BlockCipher.generate_encrypt_iv_counter(cls.block_size) ciphertext = Crypto_AES.new(key, Crypto_AES.MODE_CTR, counter=ctr).encrypt(data) return iv + ciphertext @@ -51,44 +72,42 @@ def encrypt(cls, data, key): def decrypt(cls, data, key): validate_key_size(key, cls.key_size, "AES") - iv = data[:cls.block_size] - ctr = Counter.new(cls.block_size*8, initial_value=int(binascii.hexlify(iv), 16)) + ctr = BlockCipher.generate_decrypt_counter(data, cls.block_size) return Crypto_AES.new(key, Crypto_AES.MODE_CTR, counter=ctr).decrypt(data[cls.block_size:]) -class Twofish: +class Twofish(object): key_size = 32 block_size = 16 @classmethod - def _gen_keystream(cls, length, T, ctr): + def _gen_keystream(cls, length, tfish, ctr): req_blocks = length // cls.block_size + 1 keystream = b'' for _ in range(req_blocks): - keystream += T.encrypt(ctr()) + keystream += tfish.encrypt(ctr()) return keystream[:length] @classmethod def encrypt(cls, data, key): validate_key_size(key, cls.key_size, "Twofish") - iv = rndfile.read(cls.block_size) - ctr = Counter.new(cls.block_size*8, initial_value=int(binascii.hexlify(iv), 16)) + iv, ctr = BlockCipher.generate_encrypt_iv_counter(cls.block_size) + tfish = twofish.Twofish(key) + ciphertext = strxor(data, cls._gen_keystream(len(data), tfish, ctr)) - T = twofish.Twofish(key) - ciphertext = strxor(data, cls._gen_keystream(len(data), T, ctr)) return iv + ciphertext @classmethod def decrypt(cls, data, key): validate_key_size(key, cls.key_size, "Twofish") - iv = data[:cls.block_size] - ctr = Counter.new(cls.block_size*8, initial_value=int(binascii.hexlify(iv), 16)) + ctr = BlockCipher.generate_decrypt_counter(data, cls.block_size) + tfish = twofish.Twofish(key) - T = twofish.Twofish(key) - return strxor(data[cls.block_size:], cls._gen_keystream(len(data[cls.block_size:]), T, ctr)) + return strxor(data[cls.block_size:], + cls._gen_keystream(len(data[cls.block_size:]), tfish, ctr)) class XSalsa20: key_size = 32 @@ -99,8 +118,8 @@ def encrypt(cls, data, key): validate_key_size(key, cls.key_size, "XSalsa20") iv = rndfile.read(cls.iv_size) - ciphertext = salsa20.XSalsa20_xor(data, iv, key) + return iv + ciphertext @classmethod From ef35a2d62089d86a9a6f4fe7b9592767dcf9335e Mon Sep 17 00:00:00 2001 From: John Paraskevopoulos Date: Sun, 11 Oct 2015 00:56:36 +0300 Subject: [PATCH 5/5] pep8-remove inline if, and new style class --- triplesec/utils.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/triplesec/utils.py b/triplesec/utils.py index fb3057c..dca13fa 100644 --- a/triplesec/utils.py +++ b/triplesec/utils.py @@ -52,13 +52,14 @@ class TripleSecFailedAssertion(TripleSecError): ### UTILITIES def _constant_time_compare(a, b): - if len(a) != len(b): return False + if len(a) != len(b): + return False result = 0 for x, y in zip(six.iterbytes(a), six.iterbytes(b)): result |= x ^ y return result == 0 -class new_sha3_512: +class new_sha3_512(object): block_size = 72 digest_size = 64