aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2019-04-21 10:36:03 -0400
committerJack Lloyd <[email protected]>2019-04-21 10:36:03 -0400
commite37bd06ea487a4d7b59b2e3f7e21fb955651daf9 (patch)
treefa674ed6d4b256f80c08cd0b52846bbe67a2dd1b /src
parent14cf876e4f245829b1ca1b361ff65df16bc05ca3 (diff)
Add raw block cipher interface for Python
Diffstat (limited to 'src')
-rwxr-xr-xsrc/python/botan2.py66
-rw-r--r--src/scripts/test_python.py16
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')