aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-03-10 15:42:41 -0500
committerJack Lloyd <[email protected]>2018-03-10 15:42:41 -0500
commit5a062118ef5e4c508caa67fc8c3a38a7e1db069f (patch)
tree5ec06e8b42f6f79d19146aa070acb7a1e3d6c314
parentafe4ae0f83b7207873afac760cb3c32ed40ce4c9 (diff)
Split Python tests out of botan2.py
No reason to ship these to the end user
-rwxr-xr-xsrc/python/botan2.py258
-rwxr-xr-xsrc/scripts/ci_build.py10
-rwxr-xr-xsrc/scripts/install.py5
-rw-r--r--src/scripts/test_python.py265
4 files changed, 277 insertions, 261 deletions
diff --git a/src/python/botan2.py b/src/python/botan2.py
index 700719496..07f4b0d01 100755
--- a/src/python/botan2.py
+++ b/src/python/botan2.py
@@ -18,7 +18,7 @@ versions of Botan >= 2.0
import sys
from ctypes import CDLL, POINTER, byref, c_void_p, c_size_t, c_uint32, c_char, c_char_p, create_string_buffer
-from binascii import hexlify, unhexlify, b2a_base64
+from binascii import hexlify
from datetime import datetime
import time
@@ -93,12 +93,9 @@ def _ctype_bufout(buf):
else:
return buf.raw
-def hex_encode(buf):
+def _hex_encode(buf):
return hexlify(buf).decode('ascii')
-def hex_decode(buf):
- return unhexlify(buf.encode('ascii'))
-
#
# Versions
#
@@ -404,7 +401,7 @@ class public_key(object): # pylint: disable=invalid-name
buf_len = c_size_t(n)
botan.botan_pubkey_fingerprint(self.pubkey, _ctype_str(hash_algorithm), buf, byref(buf_len))
- return hex_encode(buf[0:buf_len.value])
+ return _hex_encode(buf[0:buf_len.value])
class private_key(object): # pylint: disable=invalid-name
def __init__(self, alg, param, rng_instance):
@@ -716,252 +713,3 @@ class x509_cert(object): # pylint: disable=invalid-name
c_void_p, c_char_p, c_size_t, POINTER(c_char), POINTER(c_size_t)]
return _call_fn_returning_string(
0, lambda b, bl: botan.botan_x509_cert_get_subject_dn(self.x509_cert, _ctype_str(key), index, b, bl))
-
-
-#
-# Tests and examples
-#
-def test():
-
- def test_version():
-
- print("\n%s" % version_string())
- print("v%d.%d.%d\n" % (version_major(), version_minor(), version_patch()))
- print("\nPython %s\n" % sys.version.replace('\n', ' '))
-
- def test_kdf():
- print("KDF2(SHA-1) %s" %
- hex_encode(kdf('KDF2(SHA-1)', hex_decode('701F3480DFE95F57941F804B1B2413EF'), 7,
- hex_decode('55A4E9DD5F4CA2EF82'), hex_decode(''))))
-
- def test_pbkdf():
- print("PBKDF2(SHA-1) %s" %
- hex_encode(pbkdf('PBKDF2(SHA-1)', '', 32, 10000, hex_decode('0001020304050607'))[2]))
- print("good output %s\n" %
- '59B2B1143B4CB1059EC58D9722FB1C72471E0D85C6F7543BA5228526375B0127')
-
- (salt, iterations, psk) = pbkdf_timed('PBKDF2(SHA-256)', 'xyz', 32, 200)
-
- print("PBKDF2(SHA-256) x=timed, y=iterated; salt = %s (len=%d) #iterations = %d\n" %
- (hex_encode(salt), len(salt), iterations))
-
- print('x %s' % hex_encode(psk))
- print('y %s\n' % (hex_encode(pbkdf('PBKDF2(SHA-256)', 'xyz', 32, iterations, salt)[2])))
-
- def test_bcrypt():
- print("Testing Bcrypt...")
- r = rng()
- phash = bcrypt('testing', r)
- print("bcrypt returned %s (%d bytes)" % (hex_encode(phash), len(phash)))
- print("validating the hash produced: %r" % (check_bcrypt('testing', phash)))
- print("\n")
-
- def test_hmac():
-
- hmac = message_authentication_code('HMAC(SHA-256)')
- hmac.set_key(hex_decode('0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20'))
- hmac.update(hex_decode('616263'))
-
- hmac_vec = hex_decode('A21B1F5D4CF4F73A4DD939750F7A066A7F98CC131CB16A6692759021CFAB8181')
- hmac_output = hmac.final()
-
- if hmac_output != hmac_vec:
- print("Bad HMAC:\t%s" % hex_encode(hmac_output))
- print("vs good: \t%s" % hex_encode(hmac_vec))
- else:
- print("HMAC output correct: %s\n" % hex_encode(hmac_output))
-
- def test_rng():
- user_rng = rng("user")
-
- print("rng output:\n\t%s\n\t%s\n\t%s\n" %
- (hex_encode(user_rng.get(42)),
- hex_encode(user_rng.get(13)),
- hex_encode(user_rng.get(9))))
-
- def test_hash():
- md5 = hash_function('MD5')
- assert md5.output_length() == 16
- md5.update('h')
- md5.update('i')
- h1 = md5.final()
- print("md5 hash: %s (%s)\n" % (hex_encode(h1), '49f68a5c8493ec2c0bf489821c21fc3b'))
-
- md5.update(hex_decode('f468025b'))
- h2 = md5.final()
- print("md5 hash: %s (%s)\n" % (hex_encode(h2), '47efd2be302a937775e93dea281b6751'))
-
- def test_cipher():
- for mode in ['AES-128/CTR-BE', 'Serpent/GCM', 'ChaCha20Poly1305']:
- enc = cipher(mode, encrypt=True)
-
- (kmin, kmax) = enc.key_length()
- print("%s: default nonce=%d update_size=%d key_min=%d key_max=%d" %
- (mode, enc.default_nonce_length(), enc.update_granularity(), kmin, kmax))
- iv = rng().get(enc.default_nonce_length())
- key = rng().get(kmax)
- pt = rng().get(21)
-
- print(" plaintext %s (%d)" % (hex_encode(pt), len(pt)))
-
- enc.set_key(key)
- enc.start(iv)
-
- update_result = enc.update('')
- assert not update_result
-
- ct = enc.finish(pt)
- print(" ciphertext %s (%d)" % (hex_encode(ct), len(ct)))
-
- dec = cipher(mode, encrypt=False)
- dec.set_key(key)
- dec.start(iv)
- decrypted = dec.finish(ct)
-
- print(" decrypted %s (%d)\n" % (hex_encode(decrypted), len(decrypted)))
-
-
- def test_mceliece():
- mce_priv = private_key('mce', [2960, 57], rng())
- mce_pub = mce_priv.get_public_key()
-
- mce_plaintext = 'mce plaintext'
- mce_ad = 'mce AD'
- mce_ciphertext = mceies_encrypt(mce_pub, rng(), 'ChaCha20Poly1305', mce_plaintext, mce_ad)
-
- print("mceies len(pt)=%d len(ct)=%d" % (len(mce_plaintext), len(mce_ciphertext)))
-
- mce_decrypt = mceies_decrypt(mce_priv, 'ChaCha20Poly1305', mce_ciphertext, mce_ad)
- print(" mceies plaintext \'%s\' (%d)" % (mce_plaintext, len(mce_plaintext)))
-
- # Since mceies_decrypt() returns bytes in Python3, the following line
- # needs .decode('utf-8') to convert mce_decrypt from bytes to a
- # text string (Unicode).
- # You don't need to add .decode() if
- # (a) your expected output is bytes rather than a text string, or
- # (b) you are using Python2 rather than Python3.
- print(" mceies decrypted \'%s\' (%d)" % (mce_decrypt.decode('utf-8'), len(mce_decrypt)))
-
- print("mce_pub %s/SHA-1 fingerprint: %s\nEstimated strength %s bits (len %d)\n" % (
- mce_pub.algo_name(), mce_pub.fingerprint("SHA-1"),
- mce_pub.estimated_strength(), len(mce_pub.encoding())
- ))
-
- def test_rsa():
- rsapriv = private_key('rsa', 1536, rng())
- rsapub = rsapriv.get_public_key()
-
- print("rsapub %s SHA-1 fingerprint: %s estimated strength %d (len %d)" % (
- rsapub.algo_name(), rsapub.fingerprint("SHA-1"),
- rsapub.estimated_strength(), len(rsapub.encoding())
- ))
-
- dec = pk_op_decrypt(rsapriv, "EME1(SHA-256)")
- enc = pk_op_encrypt(rsapub, "EME1(SHA-256)")
-
- sys_rng = rng()
- symkey = sys_rng.get(32)
- ctext = enc.encrypt(symkey, sys_rng)
- print("ptext \'%s\' (%d)" % (hex_encode(symkey), len(symkey)))
- print("ctext \'%s\' (%d)" % (hex_encode(ctext), len(ctext)))
- print("decrypt \'%s\' (%d)\n" % (hex_encode(dec.decrypt(ctext)),
- len(dec.decrypt(ctext))))
-
- signer = pk_op_sign(rsapriv, 'EMSA4(SHA-384)')
-
- signer.update('messa')
- signer.update('ge')
- sig = signer.finish(rng())
-
- print("EMSA4(SHA-384) signature: %s" % hex_encode(sig))
-
- verify = pk_op_verify(rsapub, 'EMSA4(SHA-384)')
-
- verify.update('mess')
- verify.update('age')
- print("good sig accepted? %s" % verify.check_signature(sig))
-
- verify.update('mess of things')
- verify.update('age')
- print("bad sig accepted? %s" % verify.check_signature(sig))
-
- verify.update('message')
- print("good sig accepted? %s\n" % verify.check_signature(sig))
-
- def test_dh():
- a_rng = rng('user')
- b_rng = rng('user')
-
- for dh_grp in ['secp256r1', 'curve25519']:
- dh_kdf = 'KDF2(SHA-384)'.encode('utf-8')
- a_dh_priv = private_key('ecdh', dh_grp, rng())
- b_dh_priv = private_key('ecdh', dh_grp, rng())
-
- a_dh = pk_op_key_agreement(a_dh_priv, dh_kdf)
- b_dh = pk_op_key_agreement(b_dh_priv, dh_kdf)
-
- a_dh_pub = a_dh.public_value()
- b_dh_pub = b_dh.public_value()
-
- a_salt = a_rng.get(8)
- b_salt = b_rng.get(8)
-
- print("ecdh %s pubs:\n %s (salt %s)\n %s (salt %s)\n" %
- (dh_grp,
- hex_encode(a_dh_pub), hex_encode(a_salt),
- hex_encode(b_dh_pub), hex_encode(b_salt)))
-
- a_key = a_dh.agree(b_dh_pub, 32, a_salt + b_salt)
- b_key = b_dh.agree(a_dh_pub, 32, a_salt + b_salt)
-
- print("ecdh %s shared:\n %s\n %s\n" %
- (dh_grp, hex_encode(a_key), hex_encode(b_key)))
-
- def test_certs():
- cert = x509_cert(filename="src/tests/data/x509/ecc/CSCA.CSCA.csca-germany.1.crt")
- print("CSCA (Germany) Certificate\nDetails:")
- print("SHA-1 fingerprint: %s" % cert.fingerprint("SHA-1"))
- print("Expected: 32:42:1C:C3:EC:54:D7:E9:43:EC:51:F0:19:23:BD:85:1D:F2:1B:B9")
-
- print("Not before: %s" % cert.time_starts())
- print("Not after: %s" % cert.time_expires())
-
- print("Serial number: %s" % hex_encode(cert.serial_number()))
- print("Authority Key ID: %s" % hex_encode(cert.authority_key_id()))
- print("Subject Key ID: %s" % hex_encode(cert.subject_key_id()))
- print("Public key bits:\n%s\n" % b2a_base64(cert.subject_public_key_bits()))
-
- pubkey = cert.subject_public_key()
- print("Public key algo: %s" % pubkey.algo_name())
- print("Public key strength: %s" % pubkey.estimated_strength() + " bits")
-
- dn_fields = ("Name", "Email", "Organization", "Organizational Unit", "Country")
- for field in dn_fields:
- try:
- print("%s: %s" % (field, cert.subject_dn(field, 0)))
- except BotanException:
- print("Field: %s not found in certificate" % field)
-
- print(cert.to_string())
-
- test_version()
- test_kdf()
- test_pbkdf()
- test_bcrypt()
- test_hmac()
- test_rng()
- test_hash()
- test_cipher()
- test_mceliece()
- test_rsa()
- test_dh()
- test_certs()
-
-
-def main(args=None):
- if args is None:
- args = sys.argv
- test()
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/src/scripts/ci_build.py b/src/scripts/ci_build.py
index 5560ced51..a9a6afbdf 100755
--- a/src/scripts/ci_build.py
+++ b/src/scripts/ci_build.py
@@ -213,6 +213,7 @@ def run_cmd(cmd, root_dir):
cmd = [os.path.expandvars(elem) for elem in cmd]
sub_env = os.environ.copy()
sub_env['LD_LIBRARY_PATH'] = root_dir
+ sub_env['PYTHONPATH'] = os.path.join(root_dir, 'src/python')
redirect_stdout = None
if len(cmd) > 3 and cmd[-2] == '>':
@@ -376,6 +377,7 @@ def main(args=None):
'src/scripts/build_docs.py',
'src/scripts/website.py',
'src/scripts/bench.py',
+ 'src/scripts/test_python.py',
'src/scripts/python_unittests.py',
'src/scripts/python_unittests_unix.py']
@@ -436,14 +438,14 @@ def main(args=None):
os.path.join(root_dir, 'src/scripts/cli_tests.py'),
botan_exe])
- botan_py = os.path.join(root_dir, 'src/python/botan2.py')
+ python_tests = os.path.join(root_dir, 'src/scripts/test_python.py')
if target in ['shared', 'coverage']:
if use_python2:
- cmds.append(['python2', botan_py])
+ cmds.append(['python2', '-b', python_tests])
if use_python3:
- cmds.append(['python3', botan_py])
+ cmds.append(['python3', '-b', python_tests])
if target in ['shared', 'static', 'bsi', 'nist']:
cmds.append(make_cmd + ['install'])
@@ -480,7 +482,7 @@ def main(args=None):
if have_prog('coverage'):
cmds.append(['coverage', 'run', '--branch',
'--rcfile', os.path.join(root_dir, 'src/configs/coverage.rc'),
- botan_py])
+ python_tests])
if have_prog('codecov'):
# If codecov exists assume we are on Travis and report to codecov.io
diff --git a/src/scripts/install.py b/src/scripts/install.py
index 243d58eda..03a15ba3e 100755
--- a/src/scripts/install.py
+++ b/src/scripts/install.py
@@ -236,8 +236,9 @@ def main(args):
makedirs(prepend_destdir(py_lib_path))
py_dir = cfg['python_dir']
- for py in os.listdir(py_dir):
- copy_file(os.path.join(py_dir, py), prepend_destdir(os.path.join(py_lib_path, py)))
+
+ copy_file(os.path.join(py_dir, 'botan2.py'),
+ prepend_destdir(os.path.join(py_lib_path, 'botan2.py')))
if cfg['with_documentation']:
target_doc_dir = os.path.join(options.prefix, options.docdir,
diff --git a/src/scripts/test_python.py b/src/scripts/test_python.py
new file mode 100644
index 000000000..aad6b212b
--- /dev/null
+++ b/src/scripts/test_python.py
@@ -0,0 +1,265 @@
+#!/usr/bin/env python
+
+"""
+(C) 2015,2017,2018 Jack Lloyd
+
+Botan is released under the Simplified BSD License (see license.txt)
+"""
+
+import botan2
+import sys
+import binascii
+
+def hex_encode(buf):
+ return binascii.hexlify(buf).decode('ascii')
+
+def hex_decode(buf):
+ return binascii.unhexlify(buf.encode('ascii'))
+
+def test():
+
+ def test_version():
+
+ print("\n%s" % botan2.version_string())
+ print("v%d.%d.%d\n" % (botan2.version_major(), botan2.version_minor(), botan2.version_patch()))
+ print("\nPython %s\n" % sys.version.replace('\n', ' '))
+
+ def test_kdf():
+ print("KDF2(SHA-1) %s" %
+ hex_encode(botan2.kdf('KDF2(SHA-1)',
+ hex_decode('701F3480DFE95F57941F804B1B2413EF'), 7,
+ hex_decode('55A4E9DD5F4CA2EF82'), hex_decode(''))))
+
+ def test_pbkdf():
+ print("PBKDF2(SHA-1) %s" %
+ hex_encode(botan2.pbkdf('PBKDF2(SHA-1)', '', 32, 10000, hex_decode('0001020304050607'))[2]))
+ print("good output %s\n" %
+ '59B2B1143B4CB1059EC58D9722FB1C72471E0D85C6F7543BA5228526375B0127')
+
+ (salt, iterations, psk) = botan2.pbkdf_timed('PBKDF2(SHA-256)', 'xyz', 32, 200)
+
+ print("PBKDF2(SHA-256) x=timed, y=iterated; salt = %s (len=%d) #iterations = %d\n" %
+ (hex_encode(salt), len(salt), iterations))
+
+ print('x %s' % hex_encode(psk))
+ print('y %s\n' % (hex_encode(botan2.pbkdf('PBKDF2(SHA-256)', 'xyz', 32, iterations, salt)[2])))
+
+ def test_bcrypt():
+ print("Testing Bcrypt...")
+ r = botan2.rng()
+ phash = botan2.bcrypt('testing', r)
+ print("bcrypt returned %s (%d bytes)" % (hex_encode(phash), len(phash)))
+ print("validating the hash produced: %r" % (botan2.check_bcrypt('testing', phash)))
+ print("\n")
+
+ def test_hmac():
+
+ hmac = botan2.message_authentication_code('HMAC(SHA-256)')
+ hmac.set_key(hex_decode('0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20'))
+ hmac.update(hex_decode('616263'))
+
+ hmac_vec = hex_decode('A21B1F5D4CF4F73A4DD939750F7A066A7F98CC131CB16A6692759021CFAB8181')
+ hmac_output = hmac.final()
+
+ if hmac_output != hmac_vec:
+ print("Bad HMAC:\t%s" % hex_encode(hmac_output))
+ print("vs good: \t%s" % hex_encode(hmac_vec))
+ else:
+ print("HMAC output correct: %s\n" % hex_encode(hmac_output))
+
+ def test_rng():
+ user_rng = botan2.rng("user")
+
+ print("rng output:\n\t%s\n\t%s\n\t%s\n" %
+ (hex_encode(user_rng.get(42)),
+ hex_encode(user_rng.get(13)),
+ hex_encode(user_rng.get(9))))
+
+ def test_hash():
+ md5 = botan2.hash_function('MD5')
+ assert md5.output_length() == 16
+ md5.update('h')
+ md5.update('i')
+ h1 = md5.final()
+ print("md5 hash: %s (%s)\n" % (hex_encode(h1), '49f68a5c8493ec2c0bf489821c21fc3b'))
+
+ md5.update(hex_decode('f468025b'))
+ h2 = md5.final()
+ print("md5 hash: %s (%s)\n" % (hex_encode(h2), '47efd2be302a937775e93dea281b6751'))
+
+ def test_cipher():
+ for mode in ['AES-128/CTR-BE', 'Serpent/GCM', 'ChaCha20Poly1305']:
+ enc = botan2.cipher(mode, encrypt=True)
+
+ (kmin, kmax) = enc.key_length()
+ print("%s: default nonce=%d update_size=%d key_min=%d key_max=%d" %
+ (mode, enc.default_nonce_length(), enc.update_granularity(), kmin, kmax))
+
+ rng = botan2.rng()
+ iv = rng.get(enc.default_nonce_length())
+ key = rng.get(kmax)
+ pt = rng.get(21)
+
+ print(" plaintext %s (%d)" % (hex_encode(pt), len(pt)))
+
+ enc.set_key(key)
+ enc.start(iv)
+
+ update_result = enc.update('')
+ assert not update_result
+
+ ct = enc.finish(pt)
+ print(" ciphertext %s (%d)" % (hex_encode(ct), len(ct)))
+
+ dec = botan2.cipher(mode, encrypt=False)
+ dec.set_key(key)
+ dec.start(iv)
+ decrypted = dec.finish(ct)
+
+ print(" decrypted %s (%d)\n" % (hex_encode(decrypted), len(decrypted)))
+
+
+ def test_mceliece():
+ mce_priv = botan2.private_key('mce', [2960, 57], botan2.rng())
+ mce_pub = mce_priv.get_public_key()
+
+ mce_plaintext = 'mce plaintext'
+ mce_ad = 'mce AD'
+ mce_ciphertext = botan2.mceies_encrypt(mce_pub, botan2.rng(), 'ChaCha20Poly1305', mce_plaintext, mce_ad)
+
+ print("mceies len(pt)=%d len(ct)=%d" % (len(mce_plaintext), len(mce_ciphertext)))
+
+ mce_decrypt = botan2.mceies_decrypt(mce_priv, 'ChaCha20Poly1305', mce_ciphertext, mce_ad)
+ print(" mceies plaintext \'%s\' (%d)" % (mce_plaintext, len(mce_plaintext)))
+
+ # Since mceies_decrypt() returns bytes in Python3, the following line
+ # needs .decode('utf-8') to convert mce_decrypt from bytes to a
+ # text string (Unicode).
+ # You don't need to add .decode() if
+ # (a) your expected output is bytes rather than a text string, or
+ # (b) you are using Python2 rather than Python3.
+ print(" mceies decrypted \'%s\' (%d)" % (mce_decrypt.decode('utf-8'), len(mce_decrypt)))
+
+ print("mce_pub %s/SHA-1 fingerprint: %s\nEstimated strength %s bits (len %d)\n" % (
+ mce_pub.algo_name(), mce_pub.fingerprint("SHA-1"),
+ mce_pub.estimated_strength(), len(mce_pub.encoding())
+ ))
+
+ def test_rsa():
+ rsapriv = botan2.private_key('rsa', 1536, botan2.rng())
+ rsapub = rsapriv.get_public_key()
+
+ print("rsapub %s SHA-1 fingerprint: %s estimated strength %d (len %d)" % (
+ rsapub.algo_name(), rsapub.fingerprint("SHA-1"),
+ rsapub.estimated_strength(), len(rsapub.encoding())
+ ))
+
+ dec = botan2.pk_op_decrypt(rsapriv, "EME1(SHA-256)")
+ enc = botan2.pk_op_encrypt(rsapub, "EME1(SHA-256)")
+
+ sys_rng = botan2.rng()
+ symkey = sys_rng.get(32)
+ ctext = enc.encrypt(symkey, sys_rng)
+ print("ptext \'%s\' (%d)" % (hex_encode(symkey), len(symkey)))
+ print("ctext \'%s\' (%d)" % (hex_encode(ctext), len(ctext)))
+ print("decrypt \'%s\' (%d)\n" % (hex_encode(dec.decrypt(ctext)),
+ len(dec.decrypt(ctext))))
+
+ signer = botan2.pk_op_sign(rsapriv, 'EMSA4(SHA-384)')
+
+ signer.update('messa')
+ signer.update('ge')
+ sig = signer.finish(botan2.rng())
+
+ print("EMSA4(SHA-384) signature: %s" % hex_encode(sig))
+
+ verify = botan2.pk_op_verify(rsapub, 'EMSA4(SHA-384)')
+
+ verify.update('mess')
+ verify.update('age')
+ print("good sig accepted? %s" % verify.check_signature(sig))
+
+ verify.update('mess of things')
+ verify.update('age')
+ print("bad sig accepted? %s" % verify.check_signature(sig))
+
+ verify.update('message')
+ print("good sig accepted? %s\n" % verify.check_signature(sig))
+
+ def test_dh():
+ a_rng = botan2.rng('user')
+ b_rng = botan2.rng('user')
+
+ for dh_grp in ['secp256r1', 'curve25519']:
+ dh_kdf = 'KDF2(SHA-384)'.encode('utf-8')
+ a_dh_priv = botan2.private_key('ecdh', dh_grp, botan2.rng())
+ b_dh_priv = botan2.private_key('ecdh', dh_grp, botan2.rng())
+
+ a_dh = botan2.pk_op_key_agreement(a_dh_priv, dh_kdf)
+ b_dh = botan2.pk_op_key_agreement(b_dh_priv, dh_kdf)
+
+ a_dh_pub = a_dh.public_value()
+ b_dh_pub = b_dh.public_value()
+
+ a_salt = a_rng.get(8)
+ b_salt = b_rng.get(8)
+
+ print("ecdh %s pubs:\n %s (salt %s)\n %s (salt %s)\n" %
+ (dh_grp,
+ hex_encode(a_dh_pub), hex_encode(a_salt),
+ hex_encode(b_dh_pub), hex_encode(b_salt)))
+
+ a_key = a_dh.agree(b_dh_pub, 32, a_salt + b_salt)
+ b_key = b_dh.agree(a_dh_pub, 32, a_salt + b_salt)
+
+ print("ecdh %s shared:\n %s\n %s\n" %
+ (dh_grp, hex_encode(a_key), hex_encode(b_key)))
+
+ def test_certs():
+ cert = botan2.x509_cert(filename="src/tests/data/x509/ecc/CSCA.CSCA.csca-germany.1.crt")
+ print("CSCA (Germany) Certificate\nDetails:")
+ print("SHA-1 fingerprint: %s" % cert.fingerprint("SHA-1"))
+ print("Expected: 32:42:1C:C3:EC:54:D7:E9:43:EC:51:F0:19:23:BD:85:1D:F2:1B:B9")
+
+ print("Not before: %s" % cert.time_starts())
+ print("Not after: %s" % cert.time_expires())
+
+ print("Serial number: %s" % hex_encode(cert.serial_number()))
+ print("Authority Key ID: %s" % hex_encode(cert.authority_key_id()))
+ print("Subject Key ID: %s" % hex_encode(cert.subject_key_id()))
+ print("Public key bits:\n%s\n" % binascii.b2a_base64(cert.subject_public_key_bits()))
+
+ pubkey = cert.subject_public_key()
+ print("Public key algo: %s" % pubkey.algo_name())
+ print("Public key strength: %s" % pubkey.estimated_strength() + " bits")
+
+ dn_fields = ("Name", "Email", "Organization", "Organizational Unit", "Country")
+ for field in dn_fields:
+ try:
+ print("%s: %s" % (field, cert.subject_dn(field, 0)))
+ except BotanException:
+ print("Field: %s not found in certificate" % field)
+
+ print(cert.to_string())
+
+ test_version()
+ test_kdf()
+ test_pbkdf()
+ test_bcrypt()
+ test_hmac()
+ test_rng()
+ test_hash()
+ test_cipher()
+ test_mceliece()
+ test_rsa()
+ test_dh()
+ test_certs()
+
+
+def main(args=None):
+ if args is None:
+ args = sys.argv
+ test()
+
+if __name__ == '__main__':
+ sys.exit(main())