def test_create_rsa_key_no_overwrite(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): with open("broken_rsa.key", "wb"): pass self._run_x509sak(["genbrokenrsa"], on_failure="exception-nopause", success_return_codes=[1])
def test_extract_broken_pem1(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir( tempdir), tempfile.NamedTemporaryFile(prefix="scrapeme_", suffix=".bin") as f: self._prepare_file(f, [100, b"-----BEGIN XYZ", 100]) self._run_x509sak(["scrape", "--extract-nested", f.name]) self.assertEqual(len(os.listdir("scrape/")), 0)
def test_included_types(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir( tempdir), tempfile.NamedTemporaryFile(prefix="scrapeme_", suffix=".bin") as f: crt = self._load_crt("ok/johannes-bauer.com") self._prepare_file(f, [100, crt.der_data, 100]) self._run_x509sak(["scrape", "--include-dertype", "crt", f.name]) self.assertEqual(len(os.listdir("scrape/")), 1) shutil.rmtree("scrape") self._run_x509sak([ "scrape", "--include-dertype", "crt", "--exclude-dertype", "crt", f.name ]) self.assertEqual(len(os.listdir("scrape/")), 0) shutil.rmtree("scrape") self._run_x509sak( ["scrape", "--include-dertype", "pubkey", f.name]) self.assertEqual(len(os.listdir("scrape/")), 1) shutil.rmtree("scrape") self._run_x509sak( ["scrape", "--include-dertype", "ec_key", f.name]) self.assertEqual(len(os.listdir("scrape/")), 0) shutil.rmtree("scrape")
def test_invalid_stepping(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): self.assertIn( b"greater or equal", self._run_x509sak( ["genbrokenrsa", "--bitlen", "128", "--q-stepping", "0"], success_return_codes=[1]).stderr)
def test_sign_csr(self): with SoftHSMInstance() as hsm, tempfile.TemporaryDirectory( ) as tempdir, WorkDir(tempdir): key_name = hsm.keygen(key_id=1, key_label="CA_key", key_spec="EC:secp256r1") # Create root certificate with key in SoftHSM self._run_x509sak([ "createca", "-s", "/CN=Root CA with key in HSM", "--pkcs11-so-search", hsm.so_search_path, "--pkcs11-module", "libsofthsm2.so", "--hardware-key", key_name, "root_ca" ], env=hsm.env) # Then create child CSR self._run_x509sak(["createcsr", "client.key", "client.csr"], env=hsm.env) # Finally, sign the child certificate self._run_x509sak([ "signcsr", "-s", "/CN=Child Cert", "-t", "tls-client", "root_ca", "client.csr", "client.crt" ], env=hsm.env) # Verify the child certificate is valid SubprocessExecutor([ "openssl", "verify", "-check_ss_sig", "-CAfile", "root_ca/CA.crt", "client.crt" ]).run()
def test_invalid_close_q(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): self.assertIn( b"even modulus bitlength", self._run_x509sak( ["genbrokenrsa", "--bitlen", "129", "--close-q"], success_return_codes=[1]).stderr)
def ca_sign_csr(cls, ca_manager, csr_filename, crt_filename, subject_dn, validity_days, x509_extensions=None, subject_alternative_dns_names=None, subject_alternative_ip_addresses=None, signing_hash=None): csr_absfilename = os.path.realpath(csr_filename) crt_absfilename = os.path.realpath(crt_filename) openssl_config = cls.__get_config( private_key_storage=ca_manager.private_key_storage, x509_extensions=x509_extensions, subject_alternative_dns_names=subject_alternative_dns_names, subject_alternative_ip_addresses=subject_alternative_ip_addresses) with WorkDir(ca_manager.capath), tempfile.NamedTemporaryFile( "w", prefix="config_", suffix=".cnf") as config_file: openssl_config.write_to(config_file.name) cmd = [ cls._EXECUTABLE, "ca", "-utf8", "-in", csr_absfilename, "-batch", "-notext", "-out", crt_absfilename ] cmd += cls._privkey_option(ca_manager.private_key_storage, key_option="keyfile") if subject_dn is not None: cmd += ["-subj", subject_dn] if validity_days is not None: cmd += ["-days", str(validity_days)] if signing_hash is not None: cmd += ["-md", signing_hash] SubprocessExecutor(cmd, env={ "OPENSSL_CONF": config_file.name }).run()
def test_gcd_n_phi_n_try_again_q(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): PrimeDB().add(0x3f25fbdd02563798a3ee15, 0x3c1e53497fe2626fa6d389, 0x3bf7ae07a1892c3881ee69).write() result = self._run_x509sak( ["genbrokenrsa", "--bitlen", "259", "--gcd-n-phi-n", "-vv"], success_return_codes=[1]) self.assertIn(b"exhausted", result.stderr)
def test_retry_q(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): PrimeDB().add(0xd7627ea571293d6bd1dc8d4664bc6ab1).write() result = self._run_x509sak([ "genbrokenrsa", "--bitlen", "256", "-v", "--close-q", "--public-exponent", "3", "-vv" ]) self.assertIn(b"retrying", result.stderr)
def test_subject_info(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): self._run_x509sak([ "createca", "-s", "/CN=Elem00/OU=Elem01/C=DE/SN=Elem02/GN=Elem03/emailAddress=Elem04/title=Elem05/L=Elem06/stateOrProvinceName=Elem07/pseudonym=Elem08", "root_ca" ]) output = SubprocessExecutor([ "openssl", "x509", "-subject", "-noout", "-in", "root_ca/CA.crt" ]).run().stdout self.assertIn(b"DE", output) for eid in range(9): element = ("Elem%02d" % (eid)).encode("ascii") self.assertIn(element, output)
def test_create_nested_ca(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): self._run_x509sak([ "createca", "this/is/a/root_ca" ]) output = SubprocessExecutor([ "openssl", "x509", "-text", "-in", "this/is/a/root_ca/CA.crt" ]).run().stdout self.assertIn(b"--BEGIN CERTIFICATE--", output) self.assertIn(b"--END CERTIFICATE--", output) self.assertIn(b"id-ecPublicKey", output) SubprocessExecutor([ "openssl", "ec", "-in", "this/is/a/root_ca/CA.key" ]).run()
def ca_revoke_crt(cls, ca_manager, crt_filename): crt_absfilename = os.path.realpath(crt_filename) openssl_config = cls.__get_config(private_key_storage = ca_manager.private_key_storage) with WorkDir(ca_manager.capath), tempfile.NamedTemporaryFile("w", prefix = "config_", suffix = ".cnf") as config_file: openssl_config.write_to(config_file.name) cmd = [ cls._EXECUTABLE, "ca", "-revoke", crt_absfilename ] cmd += cls._privkey_option(ca_manager.private_key_storage, key_option = "keyfile") SubprocessExecutor(cmd, env = { "OPENSSL_CONF": config_file.name }).run()
def test_der_input(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): crt = self._load_crt("ok/johannes-bauer-root") crt.write_derfile("root.der") output = self._run_x509sak([ "buildchain", "--inform", "der", "root.der" ]).stdout self.assertOcurrences(output, b"-----BEGIN CERTIFICATE-----", 1) crts = X509Certificate.from_pem_data(output.decode("ascii")) self.assertEqual(crts[0].subject.rfc2253_str, "CN=DST Root CA X3,O=Digital Signature Trust Co.")
def test_32k_cert(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir( tempdir), tempfile.NamedTemporaryFile(prefix="scrapeme_", suffix=".bin") as f: crt_der = self._load_data("certs/broken/length_32k.der.gz") self.assertEqual(len(crt_der), 32 * 1024) self._prepare_file(f, [100, crt_der, 100]) self._run_x509sak(["scrape", f.name]) self.assertEqual(len(os.listdir("scrape/")), 1)
def test_extract_broken_pem2(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir( tempdir), tempfile.NamedTemporaryFile(prefix="scrapeme_", suffix=".bin") as f: crt = self._load_crt("ok/johannes-bauer.com") self._prepare_file( f, [100, crt.to_pem_data().encode("ascii")[:-10], 100]) self._run_x509sak(["scrape", "--extract-nested", f.name]) self.assertEqual(len(os.listdir("scrape/")), 0)
def test_create_close_q_rsa_key(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): PrimeDB().add(0xd7627ea571293d6bd1dc8d4664bc6ab1).write() self._run_x509sak(["genbrokenrsa", "--bitlen", "256", "--close-q"]) key = RSAPrivateKey.read_pemfile("broken_rsa.key")[0] self.assertEqual(key.n.bit_length(), 256) self.assertEqual(key.p, 0xd7627ea571293d6bd1dc8d4664bc6ab1) self.assertEqual(key.q, key.p + 94) key.check_integrity()
def test_dont_overwrite_dir_except_force(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): os.makedirs("root_ca") with open("root_ca/foobar", "wb"): pass self._run_x509sak([ "createca", "root_ca" ], success_return_codes = [ 1 ]) self.assertTrue(os.path.isfile("root_ca/foobar")) self._run_x509sak([ "createca", "--force", "root_ca" ]) self.assertFalse(os.path.isfile("root_ca/foobar"))
def test_scrape_dir_exists(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): HashedPRNG(seed=b"foobar").write_file("out.bin", 3000) os.mkdir("scrape") with open("scrape/foo", "wb"): pass self._run_x509sak(["scrape", "out.bin"], success_return_codes=[1]) self.assertTrue(os.path.isfile("scrape/foo")) self._run_x509sak(["scrape", "--force", "out.bin"]) self.assertTrue(os.path.isfile("scrape/foo"))
def test_scrape_json(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir( tempdir), tempfile.NamedTemporaryFile(prefix="scrapeme_", suffix=".bin") as f: crt = self._load_crt("ok/johannes-bauer.com") self._prepare_file(f, [1000, crt.der_data, 100, crt.der_data, 500]) self._run_x509sak(["scrape", "--write-json", "out.json", f.name]) with open("out.json") as f: data = json.load(f) self.assertEqual(len(data["findings"]), 4)
def test_x509_extension(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): self._run_x509sak([ "createca", "--extension", "nameConstraints=critical,permitted;DNS:foo.bar.com", "root_ca" ]) output = SubprocessExecutor([ "openssl", "x509", "-text", "-noout", "-in", "root_ca/CA.crt" ]).run().stdout self.assertIn(b"DNS:foo.bar.com", output) self.assertNotIn(b"pathlen", output) self._run_x509sak([ "createca", "--extension", "nameConstraints=critical,permitted;DNS:foo.bar.com", "--extension", "basicConstraints=critical,CA:TRUE,pathlen:123", "root_ca2" ]) output = SubprocessExecutor([ "openssl", "x509", "-text", "-noout", "-in", "root_ca2/CA.crt" ]).run().stdout self.assertIn(b"DNS:foo.bar.com", output) self.assertIn(b"pathlen:123", output)
def test_automatic_e(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): PrimeDB().add(0xd06bda6bd4031ec96cb8023fd89fc9bb, 0xd578117dc5a445697a7c6e04e09c801f).write() self._run_x509sak(["genbrokenrsa", "--bitlen", "256", "-e", "-1"]) key = RSAPrivateKey.read_pemfile("broken_rsa.key")[0] self.assertEqual(key.n.bit_length(), 256) self.assertEqual(key.p, 0xd06bda6bd4031ec96cb8023fd89fc9bb) self.assertEqual(key.q, 0xd578117dc5a445697a7c6e04e09c801f) self.assertNotEqual(key.e, 0x10001) key.check_integrity()
def test_failed_rsa_privkey(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir( tempdir), tempfile.NamedTemporaryFile(prefix="scrapeme_", suffix=".bin") as f: crt = self._load_crt("ok/johannes-bauer.com") self._prepare_file(f, [100, crt.der_data, 100]) self._run_x509sak(["scrape", "--keep-original-der", f.name]) scraped_crt = X509Certificate.read_derfile( "scrape/scrape_%07x_crt.der" % (100)) self.assertEqual(len(os.listdir("scrape/")), 1) self.assertEqual(crt, scraped_crt)
def test_multifile_all_except_root(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir), ResourceFileLoader([ "certs/ok/johannes-bauer-root.pem", "certs/ok/johannes-bauer-intermediate.pem" ], "certs/ok/johannes-bauer.com.pem") as (searchdir, certfile): self._run_x509sak([ "buildchain", "-s", searchdir, "--outform", "multifile", "--outfile", "outcrt%02d.pem", certfile ]) self.assertEqual(X509Certificate.read_pemfile("outcrt00.pem")[0].subject.rfc2253_str, "CN=DST Root CA X3,O=Digital Signature Trust Co.") self.assertEqual(X509Certificate.read_pemfile("outcrt01.pem")[0].subject.rfc2253_str, "CN=Let's Encrypt Authority X3,O=Let's Encrypt,C=US") self.assertEqual(X509Certificate.read_pemfile("outcrt02.pem")[0].subject.rfc2253_str, "CN=johannes-bauer.com") self._run_x509sak([ "buildchain", "-s", searchdir, "--outform", "multifile", "--order-leaf-to-root", "--outfile", "rev_outcrt%02d.pem", certfile ]) self.assertEqual(X509Certificate.read_pemfile("rev_outcrt00.pem")[0].subject.rfc2253_str, "CN=johannes-bauer.com") self.assertEqual(X509Certificate.read_pemfile("rev_outcrt01.pem")[0].subject.rfc2253_str, "CN=Let's Encrypt Authority X3,O=Let's Encrypt,C=US") self.assertEqual(X509Certificate.read_pemfile("rev_outcrt02.pem")[0].subject.rfc2253_str, "CN=DST Root CA X3,O=Digital Signature Trust Co.")
def test_duplicate_cn(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): self._run_x509sak(["createca", "-s", "/CN=PARENT", "root_ca"]) self._gencert(1) # Try to reuse same CN for other certificate -- must fail! self._run_x509sak([ "createcsr", "-s", "/CN=CHILD1", "-t", "tls-client", "-c", "root_ca", "client2.key", "client2.crt" ], on_failure="exception-nopause", success_return_codes=[1])
def test_failed_rsa_plausibility(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir( tempdir), tempfile.NamedTemporaryFile(prefix="scrapeme_", suffix=".bin") as f: privkey = self._load_privkey("broken/rsa_p_q_neq_n") self._prepare_file(f, [100, privkey.der_data, 100]) self._run_x509sak(["scrape", f.name]) self.assertEqual(len(os.listdir("scrape/")), 0) shutil.rmtree("scrape") self._run_x509sak( ["scrape", "--disable-der-sanity-checks", f.name]) self.assertEqual(len(os.listdir("scrape/")), 1)
def ca_create_crl(cls, ca_manager, crl_filename, signing_hash = None, validity_days = None): crl_absfilename = os.path.realpath(crl_filename) openssl_config = cls.__get_config(private_key_storage = ca_manager.private_key_storage) with WorkDir(ca_manager.capath), tempfile.NamedTemporaryFile("w", prefix = "config_", suffix = ".cnf") as config_file: openssl_config.write_to(config_file.name) cmd = [ cls._EXECUTABLE, "ca", "-gencrl", "-out", crl_absfilename ] if validity_days is not None: cmd += [ "-crldays", str(validity_days) ] if signing_hash is not None: cmd += [ "-md", signing_hash ] cmd += cls._privkey_option(ca_manager.private_key_storage, key_option = "keyfile") SubprocessExecutor(cmd, env = { "OPENSSL_CONF": config_file.name }).run()
def test_failed_dsa_plausibility(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir( tempdir), tempfile.NamedTemporaryFile(prefix="scrapeme_", suffix=".bin") as f: self._prepare_file( f, [100, bytes.fromhex("300b0203112233020400aabbcc"), 100]) self._run_x509sak(["scrape", f.name]) self.assertEqual(len(os.listdir("scrape/")), 0) shutil.rmtree("scrape") self._run_x509sak( ["scrape", "--disable-der-sanity-checks", f.name]) self.assertEqual(len(os.listdir("scrape/")), 1)
def test_forge_root(self): root_crt = self._load_crt("ok/johannes-bauer-root") with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): root_crt.write_pemfile("root.crt") self._run_x509sak(["forgecert", "root.crt"]) forged_root_crt = X509Certificate.read_pemfile("forged_00.crt")[0] self._assertCrtsSimilar(root_crt, forged_root_crt) orig_ski = root_crt.extensions.get_first( OIDDB.X509Extensions.inverse("SubjectKeyIdentifier")) forged_ski = forged_root_crt.extensions.get_first( OIDDB.X509Extensions.inverse("SubjectKeyIdentifier")) self.assertEqual(orig_ski, forged_ski)
def test_serial_spec(self): with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir): self._run_x509sak([ "createca", "-s", "/CN=PARENT", "--serial", "1234567", "root_ca" ]) output = SubprocessExecutor([ "openssl", "x509", "-text", "-in", "root_ca/CA.crt" ]).run().stdout self.assertIn(b"Serial Number: 1234567", output) self._run_x509sak([ "createca", "-s", "/CN=PARENT", "-f", "--serial", "0x1234567", "root_ca" ]) output = SubprocessExecutor([ "openssl", "x509", "-text", "-in", "root_ca/CA.crt" ]).run().stdout self.assertIn(b"Serial Number: 19088743", output) # Catch error message output = self._run_x509sak([ "createca", "-p", "root_ca", "-s", "/CN=INTERMEDIATE", "--serial", "9876", "intermediate_ca" ], success_return_codes = [ 1 ]).stderr self.assertIn(b"specify certificate serial number", output)
def test_create_ca(self): with SoftHSMInstance() as hsm, tempfile.TemporaryDirectory( ) as tempdir, WorkDir(tempdir): key_name = hsm.keygen(key_id=12345, key_label="my secure key", key_spec="EC:secp256r1") pubkey = hsm.get_ecc_pubkey_text(key_id=12345) pubkey = pubkey.split("\n") pubkey_start = pubkey[2] self.assertTrue(pubkey_start.startswith(" 04:")) pubkey_start = pubkey_start[4:].encode("ascii") # With unknown key object name, it fails self._run_x509sak([ "createca", "-f", "-s", "/CN=Root CA with key in HSM", "--pkcs11-so-search", hsm.so_search_path, "--pkcs11-module", "libsofthsm2.so", "--hardware-key", key_name.replace("secure", "UNKNOWN"), "root_ca" ], env=hsm.env, success_return_codes=[1]) # With unknown token name, it fails self._run_x509sak([ "createca", "-f", "-s", "/CN=Root CA with key in HSM", "--pkcs11-so-search", hsm.so_search_path, "--pkcs11-module", "libsofthsm2.so", "--hardware-key", key_name.replace("Token", "UNKNOWN"), "root_ca" ], env=hsm.env, success_return_codes=[1]) # Create root certificate with key in SoftHSM self._run_x509sak([ "createca", "-f", "-s", "/CN=Root CA with key in HSM", "--pkcs11-so-search", hsm.so_search_path, "--pkcs11-module", "libsofthsm2.so", "--hardware-key", key_name, "root_ca" ], env=hsm.env) # Check that it's validly self-signed SubprocessExecutor([ "openssl", "verify", "-check_ss_sig", "-CAfile", "root_ca/CA.crt", "root_ca/CA.crt" ]).run() # Check that the public key on the smart card appears inside the certificate output = SubprocessExecutor([ "openssl", "x509", "-noout", "-text", "-in", "root_ca/CA.crt" ]).run().stdout self.assertIn(pubkey_start, output)