def test_ecdh(self): # pylint: disable=too-many-locals a_rng = botan2.RandomNumberGenerator('user') b_rng = botan2.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_op = botan2.PKKeyAgreement(a_priv, kdf) b_op = botan2.PKKeyAgreement(b_priv, kdf) a_pub = a_op.public_value() b_pub = b_op.public_value() salt = a_rng.get(8) + b_rng.get(8) a_key = a_op.agree(b_pub, 32, salt) b_key = b_op.agree(a_pub, 32, salt) self.assertEqual(a_key, b_key) a_pem = a_priv.to_pem() a_priv_x = a_priv.get_field('x') new_a = botan2.PrivateKey.load_ecdh(grp, a_priv_x) self.assertEqual(a_pem, new_a.to_pem())
def test_rsa(self): # pylint: disable=too-many-locals rng = botan2.RandomNumberGenerator() rsapriv = botan2.PrivateKey.create('RSA', '1024', rng) self.assertEqual(rsapriv.algo_name(), 'RSA') priv_pem = rsapriv.to_pem() priv_der = rsapriv.to_der() self.assertEqual(priv_pem[0:28], "-----BEGIN PRIVATE KEY-----\n") self.assertGreater(len(priv_pem), len(priv_der)) rsapub = rsapriv.get_public_key() self.assertEqual(rsapub.algo_name(), 'RSA') self.assertEqual(rsapub.estimated_strength(), 80) pub_pem = rsapub.to_pem() pub_der = rsapub.to_der() 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)") symkey = rng.get(32) ctext = enc.encrypt(symkey, rng) ptext = dec.decrypt(ctext) self.assertEqual(ptext, symkey) signer = botan2.PKSign(rsapriv, 'EMSA4(SHA-384)') signer.update('messa') signer.update('ge') sig = signer.finish(botan2.RandomNumberGenerator()) verify = botan2.PKVerify(rsapub, 'EMSA4(SHA-384)') verify.update('mess') verify.update('age') self.assertTrue(verify.check_signature(sig)) verify.update('mess of things') verify.update('age') self.assertFalse(verify.check_signature(sig)) verify.update('message') self.assertTrue(verify.check_signature(sig))
def test_key_crypto(self): rng = botan2.RandomNumberGenerator() priv = botan2.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) 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) 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) self.assertEqual(dec3.export(is_pem), ref_val)
def test_sm2(self): rng = botan2.RandomNumberGenerator() hash_fn = 'EMSA1(SM3)' group = 'sm2p256v1' msg = 'test message' priv = botan2.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.update(msg) signature = signer.finish(rng) verifier = botan2.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) 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) # sign empty message signature = signer.finish(rng) # verify empty message self.assertTrue(verifier.check_signature(signature))
def test_cipher(self): for mode in ['AES-128/CTR-BE', 'Serpent/GCM', 'ChaCha20Poly1305']: enc = botan2.SymmetricCipher(mode, encrypt=True) if mode == 'AES-128/CTR-BE': self.assertEqual(enc.algo_name(), 'CTR-BE(AES-128)') elif mode == 'Serpent/GCM': self.assertEqual(enc.algo_name(), 'Serpent/GCM(16)') else: self.assertEqual(enc.algo_name(), mode) (kmin, kmax) = enc.key_length() self.assertLessEqual(kmin, kmax) rng = botan2.RandomNumberGenerator() iv = rng.get(enc.default_nonce_length()) key = rng.get(kmax) pt = rng.get(21) enc.set_key(key) enc.start(iv) update_result = enc.update('') assert not update_result ct = enc.finish(pt) dec = botan2.SymmetricCipher(mode, encrypt=False) dec.set_key(key) dec.start(iv) decrypted = dec.finish(ct) self.assertEqual(decrypted, pt)
def encrypt(key, ptxt): iv = botan.RandomNumberGenerator().get(16) cipher = botan.SymmetricCipher('AES-256/GCM') cipher.set_key(key) cipher.start(iv) ctxt = cipher.finish(ptxt.encode('utf-8')) cipher.clear() return (iv, ctxt)
def test_rng(self): user_rng = botan2.RandomNumberGenerator("user") output1 = user_rng.get(32) output2 = user_rng.get(32) self.assertEqual(len(output1), 32) self.assertEqual(len(output2), 32) self.assertNotEqual(output1, output2) output3 = user_rng.get(1021) self.assertEqual(len(output3), 1021) system_rng = botan2.RandomNumberGenerator('system') user_rng.reseed_from_rng(system_rng, 256) user_rng.add_entropy('seed material...')
def test_bcrypt(self): r = botan2.RandomNumberGenerator() phash = botan2.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(botan2.check_bcrypt('test', '$2a$04$wjen1fAA.UW6UxthpKK.huyOoxvCR7ATRCVC4CBIEGVDOCtr8Oj1C'))
def test_dh(self): a_rng = botan2.RandomNumberGenerator('user') b_rng = botan2.RandomNumberGenerator('user') for dh_grp in ['secp256r1', 'curve25519']: dh_kdf = 'KDF2(SHA-384)'.encode('utf-8') a_dh_priv = botan2.PrivateKey.create('ecdh', dh_grp, a_rng) b_dh_priv = botan2.PrivateKey.create('ecdh', dh_grp, b_rng) a_dh = botan2.PKKeyAgreement(a_dh_priv, dh_kdf) b_dh = botan2.PKKeyAgreement(b_dh_priv, dh_kdf) a_dh_pub = a_dh.public_value() b_dh_pub = b_dh.public_value() salt = a_rng.get(8) + b_rng.get(8) a_key = a_dh.agree(b_dh_pub, 32, salt) b_key = b_dh.agree(a_dh_pub, 32, salt) self.assertEqual(a_key, b_key)
def test_srp6(self): identity = 'alice' password = '******' rng = botan2.RandomNumberGenerator() # Test successful authentication server = botan2.Srp6ServerSession() salt = rng.get(24) verifier = botan2.generate_srp6_verifier(identity, password, salt, 'modp/srp/1024', 'SHA-512') b = server.step1(verifier, 'modp/srp/1024', 'SHA-512', rng) (a, key_c) = botan2.srp6_client_agree(identity, password, 'modp/srp/1024', 'SHA-512', salt, b, rng) key_s = server.step2(a) self.assertEqual(key_c, key_s) # Test wrong server ephemeral try: salt = rng.get(24) b = b'BD0C6151 2C692C0C B6D041FA 01BB152D 4916A1E7 7AF46AE1 05393011 \ BAF38964 DC46A067 0DD125B9 5A981652 236F99D9 B681CBF8 7837EC99 \ 6C6DA044 53728610 D0C6DDB5 8B318885 D7D82C7F 8DEB75CE 7BD4FBAA \ 37089E6F 9C6059F3 88838E7A 00030B33 1EB76840 910440B1 B27AAEAE \ EB4012B7 D7665238 A8E3FB00 4B117B58' botan2.srp6_client_agree(identity, password, 'modp/srp/1024', 'SHA-512', salt, b, rng) except botan2.BotanException as e: self.assertEqual( str(e), "botan_srp6_client_agree failed: -1 (Invalid input): Invalid SRP parameter from server" ) # Test wrong client ephemeral try: salt = rng.get(24) verifier = botan2.generate_srp6_verifier(identity, password, salt, 'modp/srp/1024', 'SHA-512') server.step1(verifier, 'modp/srp/1024', 'SHA-512', rng) a = b'61D5E490 F6F1B795 47B0704C 436F523D D0E560F0 C64115BB 72557EC4 \ 4352E890 3211C046 92272D8B 2D1A5358 A2CF1B6E 0BFCF99F 921530EC \ 8E393561 79EAE45E 42BA92AE ACED8251 71E1E8B9 AF6D9C03 E1327F44 \ BE087EF0 6530E69F 66615261 EEF54073 CA11CF58 58F0EDFD FE15EFEA \ B349EF5D 76988A36 72FAC47B 0769447B' server.step2(a) except botan2.BotanException as e: self.assertEqual( str(e), "botan_srp6_server_session_step2 failed: -32 (Bad parameter)")
def test_check_key(self): # valid (if rather small) RSA key n = 273279220906618527352827457840955116141 e = 0x10001 rng = botan2.RandomNumberGenerator() rsapub = botan2.PublicKey.load_rsa(n, e) self.assertTrue(rsapub.check_key(rng)) # invalid rsapub = botan2.PublicKey.load_rsa(n - 1, e) self.assertFalse(rsapub.check_key(rng))
def test_mpi_random(self): rng = botan2.RandomNumberGenerator() u = botan2.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) self.assertLess(x, u) self.assertGreater(x, l)
def test_check_key(self): # valid (if rather small) RSA key n = 273279220906618527352827457840955116141 e = 0x10001 rng = botan2.RandomNumberGenerator() rsapub = botan2.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: self.assertEqual(str(e), "botan_pubkey_load_rsa failed: -1 (Invalid input)")
def test_mceliece(self): rng = botan2.RandomNumberGenerator() mce_priv = botan2.PrivateKey.create('McEliece', '2960,57', rng) mce_pub = mce_priv.get_public_key() self.assertEqual(mce_pub.estimated_strength(), 128) mce_plaintext = rng.get(16) mce_ad = rng.get(48) mce_ciphertext = botan2.mceies_encrypt(mce_pub, rng, 'ChaCha20Poly1305', mce_plaintext, mce_ad) mce_decrypt = botan2.mceies_decrypt(mce_priv, 'ChaCha20Poly1305', mce_ciphertext, mce_ad) self.assertEqual(mce_plaintext, mce_decrypt)
def test_ecdsa(self): rng = botan2.RandomNumberGenerator() hash_fn = 'EMSA1(SHA-256)' group = 'secp256r1' msg = 'test message' priv = botan2.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.update(msg) signature = signer.finish(rng) verifier = botan2.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.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) 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) # sign empty message signature = signer.finish(rng) # verify empty message self.assertTrue(verifier.check_signature(signature))
def test_mpi(self): # pylint: disable=too-many-statements z = botan2.MPI() self.assertEqual(z.bit_count(), 0) five = botan2.MPI('5') self.assertEqual(five.bit_count(), 3) big = botan2.MPI('0x85839682368923476892367235') self.assertEqual(big.bit_count(), 104) small = botan2.MPI(0xDEADBEEF) self.assertEqual(hex_encode(small.to_bytes()), "deadbeef") self.assertEqual(hex_encode(big.to_bytes()), "85839682368923476892367235") self.assertEqual(int(small), 0xDEADBEEF) self.assertEqual(int(small >> 16), 0xDEAD) small >>= 15 self.assertEqual(int(small), 0x1BD5B) small <<= 15 self.assertEqual(int(small), 0xDEAD8000) ten = botan2.MPI(10) self.assertEqual(ten, five + five) self.assertNotEqual(ten, five) self.assertLess(five, ten) self.assertLessEqual(five, ten) x = botan2.MPI(five) self.assertEqual(x, five) x += botan2.MPI(1) self.assertNotEqual(x, five) self.assertEqual(int(x * five), 30) x *= five x *= five self.assertEqual(int(x), 150) self.assertTrue(not x.is_negative()) x.flip_sign() self.assertTrue(x.is_negative()) self.assertEqual(int(x), -150) x.flip_sign() x.set_bit(0) self.assertTrue(int(x), 151) self.assertTrue(x.get_bit(0)) self.assertTrue(x.get_bit(4)) self.assertFalse(x.get_bit(6)) x.clear_bit(4) self.assertEqual(int(x), 135) rng = botan2.RandomNumberGenerator() self.assertFalse(x.is_prime(rng)) two = botan2.MPI(2) x += two self.assertTrue(x.is_prime(rng)) mod = x + two inv = x.inverse_mod(mod) self.assertEqual(int(inv), 69) self.assertEqual(int((inv * x) % mod), 1) p = inv.pow_mod(botan2.MPI(46), mod) self.assertEqual(int(p), 42)
def gen_key(bytes): return botan.RandomNumberGenerator().get(bytes)
def tag(pwd): return botan.bcrypt(pwd, botan.RandomNumberGenerator(), 11)
def test_mceliece(self): rng = botan2.RandomNumberGenerator() mce_priv = botan2.PrivateKey.create('McEliece', '2960,57', rng) mce_pub = mce_priv.get_public_key() self.assertEqual(mce_pub.estimated_strength(), 128)