diff options
author | Jack Lloyd <[email protected]> | 2019-04-21 10:36:03 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2019-04-21 10:36:03 -0400 |
commit | e37bd06ea487a4d7b59b2e3f7e21fb955651daf9 (patch) | |
tree | fa674ed6d4b256f80c08cd0b52846bbe67a2dd1b /src | |
parent | 14cf876e4f245829b1ca1b361ff65df16bc05ca3 (diff) |
Add raw block cipher interface for Python
Diffstat (limited to 'src')
-rwxr-xr-x | src/python/botan2.py | 66 | ||||
-rw-r--r-- | src/scripts/test_python.py | 16 |
2 files changed, 81 insertions, 1 deletions
diff --git a/src/python/botan2.py b/src/python/botan2.py index f2dc3bd52..311b00871 100755 --- a/src/python/botan2.py +++ b/src/python/botan2.py @@ -396,7 +396,7 @@ _DLL = _set_prototypes(_load_botan_dll(BOTAN_FFI_VERSION)) def _call_fn_returning_sz(fn): sz = c_size_t(0) fn(byref(sz)) - return sz.value + return int(sz.value) def _call_fn_returning_vec(guess, fn): @@ -498,6 +498,70 @@ class RandomNumberGenerator(object): return _ctype_bufout(out) # +# Block cipher +# +class BlockCipher(object): + def __init__(self, algo): + + if isinstance(algo, c_void_p): + self.__obj = algo + else: + flags = c_uint32(0) # always zero in this API version + self.__obj = c_void_p(0) + _DLL.botan_block_cipher_init(byref(self.__obj), _ctype_str(algo), flags) + + min_keylen = c_size_t(0) + max_keylen = c_size_t(0) + mod_keylen = c_size_t(0) + _DLL.botan_block_cipher_get_keyspec(self.__obj, byref(min_keylen), byref(max_keylen), byref(mod_keylen)) + + self.__min_keylen = min_keylen.value + self.__max_keylen = max_keylen.value + self.__mod_keylen = mod_keylen.value + + self.__block_size = _DLL.botan_block_cipher_block_size(self.__obj) + + def __del__(self): + _DLL.botan_block_cipher_destroy(self.__obj) + + def set_key(self, key): + _DLL.botan_block_cipher_set_key(self.__obj, key, len(key)) + + def encrypt(self, pt): + if len(pt) % self.block_size() != 0: + raise Exception("Invalid input must be multiple of block size") + + blocks = c_size_t(len(pt) // self.block_size()) + output = create_string_buffer(len(pt)) + _DLL.botan_block_cipher_encrypt_blocks(self.__obj, pt, output, blocks) + return output + + def decrypt(self, ct): + if len(ct) % self.block_size() != 0: + raise Exception("Invalid input must be multiple of block size") + + blocks = c_size_t(len(ct) // self.block_size()) + output = create_string_buffer(len(ct)) + _DLL.botan_block_cipher_decrypt_blocks(self.__obj, ct, output, blocks) + return output + + def algo_name(self): + return _call_fn_returning_str(32, lambda b, bl: _DLL.botan_block_cipher_name(self.__obj, b, bl)) + + def clear(self): + _DLL.botan_block_cipher_clear(self.__obj) + + def block_size(self): + return self.__block_size + + def minimum_keylength(self): + return self.__min_keylen + + def maximum_keylength(self): + return self.__max_keylen + + +# # Hash function # class HashFunction(object): diff --git a/src/scripts/test_python.py b/src/scripts/test_python.py index 307d74269..94da4dc24 100644 --- a/src/scripts/test_python.py +++ b/src/scripts/test_python.py @@ -25,6 +25,22 @@ class BotanPythonTests(unittest.TestCase): self.assertEqual(botan2.version_major(), 2) self.assertTrue(botan2.version_minor() >= 8) + def test_block_cipher(self): + aes = botan2.BlockCipher("AES-128") + self.assertEqual(aes.algo_name(), "AES-128") + self.assertEqual(aes.block_size(), 16) + self.assertEqual(aes.minimum_keylength(), 16) + self.assertEqual(aes.maximum_keylength(), 16) + + aes.set_key(hex_decode("000102030405060708090a0b0c0d0e0f")) + ct = aes.encrypt(hex_decode("00112233445566778899aabbccddeeff")) + + self.assertEqual(hex_encode(ct), "69c4e0d86a7b0430d8cdb78070b4c55a") + + pt = aes.decrypt(ct) + + self.assertEqual(hex_encode(pt), "00112233445566778899aabbccddeeff") + def test_kdf(self): secret = hex_decode('6FD4C3C0F38E5C7A6F83E99CD9BD') |