示例#1
0
    def as_view(cls, responder_key, responder_cert, **kwargs):
        priv_err_msg = '%s: Could not read private key.' % responder_key
        pub_err_msg = '%s: Could not read public key.' % responder_cert

        # Preload the responder key and certificate for faster access.
        try:
            with open(responder_key, 'rb') as stream:
                responder_key = stream.read()
        except:
            raise ImproperlyConfigured(priv_err_msg)

        try:
            # try to load responder key and cert with oscrypto, to make sure they are actually usable
            load_private_key(responder_key)
        except:
            raise ImproperlyConfigured(priv_err_msg)

        if os.path.exists(responder_cert):
            with open(responder_cert, 'rb') as stream:
                responder_cert = stream.read()

        if not responder_cert:
            raise ImproperlyConfigured(pub_err_msg)

        try:
            load_certificate(responder_cert)
        except:
            raise ImproperlyConfigured(pub_err_msg)

        return super(OCSPView, cls).as_view(responder_key=responder_key,
                                            responder_cert=responder_cert,
                                            **kwargs)
示例#2
0
    def test_cert_get(self) -> None:
        """Test getting OCSP responses."""
        priv_path, _cert_path, ocsp_cert = self.ca.generate_ocsp_key()
        self.ocsp_private_key = asymmetric.load_private_key(ca_storage.path(priv_path))

        url = reverse(
            "django_ca:ocsp-cert-get",
            kwargs={
                "serial": self.ca.serial,
                "data": base64.b64encode(req1).decode("utf-8"),
            },
        )
        response = self.client.get(url)
        self.assertEqual(response.status_code, HTTPStatus.OK)

        # URL config sets expires to 3600
        self.assertOCSP(
            response, requested=[self.cert], nonce=req1_asn1_nonce, ocsp_cert=ocsp_cert, expires=3600
        )

        priv_path, _cert_path, ocsp_cert = self.ca.generate_ocsp_key(key_size=1024)
        self.ocsp_private_key = asymmetric.load_private_key(ca_storage.path(priv_path))
        response = self.client.get(url)
        self.assertEqual(response.status_code, HTTPStatus.OK)

        # URL config sets expires to 3600
        self.assertOCSP(
            response, requested=[self.cert], nonce=req1_asn1_nonce, ocsp_cert=ocsp_cert, expires=3600
        )
示例#3
0
    def test_cert_get(self):
        ca = self.cas['child']
        cert = self.certs['child-cert']

        priv_path, cert_path, ocsp_cert = ca.generate_ocsp_key()
        self.ocsp_private_key = asymmetric.load_private_key(
            ca_storage.path(priv_path))

        url = reverse('django_ca:ocsp-cert-get',
                      kwargs={
                          'serial': self.cas['child'].serial,
                          'data': base64.b64encode(req1).decode('utf-8'),
                      })
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

        # URL config sets expires to 3600
        self.assertOCSP(response,
                        requested=[cert],
                        nonce=req1_nonce,
                        ocsp_cert=ocsp_cert,
                        expires=3600)

        priv_path, cert_path, ocsp_cert = ca.generate_ocsp_key(key_size=1024)
        self.ocsp_private_key = asymmetric.load_private_key(
            ca_storage.path(priv_path))
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

        # URL config sets expires to 3600
        self.assertOCSP(response,
                        requested=[cert],
                        nonce=req1_nonce,
                        ocsp_cert=ocsp_cert,
                        expires=3600)
示例#4
0
 def test_dump_private_openssl(self):
     private = asymmetric.load_private_key(
         os.path.join(fixtures_dir, 'keys/test.key'))
     pem_serialized = asymmetric.dump_openssl_private_key(
         private, 'password123')
     private_reloaded = asymmetric.load_private_key(pem_serialized,
                                                    'password123')
     self.assertIsInstance(private_reloaded, asymmetric.PrivateKey)
     self.assertEqual('rsa', private_reloaded.algorithm)
示例#5
0
        def do_run():
            private = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test.key'))

            for password in [None, 'password123']:
                pem_serialized = asymmetric.dump_private_key(private, password, target_ms=20)
                private_reloaded = asymmetric.load_private_key(pem_serialized, password)
                self.assertTrue(pem.detect(pem_serialized))
                self.assertIsInstance(private_reloaded, asymmetric.PrivateKey)
                self.assertEqual('rsa', private_reloaded.algorithm)
示例#6
0
        def do_run():
            private = asymmetric.load_private_key(
                os.path.join(fixtures_dir, 'keys/test.key'))

            for password in [None, 'password123']:
                pem_serialized = asymmetric.dump_private_key(private,
                                                             password,
                                                             target_ms=20)
                private_reloaded = asymmetric.load_private_key(
                    pem_serialized, password)
                self.assertTrue(pem.detect(pem_serialized))
                self.assertIsInstance(private_reloaded, asymmetric.PrivateKey)
                self.assertEqual('rsa', private_reloaded.algorithm)
示例#7
0
    def test_dsa_generate(self):
        public, private = asymmetric.generate_pair('dsa', bit_size=1024)

        self.assertEqual('dsa', public.algorithm)
        self.assertEqual(1024, public.bit_size)

        original_data = b'This is data to sign'
        signature = asymmetric.dsa_sign(private, original_data, 'sha1')
        self.assertIsInstance(signature, byte_cls)
        asymmetric.dsa_verify(public, signature, original_data, 'sha1')

        raw_public = asymmetric.dump_public_key(public)
        asymmetric.load_public_key(raw_public)
        raw_private = asymmetric.dump_private_key(private, None)
        asymmetric.load_private_key(raw_private, None)
示例#8
0
    def test_ec_generate(self):
        public, private = asymmetric.generate_pair('ec', curve='secp256r1')

        self.assertEqual('ec', public.algorithm)
        self.assertEqual('secp256r1', public.asn1.curve[1])

        original_data = b'This is data to sign'
        signature = asymmetric.ecdsa_sign(private, original_data, 'sha1')
        self.assertIsInstance(signature, byte_cls)
        asymmetric.ecdsa_verify(public, signature, original_data, 'sha1')

        raw_public = asymmetric.dump_public_key(public)
        asymmetric.load_public_key(raw_public)
        raw_private = asymmetric.dump_private_key(private, None)
        asymmetric.load_private_key(raw_private, None)
示例#9
0
    def test_ec_generate(self):
        public, private = asymmetric.generate_pair('ec', curve='secp256r1')

        self.assertEqual('ec', public.algorithm)
        self.assertEqual('secp256r1', public.asn1.curve[1])

        original_data = b'This is data to sign'
        signature = asymmetric.ecdsa_sign(private, original_data, 'sha1')
        self.assertIsInstance(signature, byte_cls)
        asymmetric.ecdsa_verify(public, signature, original_data, 'sha1')

        raw_public = asymmetric.dump_public_key(public)
        asymmetric.load_public_key(raw_public)
        raw_private = asymmetric.dump_private_key(private, None)
        asymmetric.load_private_key(raw_private, None)
示例#10
0
    def test_dsa_generate(self):
        public, private = asymmetric.generate_pair('dsa', bit_size=1024)

        self.assertEqual('dsa', public.algorithm)
        self.assertEqual(1024, public.bit_size)

        original_data = b'This is data to sign'
        signature = asymmetric.dsa_sign(private, original_data, 'sha1')
        self.assertIsInstance(signature, byte_cls)
        asymmetric.dsa_verify(public, signature, original_data, 'sha1')

        raw_public = asymmetric.dump_public_key(public)
        asymmetric.load_public_key(raw_public)
        raw_private = asymmetric.dump_private_key(private, None)
        asymmetric.load_private_key(raw_private, None)
示例#11
0
    def test_rsa_private_oaep_decrypt(self):
        original_data = b'This is the message to sign'
        private = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test.key'))

        with open(os.path.join(fixtures_dir, 'rsa_public_encrypted_oaep'), 'rb') as f:
            plaintext = asymmetric.rsa_oaep_decrypt(private, f.read())
            self.assertEqual(original_data, plaintext)
def test_demo_plugin(requests_mock):

    with_plugin_cfg = CertomancerConfig.from_file('tests/data/with-plugin.yml',
                                                  'tests/data')

    arch = with_plugin_cfg.get_pki_arch(ArchLabel('testing-ca'))

    illusionist.Illusionist(pki_arch=arch).register(requests_mock)

    importlib.import_module('example_plugin.encrypt_echo')

    # make the endpoint encrypt something
    endpoint = 'http://test.test/testing-ca/plugin/encrypt-echo/test-endpoint'
    payload = b'test test test'
    response = requests.post(endpoint, data=payload)

    # decrypt it
    env_data = cms.ContentInfo.load(response.content)['content']
    key = arch.key_set.get_private_key(KeyLabel('signer1'))
    ktri = env_data['recipient_infos'][0].chosen
    encrypted_key = ktri['encrypted_key'].native

    decrypted_key = asymmetric.rsa_pkcs1v15_decrypt(
        asymmetric.load_private_key(key.dump()), encrypted_key)

    eci = env_data['encrypted_content_info']
    cea = eci['content_encryption_algorithm']
    assert cea['algorithm'].native == 'aes256_cbc'
    iv = cea['parameters'].native
    encrypted_content_bytes = eci['encrypted_content'].native
    decrypted_payload = symmetric.aes_cbc_pkcs7_decrypt(
        decrypted_key, encrypted_content_bytes, iv)
    assert decrypted_payload == payload
    def test_build_signed_request(self):
        issuer_cert = asymmetric.load_certificate(os.path.join(fixtures_dir, "test.crt"))
        subject_cert = asymmetric.load_certificate(os.path.join(fixtures_dir, "test-inter.crt"))

        requestor_cert = asymmetric.load_certificate(os.path.join(fixtures_dir, "test-third.crt"))
        requestor_key = asymmetric.load_private_key(os.path.join(fixtures_dir, "test-third.key"))

        builder = OCSPRequestBuilder(subject_cert, issuer_cert)
        ocsp_request = builder.build(requestor_key, requestor_cert, [subject_cert, issuer_cert])
        der_bytes = ocsp_request.dump()

        new_request = asn1crypto.ocsp.OCSPRequest.load(der_bytes)
        tbs_request = new_request["tbs_request"]
        signature = new_request["optional_signature"]

        self.assertEqual("sha256", signature["signature_algorithm"].hash_algo)
        self.assertEqual("rsassa_pkcs1v15", signature["signature_algorithm"].signature_algo)
        self.assertEqual(3, len(signature["certs"]))
        self.assertEqual("v1", tbs_request["version"].native)
        self.assertEqual(requestor_cert.asn1.subject, tbs_request["requestor_name"].chosen)
        self.assertEqual(1, len(tbs_request["request_list"]))

        request = tbs_request["request_list"][0]
        self.assertEqual("sha1", request["req_cert"]["hash_algorithm"]["algorithm"].native)
        self.assertEqual(issuer_cert.asn1.subject.sha1, request["req_cert"]["issuer_name_hash"].native)
        self.assertEqual(issuer_cert.asn1.public_key.sha1, request["req_cert"]["issuer_key_hash"].native)
        self.assertEqual(subject_cert.asn1.serial_number, request["req_cert"]["serial_number"].native)
        self.assertEqual(0, len(request["single_request_extensions"]))

        self.assertEqual(1, len(tbs_request["request_extensions"]))
        extn = tbs_request["request_extensions"][0]

        self.assertEqual("nonce", extn["extn_id"].native)
        self.assertEqual(16, len(extn["extn_value"].parsed.native))
示例#14
0
    def frompem(cls, issuer_cert: StrOrBytes, responder_cert: StrOrBytes, responder_key: StrOrBytes,
                       validate_func: ValidateFunc, cert_retrieve_func: CertRetrieveFunc = None,
                       next_update_days: int = 7):
        """
        Create a new OCSPResponder instance from filepaths or bytes.
        :param issuer_cert: Path to or Bytes of the issuer certificate.
        :param responder_cert: Path to or Bytes of the certificate of the OCSP responder
            with the `OCSP Signing` extension.
        :param responder_key: Path to or Bytes of the private key belonging to the
            responder cert.
        :param validate_func: A function that - given a certificate serial -
            will return the appropriate :class:`CertificateStatus` and -
            depending on the status - a revocation datetime.
        :param cert_retrieve_func: A function that - given a certificate serial -
            will return the corresponding certificate as a string.
        :param next_update_days: The ``nextUpdate`` value that will be written
            into the response. Default: 7 days.
        """
        # Certs and keys
        _issuer_cert = asymmetric.load_certificate(issuer_cert)
        _responder_cert = asymmetric.load_certificate(responder_cert)
        _responder_key = asymmetric.load_private_key(responder_key)

        return cls(_issuer_cert, _responder_cert, _responder_key,
                validate_func=validate_func,
                cert_retrieve_func=cert_retrieve_func,
                next_update_days=next_update_days)
    def test_build_revoked_no_reason(self):
        issuer_key = asymmetric.load_private_key(
            os.path.join(fixtures_dir, 'test.key'))
        issuer_cert = asymmetric.load_certificate(
            os.path.join(fixtures_dir, 'test.crt'))
        subject_cert = asymmetric.load_certificate(
            os.path.join(fixtures_dir, 'test-inter.crt'))

        revoked_time = datetime(2015, 9, 1, 12, 0, 0, tzinfo=timezone.utc)
        builder = OCSPResponseBuilder('successful',
                                      [{
                                          'certificate': subject_cert,
                                          'certificate_status': 'revoked',
                                          'revocation_date': revoked_time
                                      }])
        ocsp_response = builder.build(issuer_key, issuer_cert)
        der_bytes = ocsp_response.dump()

        new_response = asn1crypto.ocsp.OCSPResponse.load(der_bytes)
        basic_response = new_response['response_bytes']['response'].parsed
        response_data = basic_response['tbs_response_data']
        cert_response = response_data['responses'][0]

        self.assertEqual('revoked', cert_response['cert_status'].name)
        self.assertEqual(
            revoked_time,
            cert_response['cert_status'].chosen['revocation_time'].native)
        self.assertEqual(
            'unspecified',
            cert_response['cert_status'].chosen['revocation_reason'].native)
示例#16
0
 def test_private_key_ec_attributes(self):
     private_key = asymmetric.load_private_key(
         os.path.join(fixtures_dir, 'keys/test-ec-named.key'))
     self.assertEqual(256, private_key.bit_size)
     self.assertEqual(32, private_key.byte_size)
     self.assertEqual('secp256r1', private_key.curve)
     self.assertEqual('ec', private_key.algorithm)
    def test_build_no_certificate(self):
        issuer_key = asymmetric.load_private_key(
            os.path.join(fixtures_dir, 'test.key'))
        issuer_cert = asymmetric.load_certificate(
            os.path.join(fixtures_dir, 'test.crt'))
        subject_cert = asymmetric.load_certificate(
            os.path.join(fixtures_dir, 'test-inter.crt'))

        with self.assertRaisesRegexp(
                ValueError,
                'must be set if the response_status is "successful"'):
            builder = OCSPResponseBuilder('successful', subject_cert, 'good')
            builder.certificate = None
            builder.build(issuer_key, issuer_cert)

        with self.assertRaisesRegexp(
                ValueError,
                'must be set if the response_status is "successful"'):
            builder = OCSPResponseBuilder('successful', subject_cert, 'good')
            builder.certificate_status = None
            builder.build(issuer_key, issuer_cert)

        with self.assertRaisesRegexp(
                ValueError,
                'must be set if the response_status is "successful"'):
            builder = OCSPResponseBuilder('successful', subject_cert)
            builder.build(issuer_key, issuer_cert)

        with self.assertRaisesRegexp(
                ValueError,
                'must be set if the response_status is "successful"'):
            builder = OCSPResponseBuilder('successful', None, 'good')
            builder.build(issuer_key, issuer_cert)
    def __init__(self, issuer_cert: str, responder_cert: str, responder_key: str,
                       fault: str, next_update_seconds: int):
        """
        Create a new OCSPResponder instance.

        :param issuer_cert: Path to the issuer certificate.
        :param responder_cert: Path to the certificate of the OCSP responder
            with the `OCSP Signing` extension.
        :param responder_key: Path to the private key belonging to the
            responder cert.
        :param validate_func: A function that - given a certificate serial -
            will return the appropriate :class:`CertificateStatus` and -
            depending on the status - a revocation datetime.
        :param cert_retrieve_func: A function that - given a certificate serial -
            will return the corresponding certificate as a string.
        :param next_update_seconds: The ``nextUpdate`` value that will be written
            into the response. Default: 9 hours.

        """
        # Certs and keys
        self._issuer_cert = asymmetric.load_certificate(issuer_cert)
        self._responder_cert = asymmetric.load_certificate(responder_cert)
        self._responder_key = asymmetric.load_private_key(responder_key)

        # Next update
        self._next_update_seconds = next_update_seconds

        self._fault = fault
示例#19
0
    def setUp(self) -> None:  # pylint: disable=invalid-name,missing-function-docstring
        super().setUp()

        # used for verifying signatures
        key_path = os.path.join(settings.FIXTURES_DIR,
                                ocsp_profile["key_filename"])
        self.ocsp_private_key = asymmetric.load_private_key(key_path)
示例#20
0
def test_demo_plugin():

    with_plugin_cfg = CertomancerConfig.from_file('tests/data/with-plugin.yml',
                                                  'tests/data')

    with_plugin_app = Animator(AnimatorArchStore(with_plugin_cfg.pki_archs),
                               with_web_ui=False)
    client = Client(with_plugin_app, Response)

    # make the endpoint encrypt something
    endpoint = '/testing-ca/plugin/encrypt-echo/test-endpoint'
    payload = b'test test test'
    response = client.post(endpoint, data=payload)

    # decrypt it
    env_data = cms.ContentInfo.load(response.data)['content']
    arch = with_plugin_cfg.get_pki_arch(ArchLabel('testing-ca'))
    key = arch.key_set.get_private_key(KeyLabel('signer1'))
    ktri = env_data['recipient_infos'][0].chosen
    encrypted_key = ktri['encrypted_key'].native

    decrypted_key = asymmetric.rsa_pkcs1v15_decrypt(
        asymmetric.load_private_key(key.dump()), encrypted_key)

    eci = env_data['encrypted_content_info']
    cea = eci['content_encryption_algorithm']
    assert cea['algorithm'].native == 'aes256_cbc'
    iv = cea['parameters'].native
    encrypted_content_bytes = eci['encrypted_content'].native
    decrypted_payload = symmetric.aes_cbc_pkcs7_decrypt(
        decrypted_key, encrypted_content_bytes, iv)
    assert decrypted_payload == payload
示例#21
0
    def test_rsa_private_oaep_decrypt(self):
        original_data = b'This is the message to sign'
        private = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test.key'))

        with open(os.path.join(fixtures_dir, 'rsa_public_encrypted_oaep'), 'rb') as f:
            plaintext = asymmetric.rsa_oaep_decrypt(private, f.read())
            self.assertEqual(original_data, plaintext)
示例#22
0
    def load_key(key_str, key_pass):
        """ Function to load password protected key file in p12 or pem format"""

        try:
            # First try to parse as a p12 file
            key, cert, _ = asymmetric.load_pkcs12(key_str, key_pass)
        except ValueError as e:
            # If it fails due to invalid password raise error here
            if e.args[0] == 'Password provided is invalid':
                raise AS2Exception('Password not valid for Private Key.')

            # if not try to parse as a pem file
            key, cert = None, None
            for kc in split_pem(key_str):
                try:
                    cert = asymmetric.load_certificate(kc)
                except (ValueError, TypeError):
                    try:
                        key = asymmetric.load_private_key(kc, key_pass)
                    except OSError:
                        raise AS2Exception(
                            'Invalid Private Key or password is not correct.')

        if not key or not cert:
            raise AS2Exception(
                'Invalid Private key file or Public key not included.')

        return key, cert
    def test_build_good_response(self):
        issuer_key = asymmetric.load_private_key(os.path.join(fixtures_dir, 'test.key'))
        issuer_cert = asymmetric.load_certificate(os.path.join(fixtures_dir, 'test.crt'))
        subject_cert = asymmetric.load_certificate(os.path.join(fixtures_dir, 'test-inter.crt'))

        builder = OCSPResponseBuilder('successful', subject_cert, 'good')
        ocsp_response = builder.build(issuer_key, issuer_cert)
        der_bytes = ocsp_response.dump()

        new_response = asn1crypto.ocsp.OCSPResponse.load(der_bytes)
        basic_response = new_response['response_bytes']['response'].parsed
        response_data = basic_response['tbs_response_data']

        self.assertEqual('sha256', basic_response['signature_algorithm'].hash_algo)
        self.assertEqual('rsassa_pkcs1v15', basic_response['signature_algorithm'].signature_algo)
        self.assertEqual('v1', response_data['version'].native)
        self.assertEqual('by_key', response_data['responder_id'].name)
        self.assertEqual(
            issuer_cert.asn1.public_key.sha1,
            response_data['responder_id'].chosen.native
        )
        self.assertGreaterEqual(datetime.now(timezone.utc), response_data['produced_at'].native)
        self.assertEqual(1, len(response_data['responses']))
        self.assertEqual(0, len(response_data['response_extensions']))

        cert_response = response_data['responses'][0]

        self.assertEqual('sha1', cert_response['cert_id']['hash_algorithm']['algorithm'].native)
        self.assertEqual(issuer_cert.asn1.subject.sha1, cert_response['cert_id']['issuer_name_hash'].native)
        self.assertEqual(issuer_cert.asn1.public_key.sha1, cert_response['cert_id']['issuer_key_hash'].native)
        self.assertEqual(subject_cert.asn1.serial_number, cert_response['cert_id']['serial_number'].native)

        self.assertEqual('good', cert_response['cert_status'].name)
        self.assertGreaterEqual(datetime.now(timezone.utc), cert_response['this_update'].native)
        self.assertGreaterEqual(set(), cert_response.critical_extensions)
示例#24
0
def self_enroll(skip_notify=False):
    assert os.getuid() == 0 and os.getgid(
    ) == 0, "Can self-enroll only as root"

    from certidude import const, config
    common_name = const.FQDN
    os.umask(0o0177)

    try:
        path, buf, cert, signed, expires = get_signed(common_name)
        self_public_key = asymmetric.load_public_key(path)
        private_key = asymmetric.load_private_key(config.SELF_KEY_PATH)
    except FileNotFoundError:  # certificate or private key not found
        click.echo("Generating private key for frontend: %s" %
                   config.SELF_KEY_PATH)
        with open(config.SELF_KEY_PATH, 'wb') as fh:
            if public_key.algorithm == "ec":
                self_public_key, private_key = asymmetric.generate_pair(
                    "ec", curve=public_key.curve)
            elif public_key.algorithm == "rsa":
                self_public_key, private_key = asymmetric.generate_pair(
                    "rsa", bit_size=public_key.bit_size)
            else:
                raise NotImplemented(
                    "CA certificate public key algorithm %s not supported" %
                    public_key.algorithm)
            fh.write(asymmetric.dump_private_key(private_key, None))
    else:
        now = datetime.utcnow()
        if now + timedelta(days=1) < expires:
            click.echo(
                "Certificate %s still valid, delete to self-enroll again" %
                path)
            return

    builder = CSRBuilder({"common_name": common_name}, self_public_key)
    request = builder.build(private_key)
    pid = os.fork()
    if not pid:
        from certidude import authority, config
        from certidude.common import drop_privileges
        drop_privileges()
        assert os.getuid() != 0 and os.getgid() != 0
        path = os.path.join(config.REQUESTS_DIR, common_name + ".pem")
        click.echo("Writing certificate signing request for frontend: %s" %
                   path)
        with open(path, "wb") as fh:
            fh.write(
                pem_armor_csr(request))  # Write CSR with certidude permissions
        authority.sign(common_name,
                       skip_notify=skip_notify,
                       skip_push=True,
                       overwrite=True,
                       profile=config.PROFILES["srv"])
        click.echo("Frontend certificate signed")
        sys.exit(0)
    else:
        os.waitpid(pid, 0)
        os.system("systemctl reload nginx")
示例#25
0
    def test_ec_public_key_attr(self):
        private = asymmetric.load_private_key(
            os.path.join(fixtures_dir, 'keys/test-ec-named.key'))
        public = asymmetric.load_public_key(
            os.path.join(fixtures_dir, 'keys/test-ec-named.crt'))

        computed_public = private.public_key
        self.assertEqual(public.asn1.dump(), computed_public.asn1.dump())
示例#26
0
    def test_ec_fingerprints(self):
        private = asymmetric.load_private_key(
            os.path.join(fixtures_dir, 'keys/test-ec-named.key'))
        public = asymmetric.load_public_key(
            os.path.join(fixtures_dir, 'keys/test-ec-named.crt'))

        self.assertIsInstance(private.fingerprint, byte_cls)
        self.assertIsInstance(public.fingerprint, byte_cls)
        self.assertEqual(private.fingerprint, public.fingerprint)
示例#27
0
    def test_ecdsa_sign(self):
        original_data = b'This is data to sign'
        private = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test-ec-named.key'))
        public = asymmetric.load_public_key(os.path.join(fixtures_dir, 'keys/test-ec-named.crt'))

        signature = asymmetric.ecdsa_sign(private, original_data, 'sha1')
        self.assertIsInstance(signature, byte_cls)

        asymmetric.ecdsa_verify(public, signature, original_data, 'sha1')
示例#28
0
        def do_run():
            original_data = b'This is data to sign'
            private = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test-dsa.key'))
            public = asymmetric.load_public_key(os.path.join(fixtures_dir, 'keys/test-dsa.crt'))

            signature = asymmetric.dsa_sign(private, original_data, 'sha256')
            self.assertIsInstance(signature, byte_cls)

            asymmetric.dsa_verify(public, signature, original_data, 'sha256')
示例#29
0
    def test_rsa_raw_sign(self):
        original_data = b'This is data to sign!'
        private = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test.key'))
        public = asymmetric.load_public_key(os.path.join(fixtures_dir, 'keys/test.crt'))

        signature = asymmetric.rsa_pkcs1v15_sign(private, original_data, 'raw')
        self.assertIsInstance(signature, byte_cls)

        asymmetric.rsa_pkcs1v15_verify(public, signature, original_data, 'raw')
示例#30
0
        def do_run():
            original_data = b'This is data to sign'
            private = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test-dsa.key'))
            public = asymmetric.load_public_key(os.path.join(fixtures_dir, 'keys/test-dsa.crt'))

            signature = asymmetric.dsa_sign(private, original_data, 'sha256')
            self.assertIsInstance(signature, byte_cls)

            asymmetric.dsa_verify(public, signature, original_data, 'sha256')
示例#31
0
    def test_rsa_raw_sign(self):
        original_data = b'This is data to sign!'
        private = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test.key'))
        public = asymmetric.load_public_key(os.path.join(fixtures_dir, 'keys/test.crt'))

        signature = asymmetric.rsa_pkcs1v15_sign(private, original_data, 'raw')
        self.assertIsInstance(signature, byte_cls)

        asymmetric.rsa_pkcs1v15_verify(public, signature, original_data, 'raw')
示例#32
0
    def test_ecdsa_sign(self):
        original_data = b'This is data to sign'
        private = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test-ec-named.key'))
        public = asymmetric.load_public_key(os.path.join(fixtures_dir, 'keys/test-ec-named.crt'))

        signature = asymmetric.ecdsa_sign(private, original_data, 'sha1')
        self.assertIsInstance(signature, byte_cls)

        asymmetric.ecdsa_verify(public, signature, original_data, 'sha1')
示例#33
0
    def setUpClass(cls):
        super(OCSPTestView, cls).setUpClass()

        logging.disable(logging.CRITICAL)
        cls.client = Client()
        cls.ocsp_cert = cls.load_cert(ca=cls.ca, x509=ocsp_pubkey)

        # used for verifying signatures
        cls.ocsp_private_key = asymmetric.load_private_key(ocsp_key_path)
    def test_build_revoked_response(self):
        issuer_key = asymmetric.load_private_key(
            os.path.join(fixtures_dir, 'test.key'))
        issuer_cert = asymmetric.load_certificate(
            os.path.join(fixtures_dir, 'test.crt'))
        subject_cert = asymmetric.load_certificate(
            os.path.join(fixtures_dir, 'test-inter.crt'))

        revoked_time = datetime(2015, 9, 1, 12, 0, 0, tzinfo=timezone.utc)
        builder = OCSPResponseBuilder(
            'successful', [{
                'certificate': subject_cert,
                'certificate_status': 'key_compromise',
                'revocation_date': revoked_time
            }])
        ocsp_response = builder.build(issuer_key, issuer_cert)
        der_bytes = ocsp_response.dump()

        new_response = asn1crypto.ocsp.OCSPResponse.load(der_bytes)
        basic_response = new_response['response_bytes']['response'].parsed
        response_data = basic_response['tbs_response_data']

        self.assertEqual('sha256',
                         basic_response['signature_algorithm'].hash_algo)
        self.assertEqual('rsassa_pkcs1v15',
                         basic_response['signature_algorithm'].signature_algo)
        self.assertEqual('v1', response_data['version'].native)
        self.assertEqual('by_key', response_data['responder_id'].name)
        self.assertEqual(issuer_cert.asn1.public_key.sha1,
                         response_data['responder_id'].chosen.native)
        self.assertGreaterEqual(datetime.now(timezone.utc),
                                response_data['produced_at'].native)
        self.assertEqual(1, len(response_data['responses']))
        self.assertEqual(0, len(response_data['response_extensions']))

        cert_response = response_data['responses'][0]

        self.assertEqual(
            'sha1',
            cert_response['cert_id']['hash_algorithm']['algorithm'].native)
        self.assertEqual(issuer_cert.asn1.subject.sha1,
                         cert_response['cert_id']['issuer_name_hash'].native)
        self.assertEqual(issuer_cert.asn1.public_key.sha1,
                         cert_response['cert_id']['issuer_key_hash'].native)
        self.assertEqual(subject_cert.asn1.serial_number,
                         cert_response['cert_id']['serial_number'].native)

        self.assertEqual('revoked', cert_response['cert_status'].name)
        self.assertEqual(
            revoked_time,
            cert_response['cert_status'].chosen['revocation_time'].native)
        self.assertEqual(
            'key_compromise',
            cert_response['cert_status'].chosen['revocation_reason'].native)
        self.assertGreaterEqual(datetime.now(timezone.utc),
                                cert_response['this_update'].native)
        self.assertGreaterEqual(set(), cert_response.critical_extensions)
示例#35
0
    def setUp(self):  # pylint: disable=invalid-name,missing-function-docstring
        super().setUp()

        self.client = Client()  # we want to be anonymous

        # used for verifying signatures
        key_path = os.path.join(settings.FIXTURES_DIR,
                                ocsp_profile['key_filename'])
        self.ocsp_private_key = asymmetric.load_private_key(key_path)
示例#36
0
def self_enroll():
    assert os.getuid() == 0 and os.getgid(
    ) == 0, "Can self-enroll only as root"

    from certidude import const
    common_name = const.FQDN
    directory = os.path.join("/var/lib/certidude", const.FQDN)
    self_key_path = os.path.join(directory, "self_key.pem")

    try:
        path, buf, cert, signed, expires = get_signed(common_name)
        self_public_key = asymmetric.load_public_key(path)
        private_key = asymmetric.load_private_key(self_key_path)
    except FileNotFoundError:  # certificate or private key not found
        with open(self_key_path, 'wb') as fh:
            if public_key.algorithm == "ec":
                self_public_key, private_key = asymmetric.generate_pair(
                    "ec", curve=public_key.curve)
            elif public_key.algorithm == "rsa":
                self_public_key, private_key = asymmetric.generate_pair(
                    "rsa", bit_size=public_key.bit_size)
            else:
                NotImplemented
            fh.write(asymmetric.dump_private_key(private_key, None))
    else:
        now = datetime.utcnow()
        if now + timedelta(days=1) < expires:
            click.echo(
                "Certificate %s still valid, delete to self-enroll again" %
                path)
            return

    builder = CSRBuilder({"common_name": common_name}, self_public_key)
    request = builder.build(private_key)
    pid = os.fork()
    if not pid:
        from certidude import authority
        from certidude.common import drop_privileges
        drop_privileges()
        assert os.getuid() != 0 and os.getgid() != 0
        path = os.path.join(directory, "requests", common_name + ".pem")
        click.echo("Writing request to %s" % path)
        with open(path, "wb") as fh:
            fh.write(
                pem_armor_csr(request))  # Write CSR with certidude permissions
        authority.sign(common_name,
                       skip_push=True,
                       overwrite=True,
                       profile=config.PROFILES["srv"])
        sys.exit(0)
    else:
        os.waitpid(pid, 0)
        if os.path.exists("/etc/systemd"):
            os.system("systemctl reload nginx")
        else:
            os.system("service nginx reload")
示例#37
0
    def test_rsa_oaep_encrypt(self):
        original_data = b'This is data to encrypt'
        private = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test.key'))
        public = asymmetric.load_public_key(os.path.join(fixtures_dir, 'keys/test.crt'))

        ciphertext = asymmetric.rsa_oaep_encrypt(public, original_data)
        self.assertIsInstance(ciphertext, byte_cls)

        plaintext = asymmetric.rsa_oaep_decrypt(private, ciphertext)
        self.assertEqual(original_data, plaintext)
示例#38
0
    def setUpClass(cls):
        super(OCSPViewTestMixin, cls).setUpClass()

        logging.disable(logging.CRITICAL)
        cls.client = Client()
        cls.ocsp_cert = cls.load_cert(ca=cls.ca, x509=ocsp_pubkey)

        # used for verifying signatures
        cls.ocsp_private_key = asymmetric.load_private_key(
            force_text(settings.OCSP_KEY_PATH))
示例#39
0
    def test_rsa_oaep_encrypt(self):
        original_data = b'This is data to encrypt'
        private = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test.key'))
        public = asymmetric.load_public_key(os.path.join(fixtures_dir, 'keys/test.crt'))

        ciphertext = asymmetric.rsa_oaep_encrypt(public, original_data)
        self.assertIsInstance(ciphertext, byte_cls)

        plaintext = asymmetric.rsa_oaep_decrypt(private, ciphertext)
        self.assertEqual(original_data, plaintext)
示例#40
0
    def setUp(self):
        super(OCSPViewTestMixin, self).setUp()

        self.client = Client()

        # used for verifying signatures
        ocsp_key_path = os.path.join(settings.FIXTURES_DIR,
                                     ocsp_profile['key_filename'])
        self.ocsp_private_key = asymmetric.load_private_key(
            force_text(ocsp_key_path))
示例#41
0
    def _read_key(self, path):
        # type: (str) -> str
        try:
            privkey = asymmetric.load_private_key(path)
        except Exception as e:
            raise CommandError("Error reading private key at {}: {}".format(path, e))

        key_pem = asymmetric.dump_private_key(privkey, None, 'pem')

        return key_pem
    def test_build_basic_crl(self):
        root_private_key = asymmetric.load_private_key(os.path.join(fixtures_dir, "root.key"), "password123")
        root_certificate = asymmetric.load_certificate(os.path.join(fixtures_dir, "root.crt"))

        builder = CertificateListBuilder("http://crl.example.com", root_certificate, 50000)
        revoked_at = datetime(2015, 8, 1, 12, 0, 0, tzinfo=timezone.utc)
        builder.add_certificate(29232181, revoked_at, "key_compromise")
        certificate_list = builder.build(root_private_key)
        der_bytes = certificate_list.dump()

        new_cert_list = crl.CertificateList.load(der_bytes)
        tbs_cert_list = new_cert_list["tbs_cert_list"]
        revoked_certificates = tbs_cert_list["revoked_certificates"]

        now = datetime.now(timezone.utc)

        self.assertEqual("v3", tbs_cert_list["version"].native)
        self.assertEqual("rsassa_pkcs1v15", tbs_cert_list["signature"].signature_algo)
        self.assertEqual("sha256", tbs_cert_list["signature"].hash_algo)
        self.assertEqual(root_certificate.asn1.subject, tbs_cert_list["issuer"])
        self.assertEqual(root_certificate.asn1.subject.sha256, tbs_cert_list["issuer"].sha256)
        self.assertGreaterEqual(now, tbs_cert_list["this_update"].native)
        self.assertLess(now, tbs_cert_list["next_update"].native)
        self.assertEqual(set(["issuing_distribution_point"]), new_cert_list.critical_extensions)

        self.assertEqual(1, len(revoked_certificates))
        revoked_cert = revoked_certificates[0]
        self.assertEqual(29232181, revoked_cert["user_certificate"].native)
        self.assertEqual(revoked_at, revoked_cert["revocation_date"].native)
        self.assertEqual(set(), revoked_cert.critical_extensions)
        self.assertEqual("key_compromise", revoked_cert.crl_reason_value.native)
        self.assertEqual(None, revoked_cert.invalidity_date_value)
        self.assertEqual(None, revoked_cert.certificate_issuer_value)
        self.assertEqual(None, revoked_cert.issuer_name)

        self.assertEqual(None, new_cert_list.issuer_alt_name_value)
        self.assertEqual(50000, new_cert_list.crl_number_value.native)
        self.assertEqual(None, new_cert_list.delta_crl_indicator_value)
        self.assertEqual("full_name", new_cert_list.issuing_distribution_point_value["distribution_point"].name)
        self.assertEqual(
            "uniform_resource_identifier",
            new_cert_list.issuing_distribution_point_value["distribution_point"].chosen[0].name,
        )
        self.assertEqual(
            "http://crl.example.com",
            new_cert_list.issuing_distribution_point_value["distribution_point"].chosen[0].native,
        )
        self.assertEqual(root_certificate.asn1.key_identifier, new_cert_list.authority_key_identifier)
        self.assertEqual(None, new_cert_list.freshest_crl_value)
        self.assertEqual(None, new_cert_list.authority_information_access_value)
    def test_build_delta_crl(self):
        root_certificate = asymmetric.load_certificate(os.path.join(fixtures_dir, "root.crt"))

        crl_issuer_private_key = asymmetric.load_private_key(
            os.path.join(fixtures_dir, "crl_issuer.key"), "password123"
        )
        crl_issuer_certificate = asymmetric.load_certificate(os.path.join(fixtures_dir, "crl_issuer.crt"))

        builder = CertificateListBuilder("http://crl.example.com/delta", crl_issuer_certificate, 50001)
        builder.certificate_issuer = root_certificate
        builder.issuer_certificate_url = "http://download.example.com/crl_issuer"
        builder.delta_of = 50000

        certificate_list = builder.build(crl_issuer_private_key)
        der_bytes = certificate_list.dump()

        new_cert_list = crl.CertificateList.load(der_bytes)
        tbs_cert_list = new_cert_list["tbs_cert_list"]
        revoked_certificates = tbs_cert_list["revoked_certificates"]

        now = datetime.now(timezone.utc)

        self.assertEqual("v3", tbs_cert_list["version"].native)
        self.assertEqual("rsassa_pkcs1v15", tbs_cert_list["signature"].signature_algo)
        self.assertEqual("sha256", tbs_cert_list["signature"].hash_algo)
        self.assertEqual(crl_issuer_certificate.asn1.subject, tbs_cert_list["issuer"])
        self.assertEqual(crl_issuer_certificate.asn1.subject.sha256, tbs_cert_list["issuer"].sha256)
        self.assertGreaterEqual(now, tbs_cert_list["this_update"].native)
        self.assertLess(now, tbs_cert_list["next_update"].native)
        self.assertEqual(set(["issuing_distribution_point", "delta_crl_indicator"]), new_cert_list.critical_extensions)

        self.assertEqual(0, len(revoked_certificates))

        self.assertEqual(None, new_cert_list.issuer_alt_name_value)
        self.assertEqual(50001, new_cert_list.crl_number_value.native)
        self.assertEqual(50000, new_cert_list.delta_crl_indicator_value.native)
        self.assertEqual("full_name", new_cert_list.issuing_distribution_point_value["distribution_point"].name)
        self.assertEqual(
            "uniform_resource_identifier",
            new_cert_list.issuing_distribution_point_value["distribution_point"].chosen[0].name,
        )
        self.assertEqual(
            "http://crl.example.com/delta",
            new_cert_list.issuing_distribution_point_value["distribution_point"].chosen[0].native,
        )
        self.assertEqual(crl_issuer_certificate.asn1.key_identifier, new_cert_list.authority_key_identifier)
        self.assertEqual([], new_cert_list.delta_crl_distribution_points)
        self.assertEqual(["http://download.example.com/crl_issuer"], new_cert_list.issuer_cert_urls)
    def test_build_revoked_no_reason(self):
        issuer_key = asymmetric.load_private_key(os.path.join(fixtures_dir, 'test.key'))
        issuer_cert = asymmetric.load_certificate(os.path.join(fixtures_dir, 'test.crt'))
        subject_cert = asymmetric.load_certificate(os.path.join(fixtures_dir, 'test-inter.crt'))

        revoked_time = datetime(2015, 9, 1, 12, 0, 0, tzinfo=timezone.utc)
        builder = OCSPResponseBuilder('successful', subject_cert, 'revoked', revoked_time)
        ocsp_response = builder.build(issuer_key, issuer_cert)
        der_bytes = ocsp_response.dump()

        new_response = asn1crypto.ocsp.OCSPResponse.load(der_bytes)
        basic_response = new_response['response_bytes']['response'].parsed
        response_data = basic_response['tbs_response_data']
        cert_response = response_data['responses'][0]

        self.assertEqual('revoked', cert_response['cert_status'].name)
        self.assertEqual(revoked_time, cert_response['cert_status'].chosen['revocation_time'].native)
        self.assertEqual('unspecified', cert_response['cert_status'].chosen['revocation_reason'].native)
    def test_build_no_certificate(self):
        issuer_key = asymmetric.load_private_key(os.path.join(fixtures_dir, 'test.key'))
        issuer_cert = asymmetric.load_certificate(os.path.join(fixtures_dir, 'test.crt'))
        subject_cert = asymmetric.load_certificate(os.path.join(fixtures_dir, 'test-inter.crt'))

        with self.assertRaisesRegexp(ValueError, 'must be set if the response_status is "successful"'):
            builder = OCSPResponseBuilder('successful', subject_cert, 'good')
            builder.certificate = None
            ocsp_response = builder.build(issuer_key, issuer_cert)

        with self.assertRaisesRegexp(ValueError, 'must be set if the response_status is "successful"'):
            builder = OCSPResponseBuilder('successful', subject_cert, 'good')
            builder.certificate_status = None
            ocsp_response = builder.build(issuer_key, issuer_cert)

        with self.assertRaisesRegexp(ValueError, 'must be set if the response_status is "successful"'):
            builder = OCSPResponseBuilder('successful', subject_cert)
            ocsp_response = builder.build(issuer_key, issuer_cert)

        with self.assertRaisesRegexp(ValueError, 'must be set if the response_status is "successful"'):
            builder = OCSPResponseBuilder('successful', None, 'good')
            ocsp_response = builder.build(issuer_key, issuer_cert)
示例#46
0
    def __init__(self, issuer_cert: str, responder_cert: str, responder_key: str,
                       validate_func: ValidateFunc, cert_retrieve_func: CertRetrieveFunc,
                       next_update_days: int = 7):
        """
        Create a new OCSPResponder instance.

        :param issuer_cert: Path to the issuer certificate.
        :param responder_cert: Path to the certificate of the OCSP responder
            with the `OCSP Signing` extension.
        :param responder_key: Path to the private key belonging to the
            responder cert.
        :param validate_func: A function that - given a certificate serial -
            will return the appropriate :class:`CertificateStatus` and -
            depending on the status - a revocation datetime.
        :param cert_retrieve_func: A function that - given a certificate serial -
            will return the corresponding certificate as a string.
        :param next_update_days: The ``nextUpdate`` value that will be written
            into the response. Default: 7 days.

        """
        # Certs and keys
        self._issuer_cert = asymmetric.load_certificate(issuer_cert)
        self._responder_cert = asymmetric.load_certificate(responder_cert)
        self._responder_key = asymmetric.load_private_key(responder_key)

        # Functions
        self._validate = validate_func
        self._cert_retrieve = cert_retrieve_func

        # Next update
        self._next_update_days = next_update_days

        # Bottle
        self._app = Bottle()

        # Initialize routing
        self._route()
示例#47
0
 def test_dump_private_openssl(self):
     private = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test.key'))
     pem_serialized = asymmetric.dump_openssl_private_key(private, 'password123')
     private_reloaded = asymmetric.load_private_key(pem_serialized, 'password123')
     self.assertIsInstance(private_reloaded, asymmetric.PrivateKey)
     self.assertEqual('rsa', private_reloaded.algorithm)
示例#48
0
 def test_private_key_attributes(self):
     private_key = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test.key'))
     self.assertEqual(2048, private_key.bit_size)
     self.assertEqual(256, private_key.byte_size)
     self.assertEqual('rsa', private_key.algorithm)
示例#49
0
 def test_private_key_ec_attributes(self):
     private_key = asymmetric.load_private_key(os.path.join(fixtures_dir, 'keys/test-ec-named.key'))
     self.assertEqual(256, private_key.bit_size)
     self.assertEqual(32, private_key.byte_size)
     self.assertEqual('secp256r1', private_key.curve)
     self.assertEqual('ec', private_key.algorithm)
示例#50
0
# coding: utf-8
from __future__ import unicode_literals, division, absolute_import, print_function

import os

from oscrypto import asymmetric
from certbuilder import CertificateBuilder


fixtures_dir = os.path.join(os.path.dirname(__file__), '..', 'tests', 'fixtures')


root_ca_private_key = asymmetric.load_private_key(os.path.join(fixtures_dir, 'test.key'))
root_ca_certificate = asymmetric.load_certificate(os.path.join(fixtures_dir, 'test.crt'))

root_ocsp_public_key, root_ocsp_private_key = asymmetric.generate_pair('rsa', bit_size=2048)

with open(os.path.join(fixtures_dir, 'test-ocsp.key'), 'wb') as f:
    f.write(asymmetric.dump_private_key(root_ocsp_private_key, 'password', target_ms=20))

builder = CertificateBuilder(
    {
        'country_name': 'US',
        'state_or_province_name': 'Massachusetts',
        'locality_name': 'Newbury',
        'organization_name': 'Codex Non Sufficit LC',
        'organization_unit_name': 'Testing',
        'common_name': 'CodexNS OCSP Responder',
    },
    root_ocsp_public_key
)
示例#51
0
    def build(self, issuer_private_key):
        """
        Validates the certificate list information, constructs the ASN.1
        structure and then signs it

        :param issuer_private_key:
            An asn1crypto.keys.PrivateKeyInfo or oscrypto.asymmetric.PrivateKey
            object for the private key of the CRL issuer

        :return:
            An asn1crypto.crl.CertificateList object of the newly signed CRL
        """

        is_oscrypto = isinstance(issuer_private_key, asymmetric.PrivateKey)
        if not isinstance(issuer_private_key, keys.PrivateKeyInfo) and not is_oscrypto:
            raise TypeError(_pretty_message(
                '''
                issuer_private_key must be an instance of
                asn1crypto.keys.PrivateKeyInfo or
                oscrypto.asymmetric.PrivateKey, not %s
                ''',
                _type_name(issuer_private_key)
            ))

        if self._this_update is None:
            self._this_update = datetime.now(timezone.utc)

        if self._next_update is None:
            self._next_update = self._this_update + timedelta(days=7)

        signature_algo = issuer_private_key.algorithm
        if signature_algo == 'ec':
            signature_algo = 'ecdsa'

        signature_algorithm_id = '%s_%s' % (self._hash_algo, signature_algo)

        def _make_extension(name, value):
            return {
                'extn_id': name,
                'critical': self._determine_critical(name),
                'extn_value': value
            }

        extensions = []
        for name in sorted(self._special_extensions):
            value = getattr(self, '_%s' % name)
            if value is not None:
                extensions.append(_make_extension(name, value))

        for name in sorted(self._other_extensions.keys()):
            extensions.append(_make_extension(name, self._other_extensions[name]))

        # For an indirect CRL we need to set the first
        if self._certificate_issuer and len(self._revoked_certificates) > 0:
            self._revoked_certificates[0]['crl_entry_extensions'].append({
                'extn_id': 'certificate_issuer',
                'critical': True,
                'extn_value': x509.GeneralNames([
                    x509.GeneralName(
                        name='directory_name',
                        value=self._certificate_issuer.subject
                    )
                ])
            })

        tbs_cert_list = crl.TbsCertList({
            'version': 'v3',
            'signature': {
                'algorithm': signature_algorithm_id
            },
            'issuer': self._issuer.subject,
            'this_update': x509.Time(name='utc_time', value=self._this_update),
            'next_update': x509.Time(name='utc_time', value=self._next_update),
            'revoked_certificates': crl.RevokedCertificates(self._revoked_certificates),
            'crl_extensions': extensions
        })

        if issuer_private_key.algorithm == 'rsa':
            sign_func = asymmetric.rsa_pkcs1v15_sign
        elif issuer_private_key.algorithm == 'dsa':
            sign_func = asymmetric.dsa_sign
        elif issuer_private_key.algorithm == 'ec':
            sign_func = asymmetric.ecdsa_sign

        if not is_oscrypto:
            issuer_private_key = asymmetric.load_private_key(issuer_private_key)
        signature = sign_func(issuer_private_key, tbs_cert_list.dump(), self._hash_algo)

        return crl.CertificateList({
            'tbs_cert_list': tbs_cert_list,
            'signature_algorithm': {
                'algorithm': signature_algorithm_id
            },
            'signature': signature
        })
示例#52
0
    def build(self, responder_private_key=None, responder_certificate=None):
        """
        Validates the request information, constructs the ASN.1 structure and
        signs it.

        The responder_private_key and responder_certificate parameters are only
        required if the response_status is "successful".

        :param responder_private_key:
            An asn1crypto.keys.PrivateKeyInfo or oscrypto.asymmetric.PrivateKey
            object for the private key to sign the response with

        :param responder_certificate:
            An asn1crypto.x509.Certificate or oscrypto.asymmetric.Certificate
            object of the certificate associated with the private key

        :return:
            An asn1crypto.ocsp.OCSPResponse object of the response
        """

        if self._response_status != 'successful':
            return ocsp.OCSPResponse({
                'response_status': self._response_status
            })

        is_oscrypto = isinstance(responder_private_key, asymmetric.PrivateKey)
        if not isinstance(responder_private_key, keys.PrivateKeyInfo) and not is_oscrypto:
            raise TypeError(_pretty_message(
                '''
                responder_private_key must be an instance of
                asn1crypto.keys.PrivateKeyInfo or
                oscrypto.asymmetric.PrivateKey, not %s
                ''',
                _type_name(responder_private_key)
            ))

        cert_is_oscrypto = isinstance(responder_certificate, asymmetric.Certificate)
        if not isinstance(responder_certificate, x509.Certificate) and not cert_is_oscrypto:
            raise TypeError(_pretty_message(
                '''
                responder_certificate must be an instance of
                asn1crypto.x509.Certificate or
                oscrypto.asymmetric.Certificate, not %s
                ''',
                _type_name(responder_certificate)
            ))

        if cert_is_oscrypto:
            responder_certificate = responder_certificate.asn1

        if self._certificate is None:
            raise ValueError(_pretty_message(
                '''
                certificate must be set if the response_status is
                "successful"
                '''
            ))
        if self._certificate_status is None:
            raise ValueError(_pretty_message(
                '''
                certificate_status must be set if the response_status is
                "successful"
                '''
            ))

        def _make_extension(name, value):
            return {
                'extn_id': name,
                'critical': False,
                'extn_value': value
            }

        response_data_extensions = []
        single_response_extensions = []

        for name, value in self._response_data_extensions.items():
            response_data_extensions.append(_make_extension(name, value))
        if self._nonce:
            response_data_extensions.append(
                _make_extension('nonce', self._nonce)
            )

        if not response_data_extensions:
            response_data_extensions = None

        for name, value in self._single_response_extensions.items():
            single_response_extensions.append(_make_extension(name, value))

        if self._certificate_issuer:
            single_response_extensions.append(
                _make_extension(
                    'certificate_issuer',
                    [
                        x509.GeneralName(
                            name='directory_name',
                            value=self._certificate_issuer.subject
                        )
                    ]
                )
            )

        if not single_response_extensions:
            single_response_extensions = None

        responder_key_hash = getattr(responder_certificate.public_key, self._key_hash_algo)

        if self._certificate_status == 'good':
            cert_status = ocsp.CertStatus(
                name='good',
                value=core.Null()
            )
        elif self._certificate_status == 'unknown':
            cert_status = ocsp.CertStatus(
                name='unknown',
                value=core.Null()
            )
        else:
            status = self._certificate_status
            reason = status if status != 'revoked' else 'unspecified'
            cert_status = ocsp.CertStatus(
                name='revoked',
                value={
                    'revocation_time': self._revocation_date,
                    'revocation_reason': reason,
                }
            )

        issuer = self._certificate_issuer if self._certificate_issuer else responder_certificate
        if issuer.subject != self._certificate.issuer:
            raise ValueError(_pretty_message(
                '''
                responder_certificate does not appear to be the issuer for
                the certificate. Perhaps set the .certificate_issuer attribute?
                '''
            ))

        produced_at = datetime.now(timezone.utc)

        if self._this_update is None:
            self._this_update = produced_at

        if self._next_update is None:
            self._next_update = self._this_update + timedelta(days=7)

        response_data = ocsp.ResponseData({
            'responder_id': ocsp.ResponderId(name='by_key', value=responder_key_hash),
            'produced_at': produced_at,
            'responses': [
                {
                    'cert_id': {
                        'hash_algorithm': {
                            'algorithm': self._key_hash_algo
                        },
                        'issuer_name_hash': getattr(self._certificate.issuer, self._key_hash_algo),
                        'issuer_key_hash': getattr(issuer.public_key, self._key_hash_algo),
                        'serial_number': self._certificate.serial_number,
                    },
                    'cert_status': cert_status,
                    'this_update': self._this_update,
                    'next_update': self._next_update,
                    'single_extensions': single_response_extensions
                }
            ],
            'response_extensions': response_data_extensions
        })

        signature_algo = responder_private_key.algorithm
        if signature_algo == 'ec':
            signature_algo = 'ecdsa'

        signature_algorithm_id = '%s_%s' % (self._hash_algo, signature_algo)

        if responder_private_key.algorithm == 'rsa':
            sign_func = asymmetric.rsa_pkcs1v15_sign
        elif responder_private_key.algorithm == 'dsa':
            sign_func = asymmetric.dsa_sign
        elif responder_private_key.algorithm == 'ec':
            sign_func = asymmetric.ecdsa_sign

        if not is_oscrypto:
            responder_private_key = asymmetric.load_private_key(responder_private_key)
        signature_bytes = sign_func(responder_private_key, response_data.dump(), self._hash_algo)

        certs = None
        if self._certificate_issuer:
            certs = [responder_certificate]

        return ocsp.OCSPResponse({
            'response_status': self._response_status,
            'response_bytes': {
                'response_type': 'basic_ocsp_response',
                'response': {
                    'tbs_response_data': response_data,
                    'signature_algorithm': {'algorithm': signature_algorithm_id},
                    'signature': signature_bytes,
                    'certs': certs
                }
            }
        })
示例#53
0
    def build(self, signing_private_key):
        """
        Validates the certificate information, constructs an X.509 certificate
        and then signs it

        :param signing_private_key:
            An asn1crypto.keys.PrivateKeyInfo or oscrypto.asymmetric.PrivateKey
            object for the private key to sign the request with. This should be
            the private key that matches the public key.

        :return:
            An asn1crypto.csr.CertificationRequest object of the request
        """

        is_oscrypto = isinstance(signing_private_key, asymmetric.PrivateKey)
        if not isinstance(signing_private_key, keys.PrivateKeyInfo) and not is_oscrypto:
            raise TypeError(_pretty_message(
                '''
                signing_private_key must be an instance of
                asn1crypto.keys.PrivateKeyInfo or
                oscrypto.asymmetric.PrivateKey, not %s
                ''',
                _type_name(signing_private_key)
            ))

        signature_algo = signing_private_key.algorithm
        if signature_algo == 'ec':
            signature_algo = 'ecdsa'

        signature_algorithm_id = '%s_%s' % (self._hash_algo, signature_algo)

        def _make_extension(name, value):
            return {
                'extn_id': name,
                'critical': self._determine_critical(name),
                'extn_value': value
            }

        extensions = []
        for name in sorted(self._special_extensions):
            value = getattr(self, '_%s' % name)
            if value is not None:
                extensions.append(_make_extension(name, value))

        for name in sorted(self._other_extensions.keys()):
            extensions.append(_make_extension(name, self._other_extensions[name]))

        attributes = []
        if extensions:
            attributes.append({
                'type': 'extension_request',
                'values': [extensions]
            })

        certification_request_info = csr.CertificationRequestInfo({
            'version': 'v1',
            'subject': self._subject,
            'subject_pk_info': self._subject_public_key,
            'attributes': attributes
        })

        if signing_private_key.algorithm == 'rsa':
            sign_func = asymmetric.rsa_pkcs1v15_sign
        elif signing_private_key.algorithm == 'dsa':
            sign_func = asymmetric.dsa_sign
        elif signing_private_key.algorithm == 'ec':
            sign_func = asymmetric.ecdsa_sign

        if not is_oscrypto:
            signing_private_key = asymmetric.load_private_key(signing_private_key)
        signature = sign_func(signing_private_key, certification_request_info.dump(), self._hash_algo)

        return csr.CertificationRequest({
            'certification_request_info': certification_request_info,
            'signature_algorithm': {
                'algorithm': signature_algorithm_id,
            },
            'signature': signature
        })
示例#54
0
    def build(self, signing_private_key):
        """
        Validates the certificate information, constructs an X.509 certificate
        and then signs it

        :param signing_private_key:
            An asn1crypto.keys.PrivateKeyInfo or oscrypto.asymmetric.PrivateKey
            object for the private key to sign the request with. This should be
            the private key that matches the public key.

        :return:
            An asn1crypto.csr.CertificationRequest object of the request
        """

        is_oscrypto = isinstance(signing_private_key, asymmetric.PrivateKey)
        if not isinstance(signing_private_key, keys.PrivateKeyInfo) and not is_oscrypto:
            raise TypeError(
                _pretty_message(
                    """
                signing_private_key must be an instance of
                asn1crypto.keys.PrivateKeyInfo or
                oscrypto.asymmetric.PrivateKey, not %s
                """,
                    _type_name(signing_private_key),
                )
            )

        signature_algo = signing_private_key.algorithm
        if signature_algo == "ec":
            signature_algo = "ecdsa"

        signature_algorithm_id = "%s_%s" % (self._hash_algo, signature_algo)

        def _make_extension(name, value):
            return {"extn_id": name, "critical": self._determine_critical(name), "extn_value": value}

        extensions = []
        for name in sorted(self._special_extensions):
            value = getattr(self, "_%s" % name)
            if value is not None:
                extensions.append(_make_extension(name, value))

        for name in sorted(self._other_extensions.keys()):
            extensions.append(_make_extension(name, self._other_extensions[name]))

        attributes = []
        if extensions:
            attributes.append({"type": "extension_request", "values": [extensions]})

        certification_request_info = csr.CertificationRequestInfo(
            {
                "version": "v1",
                "subject": self._subject,
                "subject_pk_info": self._subject_public_key,
                "attributes": attributes,
            }
        )

        if signing_private_key.algorithm == "rsa":
            sign_func = asymmetric.rsa_pkcs1v15_sign
        elif signing_private_key.algorithm == "dsa":
            sign_func = asymmetric.dsa_sign
        elif signing_private_key.algorithm == "ec":
            sign_func = asymmetric.ecdsa_sign

        if not is_oscrypto:
            signing_private_key = asymmetric.load_private_key(signing_private_key)
        signature = sign_func(signing_private_key, certification_request_info.dump(), self._hash_algo)

        return csr.CertificationRequest(
            {
                "certification_request_info": certification_request_info,
                "signature_algorithm": {"algorithm": signature_algorithm_id},
                "signature": signature,
            }
        )
示例#55
0
    def build(self, requestor_private_key=None, requestor_certificate=None, other_certificates=None):
        """
        Validates the request information, constructs the ASN.1 structure and
        then optionally signs it.

        The requestor_private_key, requestor_certificate and other_certificates
        params are all optional and only necessary if the request needs to be
        signed. Signing a request is uncommon for OCSP requests related to web
        TLS connections.

        :param requestor_private_key:
            An asn1crypto.keys.PrivateKeyInfo or oscrypto.asymmetric.PrivateKey
            object for the private key to sign the request with

        :param requestor_certificate:
            An asn1crypto.x509.Certificate or oscrypto.asymmetric.Certificate
            object of the certificate associated with the private key

        :param other_certificates:
            A list of asn1crypto.x509.Certificate or
            oscrypto.asymmetric.Certificate objects that may be useful for the
            OCSP server to verify the request signature. Intermediate
            certificates would be specified here.

        :return:
            An asn1crypto.ocsp.OCSPRequest object of the request
        """

        def _make_extension(name, value):
            return {
                'extn_id': name,
                'critical': False,
                'extn_value': value
            }

        tbs_request_extensions = []
        request_extensions = []
        has_nonce = False

        for name, value in self._tbs_request_extensions.items():
            if name == 'nonce':
                has_nonce = True
            tbs_request_extensions.append(_make_extension(name, value))
        if self._nonce and not has_nonce:
            tbs_request_extensions.append(
                _make_extension('nonce', util.rand_bytes(16))
            )

        if not tbs_request_extensions:
            tbs_request_extensions = None

        for name, value in self._request_extensions.items():
            request_extensions.append(_make_extension(name, value))

        if not request_extensions:
            request_extensions = None

        tbs_request = ocsp.TBSRequest({
            'request_list': [
                {
                    'req_cert': {
                        'hash_algorithm': {
                            'algorithm': self._key_hash_algo
                        },
                        'issuer_name_hash': getattr(self._certificate.issuer, self._key_hash_algo),
                        'issuer_key_hash': getattr(self._issuer.public_key, self._key_hash_algo),
                        'serial_number': self._certificate.serial_number,
                    },
                    'single_request_extensions': request_extensions
                }
            ],
            'request_extensions': tbs_request_extensions
        })
        signature = None

        if requestor_private_key or requestor_certificate or other_certificates:
            is_oscrypto = isinstance(requestor_private_key, asymmetric.PrivateKey)
            if not isinstance(requestor_private_key, keys.PrivateKeyInfo) and not is_oscrypto:
                raise TypeError(_pretty_message(
                    '''
                    requestor_private_key must be an instance of
                    asn1crypto.keys.PrivateKeyInfo or
                    oscrypto.asymmetric.PrivateKey, not %s
                    ''',
                    _type_name(requestor_private_key)
                ))

            cert_is_oscrypto = isinstance(requestor_certificate, asymmetric.Certificate)
            if not isinstance(requestor_certificate, x509.Certificate) and not cert_is_oscrypto:
                raise TypeError(_pretty_message(
                    '''
                    requestor_certificate must be an instance of
                    asn1crypto.x509.Certificate or
                    oscrypto.asymmetric.Certificate, not %s
                    ''',
                    _type_name(requestor_certificate)
                ))

            if other_certificates is not None and not isinstance(other_certificates, list):
                raise TypeError(_pretty_message(
                    '''
                    other_certificates must be a list of
                    asn1crypto.x509.Certificate or
                    oscrypto.asymmetric.Certificate objects, not %s
                    ''',
                    _type_name(other_certificates)
                ))

            if cert_is_oscrypto:
                requestor_certificate = requestor_certificate.asn1

            tbs_request['requestor_name'] = x509.GeneralName(
                name='directory_name',
                value=requestor_certificate.subject
            )

            certificates = [requestor_certificate]

            for other_certificate in other_certificates:
                other_cert_is_oscrypto = isinstance(other_certificate, asymmetric.Certificate)
                if not isinstance(other_certificate, x509.Certificate) and not other_cert_is_oscrypto:
                    raise TypeError(_pretty_message(
                        '''
                        other_certificate must be an instance of
                        asn1crypto.x509.Certificate or
                        oscrypto.asymmetric.Certificate, not %s
                        ''',
                        _type_name(other_certificate)
                    ))
                if other_cert_is_oscrypto:
                    other_certificate = other_certificate.asn1
                certificates.append(other_certificate)

            signature_algo = requestor_private_key.algorithm
            if signature_algo == 'ec':
                signature_algo = 'ecdsa'

            signature_algorithm_id = '%s_%s' % (self._hash_algo, signature_algo)

            if requestor_private_key.algorithm == 'rsa':
                sign_func = asymmetric.rsa_pkcs1v15_sign
            elif requestor_private_key.algorithm == 'dsa':
                sign_func = asymmetric.dsa_sign
            elif requestor_private_key.algorithm == 'ec':
                sign_func = asymmetric.ecdsa_sign

            if not is_oscrypto:
                requestor_private_key = asymmetric.load_private_key(requestor_private_key)
            signature_bytes = sign_func(requestor_private_key, tbs_request.dump(), self._hash_algo)

            signature = ocsp.Signature({
                'signature_algorithm': {'algorithm': signature_algorithm_id},
                'signature': signature_bytes,
                'certs': certificates
            })

        return ocsp.OCSPRequest({
            'tbs_request': tbs_request,
            'optional_signature': signature
        })
示例#56
0
文件: _util.py 项目: wbond/badtls.io
def load_private(name):
    return asymmetric.load_private_key(path.join(
        certs_dir,
        '{}.key'.format(name)
    ))
示例#57
0
    def build(self, signing_private_key):
        """
        Validates the certificate information, constructs the ASN.1 structure
        and then signs it

        :param signing_private_key:
            An asn1crypto.keys.PrivateKeyInfo or oscrypto.asymmetric.PrivateKey
            object for the private key to sign the certificate with. If the key
            is self-signed, this should be the private key that matches the
            public key, otherwise it needs to be the issuer's private key.

        :return:
            An asn1crypto.x509.Certificate object of the newly signed
            certificate
        """

        is_oscrypto = isinstance(signing_private_key, asymmetric.PrivateKey)
        if not isinstance(signing_private_key, keys.PrivateKeyInfo) and not is_oscrypto:
            raise TypeError(_pretty_message(
                '''
                signing_private_key must be an instance of
                asn1crypto.keys.PrivateKeyInfo or
                oscrypto.asymmetric.PrivateKey, not %s
                ''',
                _type_name(signing_private_key)
            ))

        if self._self_signed is not True and self._issuer is None:
            raise ValueError(_pretty_message(
                '''
                Certificate must be self-signed, or an issuer must be specified
                '''
            ))

        if self._self_signed:
            self._issuer = self._subject

        if self._serial_number is None:
            time_part = int_to_bytes(int(time.time()))
            random_part = util.rand_bytes(4)
            self._serial_number = int_from_bytes(time_part + random_part)

        if self._begin_date is None:
            self._begin_date = datetime.now(timezone.utc)

        if self._end_date is None:
            self._end_date = self._begin_date + timedelta(365)

        if not self.ca:
            for ca_only_extension in set(['policy_mappings', 'policy_constraints', 'inhibit_any_policy']):
                if ca_only_extension in self._other_extensions:
                    raise ValueError(_pretty_message(
                        '''
                        Extension %s is only valid for CA certificates
                        ''',
                        ca_only_extension
                    ))

        signature_algo = signing_private_key.algorithm
        if signature_algo == 'ec':
            signature_algo = 'ecdsa'

        signature_algorithm_id = '%s_%s' % (self._hash_algo, signature_algo)

        # RFC 3280 4.1.2.5
        def _make_validity_time(dt):
            if dt < datetime(2050, 1, 1, tzinfo=timezone.utc):
                value = x509.Time(name='utc_time', value=dt)
            else:
                value = x509.Time(name='general_time', value=dt)

            return value

        def _make_extension(name, value):
            return {
                'extn_id': name,
                'critical': self._determine_critical(name),
                'extn_value': value
            }

        extensions = []
        for name in sorted(self._special_extensions):
            value = getattr(self, '_%s' % name)
            if name == 'ocsp_no_check':
                value = core.Null() if value else None
            if value is not None:
                extensions.append(_make_extension(name, value))

        for name in sorted(self._other_extensions.keys()):
            extensions.append(_make_extension(name, self._other_extensions[name]))

        tbs_cert = x509.TbsCertificate({
            'version': 'v3',
            'serial_number': self._serial_number,
            'signature': {
                'algorithm': signature_algorithm_id
            },
            'issuer': self._issuer,
            'validity': {
                'not_before': _make_validity_time(self._begin_date),
                'not_after': _make_validity_time(self._end_date),
            },
            'subject': self._subject,
            'subject_public_key_info': self._subject_public_key,
            'extensions': extensions
        })

        if signing_private_key.algorithm == 'rsa':
            sign_func = asymmetric.rsa_pkcs1v15_sign
        elif signing_private_key.algorithm == 'dsa':
            sign_func = asymmetric.dsa_sign
        elif signing_private_key.algorithm == 'ec':
            sign_func = asymmetric.ecdsa_sign

        if not is_oscrypto:
            signing_private_key = asymmetric.load_private_key(signing_private_key)
        signature = sign_func(signing_private_key, tbs_cert.dump(), self._hash_algo)

        return x509.Certificate({
            'tbs_certificate': tbs_cert,
            'signature_algorithm': {
                'algorithm': signature_algorithm_id
            },
            'signature_value': signature
        })
示例#58
0
    def get_ocsp_response(self, data):
        try:
            ocsp_request = asn1crypto.ocsp.OCSPRequest.load(data)

            tbs_request = ocsp_request['tbs_request']
            request_list = tbs_request['request_list']
            if len(request_list) != 1:
                log.error('Received OCSP request with multiple sub requests')
                raise NotImplemented('Combined requests not yet supported')
            single_request = request_list[0]  # TODO: Support more than one request
            req_cert = single_request['req_cert']
            serial = serial_from_int(req_cert['serial_number'].native)
        except Exception as e:
            log.exception('Error parsing OCSP request: %s', e)
            return self.fail('malformed_request')

        # Get CA and certificate
        ca = CertificateAuthority.objects.get(serial=self.ca)
        try:
            cert = Certificate.objects.filter(ca=ca).get(serial=serial)
        except Certificate.DoesNotExist:
            log.warn('OCSP request for unknown cert received.')
            return self.fail('internal_error')

        # load ca cert and responder key/cert
        ca_cert = load_certificate(force_bytes(ca.pub))
        responder_key = load_private_key(self.responder_key)
        responder_cert = load_certificate(self.responder_cert)

        builder = OCSPResponseBuilder(
            response_status='successful',  # ResponseStatus.successful.value,
            certificate=load_certificate(force_bytes(cert.pub)),
            certificate_status=cert.ocsp_status,
            revocation_date=cert.revoked_date,
        )

        # Parse extensions
        for extension in tbs_request['request_extensions']:
            extn_id = extension['extn_id'].native
            critical = extension['critical'].native
            value = extension['extn_value'].parsed

            # This variable tracks whether any unknown extensions were encountered
            unknown = False

            # Handle nonce extension
            if extn_id == 'nonce':
                builder.nonce = value.native

            # That's all we know
            else:  # pragma: no cover
                unknown = True

            # If an unknown critical extension is encountered (which should not
            # usually happen, according to RFC 6960 4.1.2), we should throw our
            # hands up in despair and run.
            if unknown is True and critical is True:  # pragma: no cover
                log.warning('Could not parse unknown critical extension: %r',
                        dict(extension.native))
                return self._fail('internal_error')

            # If it's an unknown non-critical extension, we can safely ignore it.
            elif unknown is True:  # pragma: no cover
                log.info('Ignored unknown non-critical extension: %r', dict(extension.native))

        builder.certificate_issuer = ca_cert
        builder.next_update = datetime.utcnow() + timedelta(seconds=self.expires)
        return builder.build(responder_key, responder_cert)
示例#59
0
 def as_view(cls, **kwargs):
     kwargs['responder_key'] = load_private_key(kwargs['responder_key'])
     return super(OCSPView, cls).as_view(**kwargs)