1#!/usr/bin/env python 2 3""" 4(C) 2015,2017,2018,2019 Jack Lloyd 5 6Botan is released under the Simplified BSD License (see license.txt) 7""" 8 9import unittest 10import binascii 11import botan2 12 13def hex_encode(buf): 14 return binascii.hexlify(buf).decode('ascii') 15 16def hex_decode(buf): 17 return binascii.unhexlify(buf.encode('ascii')) 18 19class BotanPythonTests(unittest.TestCase): 20 # pylint: disable=too-many-public-methods,too-many-locals 21 22 def test_version(self): 23 version_str = botan2.version_string() 24 self.assertTrue(version_str.startswith('Botan ')) 25 26 self.assertEqual(botan2.version_major(), 2) 27 self.assertGreaterEqual(botan2.version_minor(), 8) 28 29 self.assertGreaterEqual(botan2.ffi_api_version(), 20180713) 30 31 def test_compare(self): 32 33 x = "1234" 34 y = "1234" 35 z = "1233" 36 self.assertTrue(botan2.const_time_compare(x, y)) 37 self.assertFalse(botan2.const_time_compare(x, z)) 38 self.assertFalse(botan2.const_time_compare(x, x + z)) 39 40 def test_block_cipher(self): 41 aes = botan2.BlockCipher("AES-128") 42 self.assertEqual(aes.algo_name(), "AES-128") 43 self.assertEqual(aes.block_size(), 16) 44 self.assertEqual(aes.minimum_keylength(), 16) 45 self.assertEqual(aes.maximum_keylength(), 16) 46 47 aes.set_key(hex_decode("000102030405060708090a0b0c0d0e0f")) 48 ct = aes.encrypt(hex_decode("00112233445566778899aabbccddeeff")) 49 50 self.assertEqual(hex_encode(ct), "69c4e0d86a7b0430d8cdb78070b4c55a") 51 52 pt = aes.decrypt(ct) 53 54 self.assertEqual(hex_encode(pt), "00112233445566778899aabbccddeeff") 55 56 def test_kdf(self): 57 58 secret = hex_decode('6FD4C3C0F38E5C7A6F83E99CD9BD') 59 salt = hex_decode('DBB986') 60 label = hex_decode('') 61 expected = hex_decode('02AEB40A3D4B66FBA540F9D4B20006F2046E0F3A029DEAB201FC692B79EB27CEF7E16069046A') 62 63 produced = botan2.kdf('KDF2(SHA-1)', secret, 38, salt, label) 64 65 self.assertEqual(hex_encode(produced), hex_encode(expected)) 66 67 def test_pbkdf(self): 68 69 (salt, iterations, pbkdf) = botan2.pbkdf('PBKDF2(SHA-1)', '', 32, 10000, hex_decode('0001020304050607')) 70 71 self.assertEqual(iterations, 10000) 72 self.assertEqual(hex_encode(pbkdf), 73 '59b2b1143b4cb1059ec58d9722fb1c72471e0d85c6f7543ba5228526375b0127') 74 75 (salt, iterations, pbkdf) = botan2.pbkdf_timed('PBKDF2(SHA-256)', 'xyz', 32, 200) 76 77 cmp_pbkdf = botan2.pbkdf('PBKDF2(SHA-256)', 'xyz', 32, iterations, salt)[2] 78 79 self.assertEqual(pbkdf, cmp_pbkdf) 80 81 def test_scrypt(self): 82 scrypt = botan2.scrypt(10, '', '', 16, 1, 1) 83 self.assertEqual(hex_encode(scrypt), "77d6576238657b203b19") 84 85 scrypt = botan2.scrypt(32, 'password', 'NaCl', 1024, 8, 16) 86 self.assertEqual(hex_encode(scrypt), "fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b373162") 87 88 def test_bcrypt(self): 89 r = botan2.RandomNumberGenerator() 90 phash = botan2.bcrypt('testing', r) 91 self.assertTrue(isinstance(phash, str)) 92 self.assertTrue(phash.startswith("$2a$")) 93 94 self.assertTrue(botan2.check_bcrypt('testing', phash)) 95 self.assertFalse(botan2.check_bcrypt('live fire', phash)) 96 97 self.assertTrue(botan2.check_bcrypt('test', '$2a$04$wjen1fAA.UW6UxthpKK.huyOoxvCR7ATRCVC4CBIEGVDOCtr8Oj1C')) 98 99 def test_mac(self): 100 101 hmac = botan2.MsgAuthCode('HMAC(SHA-256)') 102 self.assertEqual(hmac.algo_name(), 'HMAC(SHA-256)') 103 self.assertEqual(hmac.minimum_keylength(), 0) 104 self.assertEqual(hmac.maximum_keylength(), 4096) 105 hmac.set_key(hex_decode('0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20')) 106 hmac.update(hex_decode('616263')) 107 108 expected = hex_decode('A21B1F5D4CF4F73A4DD939750F7A066A7F98CC131CB16A6692759021CFAB8181') 109 produced = hmac.final() 110 111 self.assertEqual(hex_encode(expected), hex_encode(produced)) 112 113 def test_rng(self): 114 user_rng = botan2.RandomNumberGenerator("user") 115 116 output1 = user_rng.get(32) 117 output2 = user_rng.get(32) 118 119 self.assertEqual(len(output1), 32) 120 self.assertEqual(len(output2), 32) 121 self.assertNotEqual(output1, output2) 122 123 output3 = user_rng.get(1021) 124 self.assertEqual(len(output3), 1021) 125 126 system_rng = botan2.RandomNumberGenerator('system') 127 128 user_rng.reseed_from_rng(system_rng, 256) 129 130 user_rng.add_entropy('seed material...') 131 132 def test_hash(self): 133 134 try: 135 _h = botan2.HashFunction('NoSuchHash') 136 except botan2.BotanException as e: 137 self.assertEqual(str(e), "botan_hash_init failed: -40 (Not implemented)") 138 139 sha256 = botan2.HashFunction('SHA-256') 140 self.assertEqual(sha256.algo_name(), 'SHA-256') 141 self.assertEqual(sha256.output_length(), 32) 142 self.assertEqual(sha256.block_size(), 64) 143 sha256.update('ignore this please') 144 sha256.clear() 145 sha256.update('a') 146 hash1 = sha256.final() 147 148 self.assertEqual(hex_encode(hash1), "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb") 149 150 sha256.update(hex_decode('61')) 151 sha256_2 = sha256.copy_state() 152 sha256.update(hex_decode('6263')) 153 h2 = sha256.final() 154 self.assertEqual(hex_encode(h2), "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad") 155 156 self.assertEqual(hex_encode(sha256_2.final()), hex_encode(hash1)) 157 158 def test_cipher(self): 159 for mode in ['AES-128/CTR-BE', 'Serpent/GCM', 'ChaCha20Poly1305']: 160 enc = botan2.SymmetricCipher(mode, encrypt=True) 161 162 if mode == 'AES-128/CTR-BE': 163 self.assertEqual(enc.algo_name(), 'CTR-BE(AES-128)') 164 elif mode == 'Serpent/GCM': 165 self.assertEqual(enc.algo_name(), 'Serpent/GCM(16)') 166 else: 167 self.assertEqual(enc.algo_name(), mode) 168 169 (kmin, kmax) = enc.key_length() 170 171 self.assertLessEqual(kmin, kmax) 172 173 rng = botan2.RandomNumberGenerator() 174 iv = rng.get(enc.default_nonce_length()) 175 key = rng.get(kmax) 176 pt = rng.get(21) 177 178 enc.set_key(key) 179 enc.start(iv) 180 181 update_result = enc.update('') 182 assert not update_result 183 184 ct = enc.finish(pt) 185 186 dec = botan2.SymmetricCipher(mode, encrypt=False) 187 dec.set_key(key) 188 dec.start(iv) 189 decrypted = dec.finish(ct) 190 191 self.assertEqual(decrypted, pt) 192 193 194 def test_mceliece(self): 195 rng = botan2.RandomNumberGenerator() 196 mce_priv = botan2.PrivateKey.create('McEliece', '2960,57', rng) 197 mce_pub = mce_priv.get_public_key() 198 self.assertEqual(mce_pub.estimated_strength(), 128) 199 200 mce_plaintext = rng.get(16) 201 mce_ad = rng.get(48) 202 mce_ciphertext = botan2.mceies_encrypt(mce_pub, rng, 'ChaCha20Poly1305', mce_plaintext, mce_ad) 203 204 mce_decrypt = botan2.mceies_decrypt(mce_priv, 'ChaCha20Poly1305', mce_ciphertext, mce_ad) 205 206 self.assertEqual(mce_plaintext, mce_decrypt) 207 208 def test_rsa_load_store(self): 209 210 rsa_priv_pem = """-----BEGIN PRIVATE KEY----- 211MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALWtiBjcofJW/4+r 212CIjQZn2V3yCYsNIBpMdVkNPr36FZ3ZHGSv2ggmCe+IWy0fTcBVyP+fo3HC8zmOC2 213EsYDFRExyB2zIsjRXlPrVrTfcyXwUEaInLJQId5CguFrmyj1y7K43ezg+OTop39n 214TyaukrciCSCh++Q/UQOanHnR8ctrAgMBAAECgYBPfKySgBmk31ZyA7k4rsFgye01 215JEkcoNZ41iGG7ujJffl4maLew9a3MmZ2jI3azVbVMDMFPA5rQm5tRowBMYEJ5oBc 216LP4AP41Lujfa+vua6l3t94bAV+CufZiY0297FcPbGqNu+xSQ2Bol2uHh9mrcgQUs 217fevA50KOLR9hv4zH6QJBAPCOKiExONtVhJn8qVPCBlJ8Vjjnt9Uno5EzMBAKMbZi 218OySkGwo9/9LUWO03r7tjrGSy5jJk+iOrcLeDl6zETfkCQQDBV6PpD/3ccQ1IfWcw 219jG8yik0bIuXgrD0uW4g8Cvj+05wrv7RYPHuFtj3Rtb94YjtgYn7QvjH7y88XmTC4 2202k2DAkEA4E9Ae7kBUoz42/odDswyxwHICMIRyoJu5Ht9yscmufH5Ql6AFFnhzf9S 221eMjfZfY4j6G+Q6mjElXQAl+DtIdMSQJBAJzdMkuBggI8Zv6NYA9voThsJSsDIWcr 22212epM9sjO+nkXizQmM2OJNnThkyDHRna+Tm2MBXEemFEdn06+ODBnWkCQQChAbG4 223255RiCuYdrfiTPF/WLtvRyGd1LRwHcYIW4mJFPzxYAMTwQKbppLAnxw73vyef/zC 2242BgXEW02tjRBtgZ+ 225-----END PRIVATE KEY----- 226""" 227 228 rsa_pub_pem = """-----BEGIN PUBLIC KEY----- 229MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1rYgY3KHyVv+PqwiI0GZ9ld8g 230mLDSAaTHVZDT69+hWd2Rxkr9oIJgnviFstH03AVcj/n6NxwvM5jgthLGAxURMcgd 231syLI0V5T61a033Ml8FBGiJyyUCHeQoLha5so9cuyuN3s4Pjk6Kd/Z08mrpK3Igkg 232ofvkP1EDmpx50fHLawIDAQAB 233-----END PUBLIC KEY----- 234""" 235 236 rsapriv = botan2.PrivateKey.load(rsa_priv_pem) 237 238 self.assertEqual(rsapriv.to_pem(), rsa_priv_pem) 239 240 rsapub = rsapriv.get_public_key() 241 self.assertEqual(rsapub.to_pem(), rsa_pub_pem) 242 243 rsapub = botan2.PublicKey.load(rsa_pub_pem) 244 self.assertEqual(rsapub.to_pem(), rsa_pub_pem) 245 246 n = 0xB5AD8818DCA1F256FF8FAB0888D0667D95DF2098B0D201A4C75590D3EBDFA159DD91C64AFDA082609EF885B2D1F4DC055C8FF9FA371C2F3398E0B612C603151131C81DB322C8D15E53EB56B4DF7325F05046889CB25021DE4282E16B9B28F5CBB2B8DDECE0F8E4E8A77F674F26AE92B7220920A1FBE43F51039A9C79D1F1CB6B # pylint: disable=line-too-long 247 e = 0x10001 248 249 rsapub2 = botan2.PublicKey.load_rsa(n, e) 250 self.assertEqual(rsapub2.to_pem(), rsa_pub_pem) 251 252 self.assertEqual(rsapub2.get_field("n"), n) 253 self.assertEqual(rsapub2.get_field("e"), e) 254 255 def test_key_crypto(self): 256 rng = botan2.RandomNumberGenerator() 257 priv = botan2.PrivateKey.create('RSA', '1024', rng) 258 passphrase = "super secret tell noone" 259 260 for is_pem in [True, False]: 261 ref_val = priv.export(is_pem) 262 263 enc1 = priv.export_encrypted(passphrase, rng, True, msec=10) 264 dec1 = botan2.PrivateKey.load(enc1, passphrase) 265 self.assertEqual(dec1.export(is_pem), ref_val) 266 267 pem2 = priv.export_encrypted(passphrase, rng, True, msec=10, cipher="AES-128/SIV") 268 dec2 = botan2.PrivateKey.load(pem2, passphrase) 269 self.assertEqual(dec2.export(is_pem), ref_val) 270 271 pem3 = priv.export_encrypted(passphrase, rng, True, msec=10, cipher="AES-128/GCM", pbkdf="Scrypt") 272 dec3 = botan2.PrivateKey.load(pem3, passphrase) 273 self.assertEqual(dec3.export(is_pem), ref_val) 274 275 def test_check_key(self): 276 # valid (if rather small) RSA key 277 n = 273279220906618527352827457840955116141 278 e = 0x10001 279 280 rng = botan2.RandomNumberGenerator() 281 282 rsapub = botan2.PublicKey.load_rsa(n, e) 283 self.assertTrue(rsapub.check_key(rng)) 284 285 # invalid 286 try: 287 rsapub = botan2.PublicKey.load_rsa(n - 1, e) 288 except botan2.BotanException as e: 289 self.assertEqual(str(e), "botan_pubkey_load_rsa failed: -1 (Invalid input)") 290 291 def test_rsa(self): 292 # pylint: disable=too-many-locals 293 rng = botan2.RandomNumberGenerator() 294 rsapriv = botan2.PrivateKey.create('RSA', '1024', rng) 295 self.assertEqual(rsapriv.algo_name(), 'RSA') 296 297 priv_pem = rsapriv.to_pem() 298 priv_der = rsapriv.to_der() 299 300 self.assertEqual(priv_pem[0:28], "-----BEGIN PRIVATE KEY-----\n") 301 self.assertGreater(len(priv_pem), len(priv_der)) 302 303 rsapub = rsapriv.get_public_key() 304 self.assertEqual(rsapub.algo_name(), 'RSA') 305 self.assertEqual(rsapub.estimated_strength(), 80) 306 307 pub_pem = rsapub.to_pem() 308 pub_der = rsapub.to_der() 309 310 self.assertEqual(pub_pem[0:27], "-----BEGIN PUBLIC KEY-----\n") 311 self.assertGreater(len(pub_pem), len(pub_der)) 312 313 enc = botan2.PKEncrypt(rsapub, "OAEP(SHA-256)") 314 dec = botan2.PKDecrypt(rsapriv, "OAEP(SHA-256)") 315 316 symkey = rng.get(32) 317 ctext = enc.encrypt(symkey, rng) 318 319 ptext = dec.decrypt(ctext) 320 321 self.assertEqual(ptext, symkey) 322 323 signer = botan2.PKSign(rsapriv, 'EMSA4(SHA-384)') 324 325 signer.update('messa') 326 signer.update('ge') 327 sig = signer.finish(botan2.RandomNumberGenerator()) 328 329 verify = botan2.PKVerify(rsapub, 'EMSA4(SHA-384)') 330 331 verify.update('mess') 332 verify.update('age') 333 self.assertTrue(verify.check_signature(sig)) 334 335 verify.update('mess of things') 336 verify.update('age') 337 self.assertFalse(verify.check_signature(sig)) 338 339 verify.update('message') 340 self.assertTrue(verify.check_signature(sig)) 341 342 def test_ecdsa(self): 343 rng = botan2.RandomNumberGenerator() 344 345 hash_fn = 'EMSA1(SHA-256)' 346 group = 'secp256r1' 347 msg = 'test message' 348 349 priv = botan2.PrivateKey.create('ECDSA', group, rng) 350 pub = priv.get_public_key() 351 self.assertEqual(pub.get_field('public_x'), priv.get_field('public_x')) 352 self.assertEqual(pub.get_field('public_y'), priv.get_field('public_y')) 353 354 signer = botan2.PKSign(priv, hash_fn, True) 355 signer.update(msg) 356 signature = signer.finish(rng) 357 358 verifier = botan2.PKVerify(pub, hash_fn) 359 verifier.update(msg) 360 #fails because DER/not-DER mismatch 361 self.assertFalse(verifier.check_signature(signature)) 362 363 verifier = botan2.PKVerify(pub, hash_fn, True) 364 verifier.update(msg) 365 self.assertTrue(verifier.check_signature(signature)) 366 367 pub_x = pub.get_field('public_x') 368 pub_y = priv.get_field('public_y') 369 pub2 = botan2.PublicKey.load_ecdsa(group, pub_x, pub_y) 370 verifier = botan2.PKVerify(pub2, hash_fn, True) 371 verifier.update(msg) 372 self.assertTrue(verifier.check_signature(signature)) 373 374 priv2 = botan2.PrivateKey.load_ecdsa(group, priv.get_field('x')) 375 signer = botan2.PKSign(priv2, hash_fn, True) 376 # sign empty message 377 signature = signer.finish(rng) 378 379 # verify empty message 380 self.assertTrue(verifier.check_signature(signature)) 381 382 def test_sm2(self): 383 rng = botan2.RandomNumberGenerator() 384 385 hash_fn = 'EMSA1(SM3)' 386 group = 'sm2p256v1' 387 msg = 'test message' 388 389 priv = botan2.PrivateKey.create('SM2', group, rng) 390 pub = priv.get_public_key() 391 self.assertEqual(pub.get_field('public_x'), priv.get_field('public_x')) 392 self.assertEqual(pub.get_field('public_y'), priv.get_field('public_y')) 393 394 signer = botan2.PKSign(priv, hash_fn) 395 signer.update(msg) 396 signature = signer.finish(rng) 397 398 verifier = botan2.PKVerify(pub, hash_fn) 399 verifier.update(msg) 400 self.assertTrue(verifier.check_signature(signature)) 401 402 pub_x = pub.get_field('public_x') 403 pub_y = priv.get_field('public_y') 404 pub2 = botan2.PublicKey.load_sm2(group, pub_x, pub_y) 405 verifier = botan2.PKVerify(pub2, hash_fn) 406 verifier.update(msg) 407 self.assertTrue(verifier.check_signature(signature)) 408 409 priv2 = botan2.PrivateKey.load_sm2(group, priv.get_field('x')) 410 signer = botan2.PKSign(priv2, hash_fn) 411 # sign empty message 412 signature = signer.finish(rng) 413 414 # verify empty message 415 self.assertTrue(verifier.check_signature(signature)) 416 417 def test_ecdh(self): 418 # pylint: disable=too-many-locals 419 a_rng = botan2.RandomNumberGenerator('user') 420 b_rng = botan2.RandomNumberGenerator('user') 421 422 kdf = 'KDF2(SHA-384)' 423 424 for grp in ['secp256r1', 'secp384r1', 'brainpool256r1']: 425 a_priv = botan2.PrivateKey.create('ECDH', grp, a_rng) 426 b_priv = botan2.PrivateKey.create('ECDH', grp, b_rng) 427 428 a_op = botan2.PKKeyAgreement(a_priv, kdf) 429 b_op = botan2.PKKeyAgreement(b_priv, kdf) 430 431 a_pub = a_op.public_value() 432 b_pub = b_op.public_value() 433 434 salt = a_rng.get(8) + b_rng.get(8) 435 436 a_key = a_op.agree(b_pub, 32, salt) 437 b_key = b_op.agree(a_pub, 32, salt) 438 439 self.assertEqual(a_key, b_key) 440 441 a_pem = a_priv.to_pem() 442 443 a_priv_x = a_priv.get_field('x') 444 445 new_a = botan2.PrivateKey.load_ecdh(grp, a_priv_x) 446 447 self.assertEqual(a_pem, new_a.to_pem()) 448 449 def test_certs(self): 450 # pylint: disable=too-many-statements 451 cert = botan2.X509Cert(filename="src/tests/data/x509/ecc/CSCA.CSCA.csca-germany.1.crt") 452 pubkey = cert.subject_public_key() 453 454 self.assertEqual(pubkey.algo_name(), 'ECDSA') 455 self.assertEqual(pubkey.estimated_strength(), 112) 456 457 self.assertEqual(cert.fingerprint("SHA-1"), 458 "32:42:1C:C3:EC:54:D7:E9:43:EC:51:F0:19:23:BD:85:1D:F2:1B:B9") 459 460 self.assertEqual(hex_encode(cert.serial_number()), "01") 461 self.assertEqual(hex_encode(cert.authority_key_id()), 462 "0096452de588f966c4ccdf161dd1f3f5341b71e7") 463 464 self.assertEqual(cert.subject_dn('Name', 0), 'csca-germany') 465 self.assertEqual(cert.subject_dn('Email', 0), 'csca-germany@bsi.bund.de') 466 self.assertEqual(cert.subject_dn('Organization', 0), 'bund') 467 self.assertEqual(cert.subject_dn('Organizational Unit', 0), 'bsi') 468 self.assertEqual(cert.subject_dn('Country', 0), 'DE') 469 470 self.assertTrue(cert.to_string().startswith("Version: 3")) 471 472 self.assertEqual(cert.issuer_dn('Name', 0), 'csca-germany') 473 self.assertEqual(cert.issuer_dn('Organization', 0), 'bund') 474 self.assertEqual(cert.issuer_dn('Organizational Unit', 0), 'bsi') 475 self.assertEqual(cert.issuer_dn('Country', 0), 'DE') 476 477 self.assertTrue(cert.hostname_match('csca-germany')) 478 self.assertFalse(cert.hostname_match('csca-slovakia')) 479 480 self.assertEqual(cert.not_before(), 1184858838) 481 self.assertEqual(cert.not_after(), 1831907880) 482 483 self.assertTrue(cert.allowed_usage(["CRL_SIGN", "KEY_CERT_SIGN"])) 484 self.assertTrue(cert.allowed_usage(["KEY_CERT_SIGN"])) 485 self.assertFalse(cert.allowed_usage(["DIGITAL_SIGNATURE"])) 486 self.assertFalse(cert.allowed_usage(["DIGITAL_SIGNATURE", "CRL_SIGN"])) 487 488 root = botan2.X509Cert("src/tests/data/x509/nist/root.crt") 489 490 int09 = botan2.X509Cert("src/tests/data/x509/nist/test09/int.crt") 491 end09 = botan2.X509Cert("src/tests/data/x509/nist/test09/end.crt") 492 self.assertEqual(end09.verify([int09], [root]), 2001) 493 494 end04 = botan2.X509Cert("src/tests/data/x509/nist/test04/end.crt") 495 int04_1 = botan2.X509Cert("src/tests/data/x509/nist/test04/int1.crt") 496 int04_2 = botan2.X509Cert("src/tests/data/x509/nist/test04/int2.crt") 497 self.assertEqual(end04.verify([int04_1, int04_2], [], "src/tests/data/x509/nist/", required_strength=80), 0) 498 self.assertEqual(end04.verify([int04_1, int04_2], [], required_strength=80), 3000) 499 self.assertEqual(end04.verify([int04_1, int04_2], [root], required_strength=80, hostname="User1-CP.02.01"), 0) 500 self.assertEqual(end04.verify([int04_1, int04_2], [root], required_strength=80, hostname="invalid"), 4008) 501 self.assertEqual(end04.verify([int04_1, int04_2], [root], required_strength=80, reference_time=1), 2000) 502 503 self.assertEqual(botan2.X509Cert.validation_status(0), 'Verified') 504 self.assertEqual(botan2.X509Cert.validation_status(3000), 'Certificate issuer not found') 505 self.assertEqual(botan2.X509Cert.validation_status(4008), 'Certificate does not match provided name') 506 507 rootcrl = botan2.X509CRL("src/tests/data/x509/nist/root.crl") 508 509 end01 = botan2.X509Cert("src/tests/data/x509/nist/test01/end.crt") 510 self.assertEqual(end01.verify([], [root], required_strength=80, crls=[rootcrl]), 0) 511 512 int20 = botan2.X509Cert("src/tests/data/x509/nist/test20/int.crt") 513 end20 = botan2.X509Cert("src/tests/data/x509/nist/test20/end.crt") 514 int20crl = botan2.X509CRL("src/tests/data/x509/nist/test20/int.crl") 515 516 self.assertEqual(end20.verify([int20], [root], required_strength=80, crls=[int20crl, rootcrl]), 5000) 517 self.assertEqual(botan2.X509Cert.validation_status(5000), 'Certificate is revoked') 518 519 int21 = botan2.X509Cert("src/tests/data/x509/nist/test21/int.crt") 520 end21 = botan2.X509Cert("src/tests/data/x509/nist/test21/end.crt") 521 int21crl = botan2.X509CRL("src/tests/data/x509/nist/test21/int.crl") 522 self.assertEqual(end21.verify([int21], [root], required_strength=80, crls=[int21crl, rootcrl]), 5000) 523 524 self.assertTrue(int20.is_revoked(rootcrl)) 525 self.assertFalse(int04_1.is_revoked(rootcrl)) 526 self.assertTrue(end21.is_revoked(int21crl)) 527 528 529 def test_mpi(self): 530 # pylint: disable=too-many-statements,too-many-locals 531 z = botan2.MPI() 532 self.assertEqual(z.bit_count(), 0) 533 five = botan2.MPI('5') 534 self.assertEqual(five.bit_count(), 3) 535 big = botan2.MPI('0x85839682368923476892367235') 536 self.assertEqual(big.bit_count(), 104) 537 small = botan2.MPI(0xDEADBEEF) 538 radix = botan2.MPI("DEADBEEF", 16) 539 540 self.assertEqual(hex_encode(small.to_bytes()), "deadbeef") 541 self.assertEqual(hex_encode(big.to_bytes()), "85839682368923476892367235") 542 543 self.assertEqual(int(small), 0xDEADBEEF) 544 self.assertEqual(int(radix), int(small)) 545 546 self.assertEqual(int(small >> 16), 0xDEAD) 547 548 small >>= 15 549 550 self.assertEqual(int(small), 0x1BD5B) 551 552 small <<= 15 553 554 self.assertEqual(int(small), 0xDEAD8000) 555 556 ten = botan2.MPI(10) 557 558 self.assertEqual(ten, five + five) 559 self.assertNotEqual(ten, five) 560 self.assertLess(five, ten) 561 self.assertLessEqual(five, ten) 562 563 x = botan2.MPI(five) 564 565 self.assertEqual(x, five) 566 567 x += botan2.MPI(1) 568 self.assertNotEqual(x, five) 569 570 self.assertEqual(int(x * five), 30) 571 572 x *= five 573 x *= five 574 self.assertEqual(int(x), 150) 575 576 self.assertTrue(not x.is_negative()) 577 578 x.flip_sign() 579 self.assertTrue(x.is_negative()) 580 self.assertEqual(int(x), -150) 581 582 x.flip_sign() 583 584 x.set_bit(0) 585 self.assertTrue(int(x), 151) 586 self.assertTrue(x.get_bit(0)) 587 self.assertTrue(x.get_bit(4)) 588 self.assertFalse(x.get_bit(6)) 589 590 x.clear_bit(4) 591 self.assertEqual(int(x), 135) 592 593 rng = botan2.RandomNumberGenerator() 594 self.assertFalse(x.is_prime(rng)) 595 596 two = botan2.MPI(2) 597 598 x += two 599 self.assertTrue(x.is_prime(rng)) 600 601 mod = x + two 602 603 inv = x.inverse_mod(mod) 604 self.assertEqual(int(inv), 69) 605 self.assertEqual(int((inv * x) % mod), 1) 606 607 p = inv.pow_mod(botan2.MPI(46), mod) 608 self.assertEqual(int(p), 42) 609 610 one = botan2.MPI(1) 611 twelve = botan2.MPI("C", 16) 612 eight = botan2.MPI(8) 613 614 mul = twelve.mod_mul(eight, inv) 615 self.assertEqual(int(mul), 27) 616 617 gcd = one.gcd(one) 618 self.assertEqual(one, gcd) 619 gcd = one.gcd(twelve) 620 self.assertEqual(one, gcd) 621 gcd = twelve.gcd(eight) 622 self.assertEqual(4, int(gcd)) 623 624 def test_mpi_random(self): 625 rng = botan2.RandomNumberGenerator() 626 627 u = botan2.MPI.random(rng, 512) 628 self.assertEqual(u.bit_count(), 512) 629 630 l = u >> 32 631 self.assertEqual(l.bit_count(), 512-32) 632 633 for _i in range(10): 634 x = botan2.MPI.random_range(rng, l, u) 635 self.assertLess(x, u) 636 self.assertGreater(x, l) 637 638 def test_fpe(self): 639 640 modulus = botan2.MPI('1000000000') 641 key = b'001122334455' 642 643 fpe = botan2.FormatPreservingEncryptionFE1(modulus, key) 644 645 value = botan2.MPI('392910392') 646 tweak = 'tweak value' 647 648 ctext = fpe.encrypt(value, tweak) 649 650 ptext = fpe.decrypt(ctext, tweak) 651 652 self.assertEqual(value, ptext) 653 654 def test_keywrap(self): 655 key = hex_decode('00112233445566778899aabbccddeeff') 656 kek = hex_decode('000102030405060708090a0b0c0d0e0f') 657 658 wrapped = botan2.nist_key_wrap(kek, key) 659 self.assertEqual(hex_encode(wrapped), '1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5') 660 661 self.assertEqual(len(wrapped), 16+8) 662 unwrapped = botan2.nist_key_unwrap(kek, wrapped) 663 self.assertEqual(hex_encode(unwrapped), '00112233445566778899aabbccddeeff') 664 665 def test_hotp(self): 666 667 hotp = botan2.HOTP(b'12345678901234567890') 668 669 self.assertEqual(hotp.generate(0), 755224) 670 self.assertEqual(hotp.generate(1), 287082) 671 self.assertEqual(hotp.generate(9), 520489) 672 673 self.assertEqual(hotp.check(520489, 8), (False, 8)) 674 self.assertEqual(hotp.check(520489, 8, 1), (True, 10)) 675 self.assertEqual(hotp.check(520489, 7, 2), (True, 10)) 676 self.assertEqual(hotp.check(520489, 0, 9), (True, 10)) 677 678 def test_totp(self): 679 680 totp = botan2.TOTP(b'12345678901234567890', digest="SHA-1", digits=8) 681 682 self.assertEqual(totp.generate(59), 94287082) 683 self.assertEqual(totp.generate(1111111109), 7081804) 684 self.assertEqual(totp.generate(1111111111), 14050471) 685 self.assertEqual(totp.generate(1234567890), 89005924) 686 self.assertEqual(totp.generate(1234567890), 89005924) 687 self.assertEqual(totp.generate(2000000000), 69279037) 688 689 self.assertTrue(totp.check(7081804, 1111111109)) 690 self.assertTrue(totp.check(7081804, 1111111109 - 29)) 691 self.assertFalse(totp.check(7081804, 1111111109 + 1)) 692 self.assertTrue(totp.check(7081804, 1111111109 + 30, 1)) 693 694if __name__ == '__main__': 695 unittest.main() 696