示例#1
0
 def test_storage_load_fails(self):
     with ResourceFileLoader(
             "certs/ok/johannes-bauer-root.pem") as cert_filename:
         pks = PrivateKeyStorage(PrivateKeyStorageForm.PEM_FILE,
                                 filename=cert_filename)
         with self.assertRaises(UnexpectedFileContentException):
             pks.load_private_key()
示例#2
0
	def test_gen_csr(self):
		with tempfile.NamedTemporaryFile(prefix = "privkey_", suffix = ".pem") as privkey_file, tempfile.NamedTemporaryFile(prefix = "csr_", suffix = ".pem") as csr_file:
			OpenSSLTools.create_private_key(PrivateKeyStorage(storage_form = PrivateKeyStorageForm.PEM_FILE, filename = privkey_file.name), keyspec = KeySpecification.from_cmdline_str("ecc:secp256r1"))
			private_key_storage = PrivateKeyStorage(storage_form = PrivateKeyStorageForm.PEM_FILE, filename = privkey_file.name)

			OpenSSLTools.create_csr(private_key_storage = private_key_storage, csr_filename = csr_file.name, subject_dn = "/CN=Foobar")
			output = SubprocessExecutor([ "openssl", "req", "-text" ], stdin = self._read_file(csr_file.name)).run().stdout
			self.assertIn(b"BEGIN CERTIFICATE REQUEST", output)
			self.assertIn(b"END CERTIFICATE REQUEST", output)
			self.assertTrue((b"Subject: CN = Foobar" in output) or (b"Subject: CN=Foobar" in output))
			self.assertNotIn(b"Requested Extensions:", output)

			OpenSSLTools.create_csr(private_key_storage = private_key_storage, csr_filename = csr_file.name, subject_dn = "/CN=Foobar", subject_alternative_dns_names = [ "muhkuh" ])
			output = SubprocessExecutor([ "openssl", "req", "-text" ], stdin = self._read_file(csr_file.name)).run().stdout
			self.assertIn(b"BEGIN CERTIFICATE REQUEST", output)
			self.assertIn(b"END CERTIFICATE REQUEST", output)
			self.assertTrue((b"Subject: CN = Foobar" in output) or (b"Subject: CN=Foobar" in output))
			self.assertIn(b"Requested Extensions:", output)
			self.assertIn(b"X509v3 Subject Alternative Name:", output)
			self.assertIn(b"DNS:muhkuh", output)

			OpenSSLTools.create_csr(private_key_storage = private_key_storage, csr_filename = csr_file.name, subject_dn = "/CN=Foobar", subject_alternative_dns_names = [ "muhkuh", "kruckelmuckel" ])
			output = SubprocessExecutor([ "openssl", "req", "-text" ], stdin = self._read_file(csr_file.name)).run().stdout
			self.assertIn(b"BEGIN CERTIFICATE REQUEST", output)
			self.assertIn(b"END CERTIFICATE REQUEST", output)
			self.assertTrue((b"Subject: CN = Foobar" in output) or (b"Subject: CN=Foobar" in output))
			self.assertIn(b"Requested Extensions:", output)
			self.assertIn(b"X509v3 Subject Alternative Name:", output)
			self.assertIn(b"DNS:muhkuh", output)
			self.assertIn(b"DNS:kruckelmuckel", output)

			OpenSSLTools.create_csr(private_key_storage = private_key_storage, csr_filename = csr_file.name, subject_dn = "/CN=Foobar", subject_alternative_dns_names = [ "muhkuh", "kruckelmuckel" ], subject_alternative_ip_addresses = [ "11.22.33.44", "99.88.77.66", "abcd::9876" ])
			output = SubprocessExecutor([ "openssl", "req", "-text" ], stdin = self._read_file(csr_file.name)).run().stdout
			self.assertIn(b"BEGIN CERTIFICATE REQUEST", output)
			self.assertIn(b"END CERTIFICATE REQUEST", output)
			self.assertTrue((b"Subject: CN = Foobar" in output) or (b"Subject: CN=Foobar" in output))
			self.assertIn(b"Requested Extensions:", output)
			self.assertIn(b"X509v3 Subject Alternative Name:", output)
			self.assertIn(b"DNS:muhkuh", output)
			self.assertIn(b"DNS:kruckelmuckel", output)
			self.assertIn(b"IP Address:11.22.33.44", output)
			self.assertIn(b"IP Address:99.88.77.66", output)
			self.assertIn(b"IP Address:ABCD:0:0:0:0:0:0:9876", output)

			OpenSSLTools.create_csr(private_key_storage = private_key_storage, csr_filename = csr_file.name, subject_dn = "/CN=Foobar", subject_alternative_dns_names = [ "muhkuh", "kruckelmuckel" ], subject_alternative_ip_addresses = [ "11.22.33.44", "99.88.77.66", "abcd::9876" ], x509_extensions = { "2.3.4.5.6.7": "ASN1:UTF8String:Never gonna give you up" })
			output = SubprocessExecutor([ "openssl", "req", "-text" ], stdin = self._read_file(csr_file.name)).run().stdout
			self.assertIn(b"BEGIN CERTIFICATE REQUEST", output)
			self.assertIn(b"END CERTIFICATE REQUEST", output)
			self.assertTrue((b"Subject: CN = Foobar" in output) or (b"Subject: CN=Foobar" in output))
			self.assertIn(b"Requested Extensions:", output)
			self.assertIn(b"X509v3 Subject Alternative Name:", output)
			self.assertIn(b"DNS:muhkuh", output)
			self.assertIn(b"DNS:kruckelmuckel", output)
			self.assertIn(b"IP Address:11.22.33.44", output)
			self.assertIn(b"IP Address:99.88.77.66", output)
			self.assertIn(b"IP Address:ABCD:0:0:0:0:0:0:9876", output)
			self.assertIn(b"Never gonna give you up", output)
示例#3
0
	def test_gen_selfsigned_cert(self):
		with tempfile.NamedTemporaryFile(prefix = "privkey_", suffix = ".pem") as privkey_file, tempfile.NamedTemporaryFile(prefix = "crt_", suffix = ".pem") as certificate_file:
			OpenSSLTools.create_private_key(PrivateKeyStorage(storage_form = PrivateKeyStorageForm.PEM_FILE, filename = privkey_file.name), keyspec = KeySpecification(cryptosystem = Cryptosystems.ECC_ECDSA, parameters = { "curvename": "secp256r1" }))
			private_key_storage = PrivateKeyStorage(storage_form = PrivateKeyStorageForm.PEM_FILE, filename = privkey_file.name)

			OpenSSLTools.create_selfsigned_certificate(private_key_storage = private_key_storage, certificate_filename = certificate_file.name, subject_dn = "/CN=Foobar", validity_days = 365)
			output = SubprocessExecutor([ "openssl", "x509", "-text" ], stdin = self._read_file(certificate_file.name)).run().stdout
			self.assertIn(b"BEGIN CERTIFICATE--", output)
			self.assertIn(b"END CERTIFICATE--", output)
			self.assertTrue((b"Subject: CN = Foobar" in output) or (b"Subject: CN=Foobar" in output))
			self.assertNotIn(b"X509v3 extensions:", output)

			OpenSSLTools.create_selfsigned_certificate(private_key_storage = private_key_storage, certificate_filename = certificate_file.name, subject_dn = "/CN=Foobar", subject_alternative_dns_names = [ "muhkuh" ], validity_days = 365)
			output = SubprocessExecutor([ "openssl", "x509", "-text" ], stdin = self._read_file(certificate_file.name)).run().stdout
			self.assertIn(b"BEGIN CERTIFICATE--", output)
			self.assertIn(b"END CERTIFICATE--", output)
			self.assertTrue((b"Subject: CN = Foobar" in output) or (b"Subject: CN=Foobar" in output))
			self.assertIn(b"X509v3 extensions:", output)
			self.assertIn(b"X509v3 Subject Alternative Name:", output)
			self.assertIn(b"DNS:muhkuh", output)

			OpenSSLTools.create_selfsigned_certificate(private_key_storage = private_key_storage, certificate_filename = certificate_file.name, subject_dn = "/CN=Foobar", subject_alternative_dns_names = [ "muhkuh", "kruckelmuckel" ], validity_days = 365)
			output = SubprocessExecutor([ "openssl", "x509", "-text" ], stdin = self._read_file(certificate_file.name)).run().stdout
			self.assertIn(b"BEGIN CERTIFICATE--", output)
			self.assertIn(b"END CERTIFICATE--", output)
			self.assertTrue((b"Subject: CN = Foobar" in output) or (b"Subject: CN=Foobar" in output))
			self.assertIn(b"X509v3 extensions:", output)
			self.assertIn(b"X509v3 Subject Alternative Name:", output)
			self.assertIn(b"DNS:muhkuh", output)
			self.assertIn(b"DNS:kruckelmuckel", output)

			OpenSSLTools.create_selfsigned_certificate(private_key_storage = private_key_storage, certificate_filename = certificate_file.name, subject_dn = "/CN=Foobar", subject_alternative_dns_names = [ "muhkuh", "kruckelmuckel" ], subject_alternative_ip_addresses = [ "11.22.33.44", "99.88.77.66", "abcd::9876" ], validity_days = 365)
			output = SubprocessExecutor([ "openssl", "x509", "-text" ], stdin = self._read_file(certificate_file.name)).run().stdout
			self.assertIn(b"BEGIN CERTIFICATE--", output)
			self.assertIn(b"END CERTIFICATE--", output)
			self.assertTrue((b"Subject: CN = Foobar" in output) or (b"Subject: CN=Foobar" in output))
			self.assertIn(b"X509v3 extensions:", output)
			self.assertIn(b"X509v3 Subject Alternative Name:", output)
			self.assertIn(b"DNS:muhkuh", output)
			self.assertIn(b"DNS:kruckelmuckel", output)
			self.assertIn(b"IP Address:11.22.33.44", output)
			self.assertIn(b"IP Address:99.88.77.66", output)
			self.assertIn(b"IP Address:ABCD:0:0:0:0:0:0:9876", output)

			OpenSSLTools.create_selfsigned_certificate(private_key_storage = private_key_storage, certificate_filename = certificate_file.name, subject_dn = "/CN=Foobar", subject_alternative_dns_names = [ "muhkuh", "kruckelmuckel" ], subject_alternative_ip_addresses = [ "11.22.33.44", "99.88.77.66", "abcd::9876" ], x509_extensions = { "2.3.4.5.6.7": "ASN1:UTF8String:Never gonna give you up" }, validity_days = 365)
			output = SubprocessExecutor([ "openssl", "x509", "-text" ], stdin = self._read_file(certificate_file.name)).run().stdout
			self.assertIn(b"BEGIN CERTIFICATE--", output)
			self.assertIn(b"END CERTIFICATE--", output)
			self.assertTrue((b"Subject: CN = Foobar" in output) or (b"Subject: CN=Foobar" in output))
			self.assertIn(b"X509v3 extensions:", output)
			self.assertIn(b"X509v3 Subject Alternative Name:", output)
			self.assertIn(b"DNS:muhkuh", output)
			self.assertIn(b"DNS:kruckelmuckel", output)
			self.assertIn(b"IP Address:11.22.33.44", output)
			self.assertIn(b"IP Address:99.88.77.66", output)
			self.assertIn(b"IP Address:ABCD:0:0:0:0:0:0:9876", output)
			self.assertIn(b"Never gonna give you up", output)
示例#4
0
 def test_storage_load_key_der(self):
     with ResourceFileLoader("privkey/ok/ecc_secp256r1.der",
                             "privkey/ok/eddsa_ed25519_rfc8032.der",
                             "privkey/ok/rsa_768.der") as privkey_filenames:
         for privkey_filename in privkey_filenames:
             pks = PrivateKeyStorage(PrivateKeyStorageForm.DER_FILE,
                                     filename=privkey_filename)
             privkey = pks.load_private_key()
             self.assertIsInstance(
                 privkey, (RSAPrivateKey, ECPrivateKey, EDPrivateKey))
示例#5
0
    def __init__(self, capath):
        self._capath = os.path.realpath(capath)
        if not self._capath.endswith("/"):
            self._capath += "/"

        if not os.path.isfile(self.metadata_filename):
            # Create if does not exist for legacy CAs.
            self._private_key_storage = PrivateKeyStorage(
                PrivateKeyStorageForm.PEM_FILE,
                filename="CA.key",
                search_path=self._capath)
            self._save_metadata()
        else:
            # Load from metadata
            self._load_metadata()
        if self._private_key_storage.is_file_based:
            self._private_key_storage.update("search_path", self._capath)
示例#6
0
	def _forge_cert(self, cert_issuer_id, issuer, cert_subject_id, subject):
		self._log.debug("Forging chain element %d -> %d: %s -> %s", cert_issuer_id, cert_subject_id, issuer, subject)
		issuer_key_filename = self._args.key_template % (cert_issuer_id)
		key_filename = self._args.key_template % (cert_subject_id)
		crt_filename = self._args.cert_template % (cert_subject_id)

		if (not os.path.isfile(key_filename)) or self._args.force:
			OpenSSLTools.create_private_key(PrivateKeyStorage(storage_form = PrivateKeyStorageForm.PEM_FILE, filename = key_filename), subject.pubkey.keyspec)

		# Read new private key and convert to public key
		with tempfile.NamedTemporaryFile(prefix = "pubkey_", suffix = ".pem") as pubkey_file:
			OpenSSLTools.private_to_public(key_filename, pubkey_file.name)
			subject_pubkey = PublicKey.read_pemfile(pubkey_file.name)[0]

		# Do the same for the issuer key to get the issuer key ID
		with tempfile.NamedTemporaryFile(prefix = "pubkey_", suffix = ".pem") as pubkey_file:
			OpenSSLTools.private_to_public(issuer_key_filename, pubkey_file.name)
			issuer_pubkey = PublicKey.read_pemfile(pubkey_file.name)[0]

		# Replace public key first
		forged_cert_asn1 = subject.asn1_clone
		forged_cert_asn1["tbsCertificate"]["subjectPublicKeyInfo"] = subject_pubkey.asn1

		# Do identifiers need to be recalculated?
		if self._args.recalculate_keyids:
			if subject.extensions.has(OIDDB.X509Extensions.inverse("SubjectKeyIdentifier")):
				# Replace subject key identifier
				new_key_id = subject_pubkey.keyid()
				replacement_extension = X509SubjectKeyIdentifierExtension.construct(new_key_id)
				subject.extensions.filter(OIDDB.X509Extensions.inverse("SubjectKeyIdentifier"), replacement_extension)

			if subject.extensions.has(OIDDB.X509Extensions.inverse("AuthorityKeyIdentifier")):
				# Replace authority key identifier
				new_key_id = issuer_pubkey.keyid()
				replacement_extension = X509AuthorityKeyIdentifierExtension.construct(new_key_id)
				subject.extensions.filter(OIDDB.X509Extensions.inverse("AuthorityKeyIdentifier"), replacement_extension)

			forged_cert_asn1["tbsCertificate"]["extensions"] = subject.extensions.to_asn1()

		# Re-serialize certificate
		forged_cert = X509Certificate.from_asn1(forged_cert_asn1)

		# Then sign the modified certifiate
		signature = OpenSSLTools.sign_data(subject.signature_algorithm, issuer_key_filename, forged_cert.signed_payload)

		# Finally, place the signature into the certificate
		forged_cert_asn1["signatureValue"] = ASN1Tools.bytes2bitstring(signature)
		forged_cert = X509Certificate.from_asn1(forged_cert_asn1)
		forged_cert.write_pemfile(crt_filename)
示例#7
0
	def test_gen_privkey_rsa(self):
		input_output_data = [
			(
				{ "bitlen": 512 },
				b"512 bit",
			),
			(
				{ "bitlen": 600 },
				b"600 bit",
			),
		]

		for (input_data, output_data) in input_output_data:
			with tempfile.NamedTemporaryFile(prefix = "privkey_", suffix = ".pem") as f:
				OpenSSLTools.create_private_key(PrivateKeyStorage(storage_form = PrivateKeyStorageForm.PEM_FILE, filename = f.name), keyspec = KeySpecification(cryptosystem = Cryptosystems.RSA, parameters = input_data))
				content = self._read_file(f.name)
				self.assertIn(b"BEGIN RSA PRIVATE KEY", content)
				self.assertIn(b"END RSA PRIVATE KEY", content)
				output = SubprocessExecutor([ "openssl", "rsa", "-text" ], stdin = content).run().stdout
				self.assertIn(output_data, output)
示例#8
0
	def test_gen_privkey_ecc(self):
		input_output_data = [
			(
				{ "curvename": "secp384r1" },
				(b"384 bit", b"secp384r1"),
			),
			(
				{ "curvename": "secp256r1" },
				(b"256 bit", b"prime256v1"),
			),
		]

		for (input_data, output_data) in input_output_data:
			with tempfile.NamedTemporaryFile(prefix = "privkey_", suffix = ".pem") as f:
				OpenSSLTools.create_private_key(PrivateKeyStorage(storage_form = PrivateKeyStorageForm.PEM_FILE, filename = f.name), keyspec = KeySpecification(cryptosystem = Cryptosystems.ECC_ECDSA, parameters = input_data))
				content = self._read_file(f.name)
				self.assertNotIn(b"BEGIN EC PARAMETERS", content)
				self.assertNotIn(b"END EC PARAMETERS", content)
				self.assertIn(b"BEGIN EC PRIVATE KEY", content)
				self.assertIn(b"END EC PRIVATE KEY", content)
				output = SubprocessExecutor([ "openssl", "ec", "-text" ], stdin = content).run().stdout
				self.assertIn(output_data[0], output)
				self.assertIn(output_data[1], output)
示例#9
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)
        if self._args.force:
            try:
                os.unlink(self._args.capath)
            except (IsADirectoryError, FileNotFoundError):
                pass
            try:
                shutil.rmtree(self._args.capath)
            except FileNotFoundError:
                pass
        else:
            if os.path.exists(self._args.capath):
                raise UnfulfilledPrerequisitesException(
                    "File/directory %s already exists. Remove it first or use --force."
                    % (self._args.capath))

        os.makedirs(self._args.capath)
        os.chmod(self._args.capath, 0o700)

        camgr = CAManager(self._args.capath)
        custom_x509_extensions = {
            custom_x509_extension.key: custom_x509_extension.value
            for custom_x509_extension in self._args.extension
        }
        if (self._args.gen_keyspec
                is not None) or ((self._args.gen_keyspec is None) and
                                 (self._args.hardware_key is None)):
            # We need to generate a key.
            if self._args.gen_keyspec is not None:
                keyspec = self._args.gen_keyspec
            else:
                # Cannot default to this in argparse because it's part of a
                # mutually exclusive group with hardware_key
                keyspec = KeySpecification.from_cmdline_str("ecc:secp384r1")
            private_key_storage = PrivateKeyStorage(
                PrivateKeyStorageForm.PEM_FILE,
                filename="CA.key",
                search_path=camgr.capath)
            OpenSSLTools.create_private_key(private_key_storage,
                                            keyspec=keyspec)
        else:
            # The key is stored in hardware.
            private_key_storage = PrivateKeyStorage(
                PrivateKeyStorageForm.HARDWARE_TOKEN,
                pkcs11uri=self._args.hardware_key,
                so_search_path=self._args.pkcs11_so_search,
                module_so=self._args.pkcs11_module)

        signing_hash = self._args.hashfnc
        if private_key_storage.is_file_based:
            privkey = private_key_storage.load_private_key()
            if isinstance(privkey, EDPrivateKey):
                # We cannot specify a hash function for EdDSA because this
                # causes OpenSSL to fail with "elliptic curve
                # routines:pkey_ecd_ctrl:invalid digest type" -- for EdDSA, the
                # hash algorithms are implied
                signing_hash = None

        camgr.create_ca_structure(
            private_key_storage=private_key_storage,
            unique_subject=not self._args.allow_duplicate_subjects)
        if self._args.parent_ca is None:
            # Self-signed root CA
            camgr.create_selfsigned_ca_cert(
                subject_dn=self._args.subject_dn,
                validity_days=self._args.validity_days,
                custom_x509_extensions=custom_x509_extensions,
                signing_hash=signing_hash,
                serial=self._args.serial)

            # Create certificate chain file that only consists of our
            # self-signed certificate
            shutil.copy(self._args.capath + "/CA.crt",
                        self._args.capath + "/chain.crt")
        else:
            # Intermediate CA
            if self._args.serial is not None:
                raise InvalidUsageException(
                    "Can only specify certificate serial number when creating self-signed root CA certificate."
                )
            with tempfile.NamedTemporaryFile("w", prefix="ca_",
                                             suffix=".csr") as csr:
                camgr.create_ca_csr(csr_filename=csr.name,
                                    subject_dn=self._args.subject_dn)
                parent_ca = CAManager(self._args.parent_ca)
                parent_ca.sign_csr(
                    csr.name,
                    camgr.root_crt_filename,
                    subject_dn=self._args.subject_dn,
                    validity_days=self._args.validity_days,
                    custom_x509_extensions=custom_x509_extensions,
                    extension_template="ca",
                    signing_hash=signing_hash)

            # Create a certificate chain by appending the parent chain to our certificate
            if os.path.isfile(self._args.parent_ca + "/chain.crt"):
                with open(self._args.parent_ca +
                          "/chain.crt") as parent_chainfile:
                    parent_chain = parent_chainfile.read()
                with open(self._args.capath +
                          "/CA.crt") as new_certificate_file:
                    new_certificate = new_certificate_file.read()
                with open(self._args.capath + "/chain.crt",
                          "w") as intermediate_chainfile:
                    intermediate_chainfile.write(parent_chain)
                    intermediate_chainfile.write(new_certificate)
示例#10
0
 def _load_metadata(self):
     with open(self.metadata_filename) as f:
         metadata = json.load(f)
     self._private_key_storage = PrivateKeyStorage.from_dict(
         metadata["private_key_storage"])
示例#11
0
class CAManager():
    _FILTER_EXTENSIONS_FOR_CSR = set(["authorityKeyIdentifier"])
    _EXTENSION_TEMPLATES = {
        "rootca": {
            "basicConstraints": "critical,CA:TRUE",
            "subjectKeyIdentifier": "hash",
            "keyUsage": "critical,digitalSignature,keyCertSign,cRLSign",
        },
        "ca": {
            "basicConstraints": "critical,CA:TRUE",
            "subjectKeyIdentifier": "hash",
            "authorityKeyIdentifier": "keyid",
            "keyUsage": "critical,digitalSignature,keyCertSign,cRLSign",
        },
        "tls-client": {
            "nsCertType": "client",
            "basicConstraints": "critical,CA:FALSE",
            "subjectKeyIdentifier": "hash",
            "authorityKeyIdentifier": "keyid",
            "keyUsage":
            "critical,digitalSignature,keyAgreement,keyEncipherment",
            "extendedKeyUsage": "clientAuth",
        },
        "tls-server": {
            "nsCertType": "server",
            "basicConstraints": "critical,CA:FALSE",
            "subjectKeyIdentifier": "hash",
            "authorityKeyIdentifier": "keyid",
            "keyUsage":
            "critical,digitalSignature,keyAgreement,keyEncipherment",
            "extendedKeyUsage": "serverAuth",
        },
    }

    def __init__(self, capath):
        self._capath = os.path.realpath(capath)
        if not self._capath.endswith("/"):
            self._capath += "/"

        if not os.path.isfile(self.metadata_filename):
            # Create if does not exist for legacy CAs.
            self._private_key_storage = PrivateKeyStorage(
                PrivateKeyStorageForm.PEM_FILE,
                filename="CA.key",
                search_path=self._capath)
            self._save_metadata()
        else:
            # Load from metadata
            self._load_metadata()
        if self._private_key_storage.is_file_based:
            self._private_key_storage.update("search_path", self._capath)

    @property
    def capath(self):
        return self._capath

    def _load_metadata(self):
        with open(self.metadata_filename) as f:
            metadata = json.load(f)
        self._private_key_storage = PrivateKeyStorage.from_dict(
            metadata["private_key_storage"])

    def _save_metadata(self):
        metadata = {
            "version": 1,
            "private_key_storage": self._private_key_storage.to_dict(),
        }
        with open(self.metadata_filename, "w") as f:
            json.dump(metadata, f, sort_keys=True, indent=4)
            f.write("\n")

    def _file(self, filename):
        return self._capath + filename

    @property
    def metadata_filename(self):
        return self._file("metadata.json")

    @property
    def private_key_storage(self):
        return self._private_key_storage

    @property
    def root_crt_filename(self):
        return self._file("CA.crt")

    @property
    def serial_filename(self):
        return self._file("serial")

    @property
    def crlnumber_filename(self):
        return self._file("crlnumber")

    @property
    def crl_filename(self):
        return self._file("CA.crl")

    @property
    def index_filename(self):
        return self._file("index.txt")

    @property
    def index_attr_filename(self):
        return self._file("index.txt.attr")

    @property
    def newcerts_dirname(self):
        return self._file("certs")

    @classmethod
    def expand_extensions(cls,
                          extension_template=None,
                          custom_x509_extensions=None):
        extensions = {}
        if extension_template is not None:
            extensions.update(cls._EXTENSION_TEMPLATES[extension_template])
        if custom_x509_extensions is not None:
            extensions.update(custom_x509_extensions)
        return extensions

    def create_selfsigned_ca_cert(self,
                                  subject_dn,
                                  validity_days,
                                  signing_hash,
                                  serial,
                                  custom_x509_extensions=None):
        x509_extensions = self.expand_extensions(
            extension_template="rootca",
            custom_x509_extensions=custom_x509_extensions)
        OpenSSLTools.create_selfsigned_certificate(
            self.private_key_storage,
            self.root_crt_filename,
            subject_dn,
            validity_days,
            signing_hash=signing_hash,
            serial=serial,
            x509_extensions=x509_extensions)

    def create_ca_csr(self, csr_filename, subject_dn):
        OpenSSLTools.create_csr(self.private_key_storage, csr_filename,
                                subject_dn)

    @classmethod
    def create_csr(cls,
                   private_key_storage,
                   csr_filename,
                   subject_dn,
                   extension_template=None,
                   custom_x509_extensions=None,
                   subject_alternative_dns_names=None,
                   subject_alternative_ip_addresses=None,
                   signing_hash=None):
        extensions = cls.expand_extensions(extension_template,
                                           custom_x509_extensions)
        extensions = {
            key: value
            for (key, value) in extensions.items()
            if key not in cls._FILTER_EXTENSIONS_FOR_CSR
        }
        OpenSSLTools.create_csr(
            private_key_storage,
            csr_filename,
            subject_dn,
            x509_extensions=extensions,
            subject_alternative_dns_names=subject_alternative_dns_names,
            subject_alternative_ip_addresses=subject_alternative_ip_addresses,
            signing_hash=signing_hash)

    def sign_csr(self,
                 csr_filename,
                 crt_filename,
                 subject_dn,
                 validity_days,
                 extension_template=None,
                 custom_x509_extensions=None,
                 subject_alternative_dns_names=None,
                 subject_alternative_ip_addresses=None,
                 signing_hash=None):
        extensions = self.expand_extensions(extension_template,
                                            custom_x509_extensions)
        OpenSSLTools.ca_sign_csr(
            self,
            csr_filename,
            crt_filename,
            subject_dn,
            validity_days,
            x509_extensions=extensions,
            subject_alternative_dns_names=subject_alternative_dns_names,
            subject_alternative_ip_addresses=subject_alternative_ip_addresses,
            signing_hash=signing_hash)

    def revoke_crt(self, *args, **kwargs):
        OpenSSLTools.ca_revoke_crt(self, *args, **kwargs)

    def create_crl(self, *args, **kwargs):
        OpenSSLTools.ca_create_crl(self, *args, **kwargs)

    def __create_management_files(self, unique_subject=True):
        with open(self.index_filename, "w") as f:
            pass
        with open(self.index_attr_filename, "w") as f:
            print("unique_subject = %s" % ("yes" if unique_subject else "no"),
                  file=f)
        with open(self.serial_filename, "w") as f:
            print("01", file=f)
        with open(self.crlnumber_filename, "w") as f:
            print("01", file=f)
        os.mkdir(self.newcerts_dirname)

    def create_ca_structure(self, private_key_storage, unique_subject=True):
        self._private_key_storage = private_key_storage
        self._save_metadata()
        self.__create_management_files(unique_subject=unique_subject)
示例#12
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)
        if (self._args.private_key
                is not None) and (self._args.outform != "pkcs12"):
            raise InvalidUsageException(
                "A private key will only be exported with a PKCS#12 output file."
            )
        if self._args.outform != "pkcs12":
            if self._args.pkcs12_legacy_crypto:
                raise InvalidUsageException(
                    "Specifying PKCS#12 legacy crypto while not using PKCS#12 output format has no effect."
                )
            if self._args.pkcs12_no_passphrase:
                raise InvalidUsageException(
                    "Specifying no PKCS#12 passphrase while not using PKCS#12 output format has no effect."
                )
            if self._args.pkcs12_passphrase_file is not None:
                raise InvalidUsageException(
                    "Specifying a PKCS#12 passphrase while not using PKCS#12 output format has no effect."
                )
        else:
            if (self._args.pkcs12_legacy_crypto
                    or self._args.pkcs12_no_passphrase
                    or self._args.pkcs12_passphrase_file
                    is not None) and (self._args.private_key is None):
                raise InvalidUsageException(
                    "Specifying any PKCS#12 passphrase/crypto options when not including a private key makes no sense."
                )

        self._pool = CertificatePool()
        self._load_truststore()
        if self._args.inform == "pem":
            certs = X509Certificate.read_pemfile(self._args.crtfile)
            if not self._args.dont_trust_crtfile:
                self._pool.add_certificates(certs)
            cert = certs[0]
        elif self._args.inform == "der":
            cert = X509Certificate.read_derfile(self._args.crtfile)
        else:
            raise NotImplementedError("inform", self._args.inform)
        chain = self._pool.find_chain(cert)
        if (chain.root is None) and (not self._args.allow_partial_chain):
            raise InvalidUsageException(
                "Could not build full chain for certificate %s and partial chain matches are disallowed."
                % (self._args.crtfile))

        if self._args.outform == "rootonly":
            if chain.root is None:
                print("Root certificate output requested, but none found.",
                      file=sys.stderr)
                sys.exit(1)
            certs = [chain.root]
        elif self._args.outform == "intermediates":
            certs = list(chain.chain)
        elif self._args.outform in ["fullchain", "multifile", "pkcs12"]:
            certs = list(chain.full_chain)
        elif self._args.outform == "all-except-root":
            certs = list(chain.full_chain)
            if chain.root is not None:
                certs = certs[:-1]
        else:
            raise NotImplementedError("outform", self._args.outform)

        if not self._args.order_leaf_to_root:
            certs = certs[::-1]

        for (cid, cert) in enumerate(certs):
            self._log.debug("Cert %d: %s", cid, cert)

        if self._args.outform == "multifile":
            for (cid, cert) in enumerate(certs):
                filename = self._args.outfile % (cid)
                with open(filename, "w") as f:
                    print(cert.to_pem_data(), file=f)
        elif self._args.outform == "pkcs12":
            if self._args.private_key is not None:
                if self._args.pkcs12_no_passphrase:
                    passphrase = None
                else:
                    if self._args.pkcs12_passphrase_file is not None:
                        with open(self._args.pkcs12_passphrase_file) as f:
                            passphrase = f.readline()
                    else:
                        passphrase = PassphraseGenerator.non_ambiguous(
                        ).gen_passphrase(80)
                        print("Passphrase: %s" % (passphrase), file=sys.stderr)
            else:
                passphrase = None
            private_key_storage = PrivateKeyStorage(
                PrivateKeyStorageForm.PEM_FILE,
                filename=self._args.private_key) if (self._args.private_key
                                                     is not None) else None
            pkcs12 = OpenSSLTools.create_pkcs12(
                certificates=certs,
                private_key_storage=private_key_storage,
                modern_crypto=not self._args.pkcs12_legacy_crypto,
                passphrase=passphrase)
            if self._args.outfile is None:
                # Write to stdout
                sys.stdout.buffer.write(pkcs12)
            else:
                # Write to file, binary
                with open(self._args.outfile, "wb") as f:
                    f.write(pkcs12)
        else:
            if self._args.outfile is not None:
                with open(self._args.outfile, "w") as f:
                    self._print_certs(f, certs)
            else:
                self._print_certs(sys.stdout, certs)