Repository: randombit/botan
Pull request #3272 (2023-02-11 18:05:28)

Rename the Python module to match the major version
GH #3271


Patch:
diff --git a/doc/api_ref/python.rst b/doc/api_ref/python.rst
index e863b648b..0fd40bd08 100644
--- a/doc/api_ref/python.rst
+++ b/doc/api_ref/python.rst
@@ -6,15 +6,14 @@ Python Binding
 
 .. highlight:: python
 
-.. py:module:: botan
+.. py:module:: botan3
 
 The Python binding is based on the `ffi` module of botan and the
 `ctypes` module of the Python standard library.
 
-Starting in 2.8, the class names were renamed to match Python standard
-conventions. However aliases are defined which allow older code to
-continue to work; the older names are mentioned as "previously X".
-These aliases will be removed in a future major release.
+The versioning of the Python module follows the major versioning of
+the C++ library. So for Botan 2, the module is named ``botan2`` while
+for Botan 3 it is ``botan3``.
 
 Versioning
 ----------------------------------------
@@ -507,11 +506,11 @@ Format Preserving Encryption (FE1 scheme)
 
    .. py:method:: encrypt(msg, tweak)
 
-      The msg should be a botan2.MPI or an object which can be converted to one
+      The msg should be a botan3.MPI or an object which can be converted to one
 
    .. py:method:: decrypt(msg, tweak)
 
-      The msg should be a botan2.MPI or an object which can be converted to one
+      The msg should be a botan3.MPI or an object which can be converted to one
 
 HOTP
 -----------------------------------------
diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp
index 6a042756c..438e578b4 100644
--- a/src/lib/ffi/ffi.cpp
+++ b/src/lib/ffi/ffi.cpp
@@ -211,7 +211,7 @@ uint32_t botan_ffi_api_version()
 int botan_ffi_supports_api(uint32_t api_version)
    {
    // This is the API introduced in 3.0
-   if(api_version == 20210628)
+   if(api_version == 20230403)
       return BOTAN_FFI_SUCCESS;
 
    // This is the API introduced in 2.18
diff --git a/src/lib/ffi/info.txt b/src/lib/ffi/info.txt
index b30e275af..a4a0c92a7 100644
--- a/src/lib/ffi/info.txt
+++ b/src/lib/ffi/info.txt
@@ -1,5 +1,5 @@
 <defines>
-FFI -> 20210628
+FFI -> 20230403
 </defines>
 
 <module_info>
diff --git a/src/python/botan2.py b/src/python/botan3.py
similarity index 99%
rename from src/python/botan2.py
rename to src/python/botan3.py
index ad8ed7531..44c349704 100755
--- a/src/python/botan2.py
+++ b/src/python/botan3.py
@@ -4,7 +4,7 @@
 Python wrapper of the botan crypto library
 https://botan.randombit.net
 
-(C) 2015,2017,2018,2019 Jack Lloyd
+(C) 2015,2017,2018,2019,2023 Jack Lloyd
 (C) 2015 Uri  Blumenthal (extensions and patches)
 
 Botan is released under the Simplified BSD License (see license.txt)
@@ -12,9 +12,9 @@ Botan is released under the Simplified BSD License (see license.txt)
 This module uses the ctypes module and is usable by programs running
 under at least CPython 3.x, and PyPy
 
-It uses botan's ffi module, which exposes a C API. This version of the
-module requires FFI API version 20180713, which was introduced in
-Botan 2.8
+It uses botan's ffi module, which exposes a C API. This version
+of the Python wrapper requires FFI version 20230403, which was
+introduced in Botan 3.0.0
 
 """
 
@@ -26,7 +26,7 @@ from time import strptime, mktime, time as system_time
 from binascii import hexlify
 from datetime import datetime
 
-BOTAN_FFI_VERSION = 20191214
+BOTAN_FFI_VERSION = 20230403
 
 #
 # Base exception for all exceptions raised from this module
@@ -62,18 +62,14 @@ def _load_botan_dll(expected_version):
 
     if platform in ['win32', 'cygwin', 'msys']:
         possible_dll_names.append('botan-3.dll')
-        possible_dll_names.append('botan.dll')
         possible_dll_names.append('libbotan-3.dll')
-        possible_dll_names.append('libbotan-2.dll')
+        possible_dll_names.append('botan.dll')
     elif platform in ['darwin', 'macos']:
         possible_dll_names.append('libbotan-3.dylib')
-        possible_dll_names.append('libbotan-2.dylib')
     else:
         # assumed to be some Unix/Linux system
         possible_dll_names.append('libbotan-3.so')
-        possible_dll_names += ['libbotan-3.so.%d' % (v) for v in reversed(range(0, 10))]
-        possible_dll_names.append('libbotan-2.so')
-        possible_dll_names += ['libbotan-2.so.%d' % (v) for v in reversed(range(13, 20))]
+        possible_dll_names += ['libbotan-3.so.%d' % (v) for v in reversed(range(0, 16))]
 
     for dll_name in possible_dll_names:
         try:
diff --git a/src/scripts/ci_build.py b/src/scripts/ci_build.py
index 89a6fa27c..d2276125f 100755
--- a/src/scripts/ci_build.py
+++ b/src/scripts/ci_build.py
@@ -574,7 +574,7 @@ def main(args=None):
 
         py_scripts = [
             'configure.py',
-            'src/python/botan2.py',
+            'src/python/botan3.py',
             'src/scripts/ci_build.py',
             'src/scripts/install.py',
             'src/scripts/ci_check_headers.py',
diff --git a/src/scripts/install.py b/src/scripts/install.py
index f0f8522ef..2d059bf5d 100755
--- a/src/scripts/install.py
+++ b/src/scripts/install.py
@@ -216,8 +216,8 @@ def main(args):
 
             py_dir = cfg['python_dir']
 
-            copy_file(os.path.join(py_dir, 'botan2.py'),
-                      prepend_destdir(os.path.join(py_lib_path, 'botan2.py')))
+            copy_file(os.path.join(py_dir, 'botan3.py'),
+                      prepend_destdir(os.path.join(py_lib_path, 'botan3.py')))
 
     if cfg['with_documentation']:
         target_doc_dir = os.path.join(prefix, cfg['docdir'],


Test patch:
diff --git a/src/scripts/test_python.py b/src/scripts/test_python.py
index ee287872b..9d307938d 100644
--- a/src/scripts/test_python.py
+++ b/src/scripts/test_python.py
@@ -20,7 +20,7 @@ import sys
 if platform.system() == "Windows" and hasattr(os, "add_dll_directory"):
     os.add_dll_directory(os.getcwd())
 
-import botan2 # pylint: disable=wrong-import-position
+import botan3 as botan # pylint: disable=wrong-import-position
 
 def hex_encode(buf):
     return binascii.hexlify(buf).decode('ascii')
@@ -39,25 +39,25 @@ class BotanPythonTests(unittest.TestCase):
     # pylint: disable=too-many-public-methods,too-many-locals
 
     def test_version(self):
-        version_str = botan2.version_string()
+        version_str = botan.version_string()
         self.assertTrue(version_str.startswith('Botan '))
 
-        self.assertEqual(botan2.version_major(), 3)
-        self.assertGreaterEqual(botan2.version_minor(), 0)
+        self.assertEqual(botan.version_major(), 3)
+        self.assertGreaterEqual(botan.version_minor(), 0)
 
-        self.assertGreaterEqual(botan2.ffi_api_version(), 20180713)
+        self.assertGreaterEqual(botan.ffi_api_version(), 20180713)
 
     def test_compare(self):
 
         x = "1234"
         y = "1234"
         z = "1233"
-        self.assertTrue(botan2.const_time_compare(x, y))
-        self.assertFalse(botan2.const_time_compare(x, z))
-        self.assertFalse(botan2.const_time_compare(x, x + z))
+        self.assertTrue(botan.const_time_compare(x, y))
+        self.assertFalse(botan.const_time_compare(x, z))
+        self.assertFalse(botan.const_time_compare(x, x + z))
 
     def test_block_cipher(self):
-        aes = botan2.BlockCipher("AES-128")
+        aes = botan.BlockCipher("AES-128")
         self.assertEqual(aes.algo_name(), "AES-128")
         self.assertEqual(aes.block_size(), 16)
         self.assertEqual(aes.minimum_keylength(), 16)
@@ -79,45 +79,45 @@ class BotanPythonTests(unittest.TestCase):
         label = hex_decode('')
         expected = hex_decode('02AEB40A3D4B66FBA540F9D4B20006F2046E0F3A029DEAB201FC692B79EB27CEF7E16069046A')
 
-        produced = botan2.kdf('KDF2(SHA-1)', secret, 38, salt, label)
+        produced = botan.kdf('KDF2(SHA-1)', secret, 38, salt, label)
 
         self.assertEqual(hex_encode(produced), hex_encode(expected))
 
     def test_pbkdf(self):
 
-        (salt, iterations, pbkdf) = botan2.pbkdf('PBKDF2(SHA-1)', '', 32, 10000, hex_decode('0001020304050607'))
+        (salt, iterations, pbkdf) = botan.pbkdf('PBKDF2(SHA-1)', '', 32, 10000, hex_decode('0001020304050607'))
 
         self.assertEqual(iterations, 10000)
         self.assertEqual(hex_encode(pbkdf),
                          '59b2b1143b4cb1059ec58d9722fb1c72471e0d85c6f7543ba5228526375b0127')
 
-        (salt, iterations, pbkdf) = botan2.pbkdf_timed('PBKDF2(SHA-256)', 'xyz', 32, 200)
+        (salt, iterations, pbkdf) = botan.pbkdf_timed('PBKDF2(SHA-256)', 'xyz', 32, 200)
 
-        cmp_pbkdf = botan2.pbkdf('PBKDF2(SHA-256)', 'xyz', 32, iterations, salt)[2]
+        cmp_pbkdf = botan.pbkdf('PBKDF2(SHA-256)', 'xyz', 32, iterations, salt)[2]
 
         self.assertEqual(pbkdf, cmp_pbkdf)
 
     def test_scrypt(self):
-        scrypt = botan2.scrypt(10, '', '', 16, 1, 1)
+        scrypt = botan.scrypt(10, '', '', 16, 1, 1)
         self.assertEqual(hex_encode(scrypt), "77d6576238657b203b19")
 
-        scrypt = botan2.scrypt(32, 'password', 'NaCl', 1024, 8, 16)
+        scrypt = botan.scrypt(32, 'password', 'NaCl', 1024, 8, 16)
         self.assertEqual(hex_encode(scrypt), "fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b373162")
 
     def test_bcrypt(self):
-        r = botan2.RandomNumberGenerator()
-        phash = botan2.bcrypt('testing', r)
+        r = botan.RandomNumberGenerator()
+        phash = botan.bcrypt('testing', r)
         self.assertTrue(isinstance(phash, str))
         self.assertTrue(phash.startswith("$2a$"))
 
-        self.assertTrue(botan2.check_bcrypt('testing', phash))
-        self.assertFalse(botan2.check_bcrypt('live fire', phash))
+        self.assertTrue(botan.check_bcrypt('testing', phash))
+        self.assertFalse(botan.check_bcrypt('live fire', phash))
 
-        self.assertTrue(botan2.check_bcrypt('test', '$2a$04$wjen1fAA.UW6UxthpKK.huyOoxvCR7ATRCVC4CBIEGVDOCtr8Oj1C'))
+        self.assertTrue(botan.check_bcrypt('test', '$2a$04$wjen1fAA.UW6UxthpKK.huyOoxvCR7ATRCVC4CBIEGVDOCtr8Oj1C'))
 
     def test_mac(self):
 
-        hmac = botan2.MsgAuthCode('HMAC(SHA-256)')
+        hmac = botan.MsgAuthCode('HMAC(SHA-256)')
         self.assertEqual(hmac.algo_name(), 'HMAC(SHA-256)')
         self.assertEqual(hmac.minimum_keylength(), 0)
         self.assertEqual(hmac.maximum_keylength(), 4096)
@@ -130,7 +130,7 @@ class BotanPythonTests(unittest.TestCase):
         self.assertEqual(hex_encode(expected), hex_encode(produced))
 
     def test_rng(self):
-        user_rng = botan2.RandomNumberGenerator("user")
+        user_rng = botan.RandomNumberGenerator("user")
 
         output1 = user_rng.get(32)
         output2 = user_rng.get(32)
@@ -142,7 +142,7 @@ class BotanPythonTests(unittest.TestCase):
         output3 = user_rng.get(1021)
         self.assertEqual(len(output3), 1021)
 
-        system_rng = botan2.RandomNumberGenerator('system')
+        system_rng = botan.RandomNumberGenerator('system')
 
         user_rng.reseed_from_rng(system_rng, 256)
 
@@ -151,11 +151,11 @@ class BotanPythonTests(unittest.TestCase):
     def test_hash(self):
 
         try:
-            _h = botan2.HashFunction('NoSuchHash')
-        except botan2.BotanException as e:
+            _h = botan.HashFunction('NoSuchHash')
+        except botan.BotanException as e:
             self.assertEqual(str(e), "botan_hash_init failed: -40 (Not implemented)")
 
-        sha256 = botan2.HashFunction('SHA-256')
+        sha256 = botan.HashFunction('SHA-256')
         self.assertEqual(sha256.algo_name(), 'SHA-256')
         self.assertEqual(sha256.output_length(), 32)
         self.assertEqual(sha256.block_size(), 64)
@@ -176,7 +176,7 @@ class BotanPythonTests(unittest.TestCase):
 
     def test_cipher(self):
         for mode in ['AES-128/CTR-BE', 'Serpent/GCM', 'ChaCha20Poly1305', 'AES-128/CBC/PKCS7']:
-            enc = botan2.SymmetricCipher(mode, encrypt=True)
+            enc = botan.SymmetricCipher(mode, encrypt=True)
 
             if mode == 'AES-128/CTR-BE':
                 self.assertEqual(enc.algo_name(), 'CTR-BE(AES-128)')
@@ -189,7 +189,7 @@ class BotanPythonTests(unittest.TestCase):
 
             self.assertLessEqual(kmin, kmax)
 
-            rng = botan2.RandomNumberGenerator()
+            rng = botan.RandomNumberGenerator()
             iv = rng.get(enc.default_nonce_length())
             key = rng.get(kmax)
             pt = rng.get(21)
@@ -202,7 +202,7 @@ class BotanPythonTests(unittest.TestCase):
 
             ct = enc.finish(pt)
 
-            dec = botan2.SymmetricCipher(mode, encrypt=False)
+            dec = botan.SymmetricCipher(mode, encrypt=False)
             dec.set_key(key)
             dec.start(iv)
             decrypted = dec.finish(ct)
@@ -211,8 +211,8 @@ class BotanPythonTests(unittest.TestCase):
 
 
     def test_mceliece(self):
-        rng = botan2.RandomNumberGenerator()
-        mce_priv = botan2.PrivateKey.create('McEliece', '2960,57', rng)
+        rng = botan.RandomNumberGenerator()
+        mce_priv = botan.PrivateKey.create('McEliece', '2960,57', rng)
         mce_pub = mce_priv.get_public_key()
         self.assertEqual(mce_pub.estimated_strength(), 128)
 
@@ -244,43 +244,43 @@ ofvkP1EDmpx50fHLawIDAQAB
 -----END PUBLIC KEY-----
 """
 
-        rsapriv = botan2.PrivateKey.load(rsa_priv_pem)
+        rsapriv = botan.PrivateKey.load(rsa_priv_pem)
 
         self.assertEqual(rsapriv.to_pem(), rsa_priv_pem)
 
         rsapub = rsapriv.get_public_key()
         self.assertEqual(rsapub.to_pem(), rsa_pub_pem)
 
-        rsapub = botan2.PublicKey.load(rsa_pub_pem)
+        rsapub = botan.PublicKey.load(rsa_pub_pem)
         self.assertEqual(rsapub.to_pem(), rsa_pub_pem)
 
         n = 0xB5AD8818DCA1F256FF8FAB0888D0667D95DF2098B0D201A4C75590D3EBDFA159DD91C64AFDA082609EF885B2D1F4DC055C8FF9FA371C2F3398E0B612C603151131C81DB322C8D15E53EB56B4DF7325F05046889CB25021DE4282E16B9B28F5CBB2B8DDECE0F8E4E8A77F674F26AE92B7220920A1FBE43F51039A9C79D1F1CB6B # pylint: disable=line-too-long
         e = 0x10001
 
-        rsapub2 = botan2.PublicKey.load_rsa(n, e)
+        rsapub2 = botan.PublicKey.load_rsa(n, e)
         self.assertEqual(rsapub2.to_pem(), rsa_pub_pem)
 
         self.assertEqual(rsapub2.get_field("n"), n)
         self.assertEqual(rsapub2.get_field("e"), e)
 
     def test_key_crypto(self):
-        rng = botan2.RandomNumberGenerator()
-        priv = botan2.PrivateKey.create('RSA', '1024', rng)
+        rng = botan.RandomNumberGenerator()
+        priv = botan.PrivateKey.create('RSA', '1024', rng)
         passphrase = "super secret tell noone"
 
         for is_pem in [True, False]:
             ref_val = priv.export(is_pem)
 
             enc1 = priv.export_encrypted(passphrase, rng, True, msec=10)
-            dec1 = botan2.PrivateKey.load(enc1, passphrase)
+            dec1 = botan.PrivateKey.load(enc1, passphrase)
             self.assertEqual(dec1.export(is_pem), ref_val)
 
             pem2 = priv.export_encrypted(passphrase, rng, True, msec=10, cipher="AES-128/SIV")
-            dec2 = botan2.PrivateKey.load(pem2, passphrase)
+            dec2 = botan.PrivateKey.load(pem2, passphrase)
             self.assertEqual(dec2.export(is_pem), ref_val)
 
             pem3 = priv.export_encrypted(passphrase, rng, True, msec=10, cipher="AES-128/GCM", pbkdf="Scrypt")
-            dec3 = botan2.PrivateKey.load(pem3, passphrase)
+            dec3 = botan.PrivateKey.load(pem3, passphrase)
             self.assertEqual(dec3.export(is_pem), ref_val)
 
     def test_check_key(self):
@@ -288,21 +288,21 @@ ofvkP1EDmpx50fHLawIDAQAB
         n = 273279220906618527352827457840955116141
         e = 0x10001
 
-        rng = botan2.RandomNumberGenerator()
+        rng = botan.RandomNumberGenerator()
 
-        rsapub = botan2.PublicKey.load_rsa(n, e)
+        rsapub = botan.PublicKey.load_rsa(n, e)
         self.assertTrue(rsapub.check_key(rng))
 
         # invalid
         try:
-            rsapub = botan2.PublicKey.load_rsa(n - 1, e)
-        except botan2.BotanException as e:
+            rsapub = botan.PublicKey.load_rsa(n - 1, e)
+        except botan.BotanException as e:
             self.assertEqual(str(e), "botan_pubkey_load_rsa failed: -1 (Invalid input): Invalid RSA public key parameters")
 
     def test_rsa(self):
         # pylint: disable=too-many-locals
-        rng = botan2.RandomNumberGenerator()
-        rsapriv = botan2.PrivateKey.create('RSA', '1024', rng)
+        rng = botan.RandomNumberGenerator()
+        rsapriv = botan.PrivateKey.create('RSA', '1024', rng)
         self.assertEqual(rsapriv.algo_name(), 'RSA')
 
         priv_pem = rsapriv.to_pem()
@@ -321,8 +321,8 @@ ofvkP1EDmpx50fHLawIDAQAB
         self.assertEqual(pub_pem[0:27], "-----BEGIN PUBLIC KEY-----\n")
         self.assertGreater(len(pub_pem), len(pub_der))
 
-        enc = botan2.PKEncrypt(rsapub, "OAEP(SHA-256)")
-        dec = botan2.PKDecrypt(rsapriv, "OAEP(SHA-256)")
+        enc = botan.PKEncrypt(rsapub, "OAEP(SHA-256)")
+        dec = botan.PKDecrypt(rsapriv, "OAEP(SHA-256)")
 
         symkey = rng.get(32)
         ctext = enc.encrypt(symkey, rng)
@@ -331,13 +331,13 @@ ofvkP1EDmpx50fHLawIDAQAB
 
         self.assertEqual(ptext, symkey)
 
-        signer = botan2.PKSign(rsapriv, 'EMSA4(SHA-384)')
+        signer = botan.PKSign(rsapriv, 'EMSA4(SHA-384)')
 
         signer.update('messa')
         signer.update('ge')
-        sig = signer.finish(botan2.RandomNumberGenerator())
+        sig = signer.finish(botan.RandomNumberGenerator())
 
-        verify = botan2.PKVerify(rsapub, 'EMSA4(SHA-384)')
+        verify = botan.PKVerify(rsapub, 'EMSA4(SHA-384)')
 
         verify.update('mess')
         verify.update('age')
@@ -351,39 +351,39 @@ ofvkP1EDmpx50fHLawIDAQAB
         self.assertTrue(verify.check_signature(sig))
 
     def test_ecdsa(self):
-        rng = botan2.RandomNumberGenerator()
+        rng = botan.RandomNumberGenerator()
 
         hash_fn = 'EMSA1(SHA-256)'
         group = 'secp256r1'
         msg = 'test message'
 
-        priv = botan2.PrivateKey.create('ECDSA', group, rng)
+        priv = botan.PrivateKey.create('ECDSA', group, rng)
         pub = priv.get_public_key()
         self.assertEqual(pub.get_field('public_x'), priv.get_field('public_x'))
         self.assertEqual(pub.get_field('public_y'), priv.get_field('public_y'))
 
-        signer = botan2.PKSign(priv, hash_fn, True)
+        signer = botan.PKSign(priv, hash_fn, True)
         signer.update(msg)
         signature = signer.finish(rng)
 
-        verifier = botan2.PKVerify(pub, hash_fn)
+        verifier = botan.PKVerify(pub, hash_fn)
         verifier.update(msg)
         #fails because DER/not-DER mismatch
         self.assertFalse(verifier.check_signature(signature))
 
-        verifier = botan2.PKVerify(pub, hash_fn, True)
+        verifier = botan.PKVerify(pub, hash_fn, True)
         verifier.update(msg)
         self.assertTrue(verifier.check_signature(signature))
 
         pub_x = pub.get_field('public_x')
         pub_y = priv.get_field('public_y')
-        pub2 = botan2.PublicKey.load_ecdsa(group, pub_x, pub_y)
-        verifier = botan2.PKVerify(pub2, hash_fn, True)
+        pub2 = botan.PublicKey.load_ecdsa(group, pub_x, pub_y)
+        verifier = botan.PKVerify(pub2, hash_fn, True)
         verifier.update(msg)
         self.assertTrue(verifier.check_signature(signature))
 
-        priv2 = botan2.PrivateKey.load_ecdsa(group, priv.get_field('x'))
-        signer = botan2.PKSign(priv2, hash_fn, True)
+        priv2 = botan.PrivateKey.load_ecdsa(group, priv.get_field('x'))
+        signer = botan.PKSign(priv2, hash_fn, True)
         # sign empty message
         signature = signer.finish(rng)
 
@@ -391,34 +391,34 @@ ofvkP1EDmpx50fHLawIDAQAB
         self.assertTrue(verifier.check_signature(signature))
 
     def test_sm2(self):
-        rng = botan2.RandomNumberGenerator()
+        rng = botan.RandomNumberGenerator()
 
         hash_fn = 'EMSA1(SM3)'
         group = 'sm2p256v1'
         msg = 'test message'
 
-        priv = botan2.PrivateKey.create('SM2', group, rng)
+        priv = botan.PrivateKey.create('SM2', group, rng)
         pub = priv.get_public_key()
         self.assertEqual(pub.get_field('public_x'), priv.get_field('public_x'))
         self.assertEqual(pub.get_field('public_y'), priv.get_field('public_y'))
 
-        signer = botan2.PKSign(priv, hash_fn)
+        signer = botan.PKSign(priv, hash_fn)
         signer.update(msg)
         signature = signer.finish(rng)
 
-        verifier = botan2.PKVerify(pub, hash_fn)
+        verifier = botan.PKVerify(pub, hash_fn)
         verifier.update(msg)
         self.assertTrue(verifier.check_signature(signature))
 
         pub_x = pub.get_field('public_x')
         pub_y = priv.get_field('public_y')
-        pub2 = botan2.PublicKey.load_sm2(group, pub_x, pub_y)
-        verifier = botan2.PKVerify(pub2, hash_fn)
+        pub2 = botan.PublicKey.load_sm2(group, pub_x, pub_y)
+        verifier = botan.PKVerify(pub2, hash_fn)
         verifier.update(msg)
         self.assertTrue(verifier.check_signature(signature))
 
-        priv2 = botan2.PrivateKey.load_sm2(group, priv.get_field('x'))
-        signer = botan2.PKSign(priv2, hash_fn)
+        priv2 = botan.PrivateKey.load_sm2(group, priv.get_field('x'))
+        signer = botan.PKSign(priv2, hash_fn)
         # sign empty message
         signature = signer.finish(rng)
 
@@ -427,17 +427,17 @@ ofvkP1EDmpx50fHLawIDAQAB
 
     def test_ecdh(self):
         # pylint: disable=too-many-locals
-        a_rng = botan2.RandomNumberGenerator('user')
-        b_rng = botan2.RandomNumberGenerator('user')
+        a_rng = botan.RandomNumberGenerator('user')
+        b_rng = botan.RandomNumberGenerator('user')
 
         kdf = 'KDF2(SHA-384)'
 
         for grp in ['secp256r1', 'secp384r1', 'brainpool256r1']:
-            a_priv = botan2.PrivateKey.create('ECDH', grp, a_rng)
-            b_priv = botan2.PrivateKey.create('ECDH', grp, b_rng)
+            a_priv = botan.PrivateKey.create('ECDH', grp, a_rng)
+            b_priv = botan.PrivateKey.create('ECDH', grp, b_rng)
 
-            a_op = botan2.PKKeyAgreement(a_priv, kdf)
-            b_op = botan2.PKKeyAgreement(b_priv, kdf)
+            a_op = botan.PKKeyAgreement(a_priv, kdf)
+            b_op = botan.PKKeyAgreement(b_priv, kdf)
 
             a_pub = a_op.public_value()
             b_pub = b_op.public_value()
@@ -453,13 +453,13 @@ ofvkP1EDmpx50fHLawIDAQAB
 
             a_priv_x = a_priv.get_field('x')
 
-            new_a = botan2.PrivateKey.load_ecdh(grp, a_priv_x)
+            new_a = botan.PrivateKey.load_ecdh(grp, a_priv_x)
 
             self.assertEqual(a_pem, new_a.to_pem())
 
     def test_certs(self):
         # pylint: disable=too-many-statements
-        cert = botan2.X509Cert(filename=test_data("src/tests/data/x509/ecc/CSCA.CSCA.csca-germany.1.crt"))
+        cert = botan.X509Cert(filename=test_data("src/tests/data/x509/ecc/CSCA.CSCA.csca-germany.1.crt"))
         pubkey = cert.subject_public_key()
 
         self.assertEqual(pubkey.algo_name(), 'ECDSA')
@@ -496,40 +496,40 @@ ofvkP1EDmpx50fHLawIDAQAB
         self.assertFalse(cert.allowed_usage(["DIGITAL_SIGNATURE"]))
         self.assertFalse(cert.allowed_usage(["DIGITAL_SIGNATURE", "CRL_SIGN"]))
 
-        root = botan2.X509Cert(test_data("src/tests/data/x509/nist/root.crt"))
+        root = botan.X509Cert(test_data("src/tests/data/x509/nist/root.crt"))
 
-        int09 = botan2.X509Cert(test_data("src/tests/data/x509/nist/test09/int.crt"))
-        end09 = botan2.X509Cert(test_data("src/tests/data/x509/nist/test09/end.crt"))
+        int09 = botan.X509Cert(test_data("src/tests/data/x509/nist/test09/int.crt"))
+        end09 = botan.X509Cert(test_data("src/tests/data/x509/nist/test09/end.crt"))
         self.assertEqual(end09.verify([int09], [root]), 2001)
 
-        end04 = botan2.X509Cert(test_data("src/tests/data/x509/nist/test04/end.crt"))
-        int04_1 = botan2.X509Cert(test_data("src/tests/data/x509/nist/test04/int1.crt"))
-        int04_2 = botan2.X509Cert(test_data("src/tests/data/x509/nist/test04/int2.crt"))
+        end04 = botan.X509Cert(test_data("src/tests/data/x509/nist/test04/end.crt"))
+        int04_1 = botan.X509Cert(test_data("src/tests/data/x509/nist/test04/int1.crt"))
+        int04_2 = botan.X509Cert(test_data("src/tests/data/x509/nist/test04/int2.crt"))
         self.assertEqual(end04.verify([int04_1, int04_2], [], test_data("src/tests/data/x509/nist/"), required_strength=80), 0)
         self.assertEqual(end04.verify([int04_1, int04_2], [], required_strength=80), 3000)
         self.assertEqual(end04.verify([int04_1, int04_2], [root], required_strength=80, hostname="User1-CP.02.01"), 0)
         self.assertEqual(end04.verify([int04_1, int04_2], [root], required_strength=80, hostname="invalid"), 4008)
         self.assertEqual(end04.verify([int04_1, int04_2], [root], required_strength=80, reference_time=1), 2000)
 
-        self.assertEqual(botan2.X509Cert.validation_status(0), 'Verified')
-        self.assertEqual(botan2.X509Cert.validation_status(3000), 'Certificate issuer not found')
-        self.assertEqual(botan2.X509Cert.validation_status(4008), 'Certificate does not match provided name')
+        self.assertEqual(botan.X509Cert.validation_status(0), 'Verified')
+        self.assertEqual(botan.X509Cert.validation_status(3000), 'Certificate issuer not found')
+        self.assertEqual(botan.X509Cert.validation_status(4008), 'Certificate does not match provided name')
 
-        rootcrl = botan2.X509CRL(test_data("src/tests/data/x509/nist/root.crl"))
+        rootcrl = botan.X509CRL(test_data("src/tests/data/x509/nist/root.crl"))
 
-        end01 = botan2.X509Cert(test_data("src/tests/data/x509/nist/test01/end.crt"))
+        end01 = botan.X509Cert(test_data("src/tests/data/x509/nist/test01/end.crt"))
         self.assertEqual(end01.verify([], [root], required_strength=80, crls=[rootcrl]), 0)
 
-        int20 = botan2.X509Cert(test_data("src/tests/data/x509/nist/test20/int.crt"))
-        end20 = botan2.X509Cert(test_data("src/tests/data/x509/nist/test20/end.crt"))
-        int20crl = botan2.X509CRL(test_data("src/tests/data/x509/nist/test20/int.crl"))
+        int20 = botan.X509Cert(test_data("src/tests/data/x509/nist/test20/int.crt"))
+        end20 = botan.X509Cert(test_data("src/tests/data/x509/nist/test20/end.crt"))
+        int20crl = botan.X509CRL(test_data("src/tests/data/x509/nist/test20/int.crl"))
 
         self.assertEqual(end20.verify([int20], [root], required_strength=80, crls=[int20crl, rootcrl]), 5000)
-        self.assertEqual(botan2.X509Cert.validation_status(5000), 'Certificate is revoked')
+        self.assertEqual(botan.X509Cert.validation_status(5000), 'Certificate is revoked')
 
-        int21 = botan2.X509Cert(test_data("src/tests/data/x509/nist/test21/int.crt"))
-        end21 = botan2.X509Cert(test_data("src/tests/data/x509/nist/test21/end.crt"))
-        int21crl = botan2.X509CRL(test_data("src/tests/data/x509/nist/test21/int.crl"))
+        int21 = botan.X509Cert(test_data("src/tests/data/x509/nist/test21/int.crt"))
+        end21 = botan.X509Cert(test_data("src/tests/data/x509/nist/test21/end.crt"))
+        int21crl = botan.X509CRL(test_data("src/tests/data/x509/nist/test21/int.crl"))
         self.assertEqual(end21.verify([int21], [root], required_strength=80, crls=[int21crl, rootcrl]), 5000)
 
         self.assertTrue(int20.is_revoked(rootcrl))
@@ -539,14 +539,14 @@ ofvkP1EDmpx50fHLawIDAQAB
 
     def test_mpi(self):
         # pylint: disable=too-many-statements,too-many-locals
-        z = botan2.MPI()
+        z = botan.MPI()
         self.assertEqual(z.bit_count(), 0)
-        five = botan2.MPI('5')
+        five = botan.MPI('5')
         self.assertEqual(five.bit_count(), 3)
-        big = botan2.MPI('0x85839682368923476892367235')
+        big = botan.MPI('0x85839682368923476892367235')
         self.assertEqual(big.bit_count(), 104)
-        small = botan2.MPI(0xDEADBEEF)
-        radix = botan2.MPI("DEADBEEF", 16)
+        small = botan.MPI(0xDEADBEEF)
+        radix = botan.MPI("DEADBEEF", 16)
 
         self.assertEqual(hex_encode(small.to_bytes()), "deadbeef")
         self.assertEqual(hex_encode(big.to_bytes()), "85839682368923476892367235")
@@ -564,18 +564,18 @@ ofvkP1EDmpx50fHLawIDAQAB
 
         self.assertEqual(int(small), 0xDEAD8000)
 
-        ten = botan2.MPI(10)
+        ten = botan.MPI(10)
 
         self.assertEqual(ten, five + five)
         self.assertNotEqual(ten, five)
         self.assertLess(five, ten)
         self.assertLessEqual(five, ten)
 
-        x = botan2.MPI(five)
+        x = botan.MPI(five)
 
         self.assertEqual(x, five)
 
-        x += botan2.MPI(1)
+        x += botan.MPI(1)
         self.assertNotEqual(x, five)
 
         self.assertEqual(int(x * five), 30)
@@ -601,10 +601,10 @@ ofvkP1EDmpx50fHLawIDAQAB
         x.clear_bit(4)
         self.assertEqual(int(x), 135)
 
-        rng = botan2.RandomNumberGenerator()
+        rng = botan.RandomNumberGenerator()
         self.assertFalse(x.is_prime(rng))
 
-        two = botan2.MPI(2)
+        two = botan.MPI(2)
 
         x += two
         self.assertTrue(x.is_prime(rng))
@@ -615,12 +615,12 @@ ofvkP1EDmpx50fHLawIDAQAB
         self.assertEqual(int(inv), 69)
         self.assertEqual(int((inv * x) % mod), 1)
 
-        p = inv.pow_mod(botan2.MPI(46), mod)
+        p = inv.pow_mod(botan.MPI(46), mod)
         self.assertEqual(int(p), 42)
 
-        one = botan2.MPI(1)
-        twelve = botan2.MPI("C", 16)
-        eight = botan2.MPI(8)
+        one = botan.MPI(1)
+        twelve = botan.MPI("C", 16)
+        eight = botan.MPI(8)
 
         mul = twelve.mod_mul(eight, inv)
         self.assertEqual(int(mul), 27)
@@ -633,27 +633,27 @@ ofvkP1EDmpx50fHLawIDAQAB
         self.assertEqual(4, int(gcd))
 
     def test_mpi_random(self):
-        rng = botan2.RandomNumberGenerator()
+        rng = botan.RandomNumberGenerator()
 
-        u = botan2.MPI.random(rng, 512)
+        u = botan.MPI.random(rng, 512)
         self.assertEqual(u.bit_count(), 512)
 
         l = u >> 32
         self.assertEqual(l.bit_count(), 512-32)
 
         for _i in range(10):
-            x = botan2.MPI.random_range(rng, l, u)
+            x = botan.MPI.random_range(rng, l, u)
             self.assertLess(x, u)
             self.assertGreater(x, l)
 
     def test_fpe(self):
 
-        modulus = botan2.MPI('1000000000')
+        modulus = botan.MPI('1000000000')
         key = b'001122334455'
 
-        fpe = botan2.FormatPreservingEncryptionFE1(modulus, key)
+        fpe = botan.FormatPreservingEncryptionFE1(modulus, key)
 
-        value = botan2.MPI('392910392')
+        value = botan.MPI('392910392')
         tweak = 'tweak value'
 
         ctext = fpe.encrypt(value, tweak)
@@ -666,16 +666,16 @@ ofvkP1EDmpx50fHLawIDAQAB
         key = hex_decode('00112233445566778899aabbccddeeff')
         kek = hex_decode('000102030405060708090a0b0c0d0e0f')
 
-        wrapped = botan2.nist_key_wrap(kek, key)
+        wrapped = botan.nist_key_wrap(kek, key)
         self.assertEqual(hex_encode(wrapped), '1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5')
 
         self.assertEqual(len(wrapped), 16+8)
-        unwrapped = botan2.nist_key_unwrap(kek, wrapped)
+        unwrapped = botan.nist_key_unwrap(kek, wrapped)
         self.assertEqual(hex_encode(unwrapped), '00112233445566778899aabbccddeeff')
 
     def test_hotp(self):
 
-        hotp = botan2.HOTP(b'12345678901234567890')
+        hotp = botan.HOTP(b'12345678901234567890')
 
         self.assertEqual(hotp.generate(0), 755224)
         self.assertEqual(hotp.generate(1), 287082)
@@ -688,7 +688,7 @@ ofvkP1EDmpx50fHLawIDAQAB
 
     def test_totp(self):
 
-        totp = botan2.TOTP(b'12345678901234567890', digest="SHA-1", digits=8)
+        totp = botan.TOTP(b'12345678901234567890', digest="SHA-1", digits=8)
 
         self.assertEqual(totp.generate(59), 94287082)
         self.assertEqual(totp.generate(1111111109), 7081804)
@@ -705,16 +705,16 @@ ofvkP1EDmpx50fHLawIDAQAB
     def test_srp6(self):
         identity = 'alice'
         password = 'password123'
-        rng = botan2.RandomNumberGenerator()
+        rng = botan.RandomNumberGenerator()
         group = 'modp/srp/1024'
         hash_fn = 'SHA-512'
 
         # Test successful authentication
-        server = botan2.Srp6ServerSession()
+        server = botan.Srp6ServerSession()
         salt = rng.get(24)
-        verifier = botan2.generate_srp6_verifier(identity, password, salt, group, hash_fn)
+        verifier = botan.generate_srp6_verifier(identity, password, salt, group, hash_fn)
         b = server.step1(verifier, group, hash_fn, rng)
-        (a, key_c) = botan2.srp6_client_agree(identity, password, group, hash_fn, salt, b, rng)
+        (a, key_c) = botan.srp6_client_agree(identity, password, group, hash_fn, salt, b, rng)
         key_s = server.step2(a)
         self.assertEqual(key_c, key_s)