예제 #1
0
    def _set_subject_alt(self, name, values):
        """
        Replaces all existing asn1crypto.x509.GeneralName objects of the choice
        represented by the name parameter with the values

        :param name:
            A unicode string of the choice name of the x509.GeneralName object

        :param values:
            A list of unicode strings to use as the values for the new
            x509.GeneralName objects
        """

        if self._subject_alt_name is not None:
            filtered_general_names = []
            for general_name in self._subject_alt_name:
                if general_name.name != name:
                    filtered_general_names.append(general_name)
            self._subject_alt_name = x509.GeneralNames(filtered_general_names)
        else:
            self._subject_alt_name = x509.GeneralNames()

        if values is not None:
            for value in values:
                new_general_name = x509.GeneralName(name=name, value=value)
                self._subject_alt_name.append(new_general_name)

        if len(self._subject_alt_name) == 0:
            self._subject_alt_name = None
예제 #2
0
    def delta_crl_url(self, value):
        if value is None:
            self._freshest_crl = None
            return

        if self._delta_crl_indicator is not None:
            raise ValueError(
                _pretty_message('''
                delta_crl_url can not be set if delta_of is set
                '''))

        if not isinstance(value, str_cls):
            raise TypeError(
                _pretty_message(
                    '''
                delta_crl_url must be a unicode string, not %s
                ''', _type_name(value)))

        general_names = x509.GeneralNames([
            x509.GeneralName(name='uniform_resource_identifier', value=value)
        ])
        distribution_point_name = x509.DistributionPointName(
            name='full_name', value=general_names)
        distribution_point = x509.DistributionPoint(
            {'distribution_point': distribution_point_name})

        self._freshest_crl = x509.CRLDistributionPoints([distribution_point])
예제 #3
0
    def _csr_info(self, subject, public_key, sans):
        """
        Create the csr info portion of the certificate request"s ASN.1
        structure

        :param X509Name subject: subject to add to the certificate request
        :param asymmetric.PublicKey public_key: public key to use when creating
            the certificate request"s signature
        :param sans: collection of dns names to insert into a subjAltName
            extension for the certificate request
        :type sans: None or list(str) or tuple(str) or set(str)
        :return: the certificate request info structure
        :rtype: csr.CertificationRequestInfo
        """
        x509_subject = x509.Name.build(self._subject_as_dict(subject))
        extensions = [(u"basic_constraints",
                       x509.BasicConstraints({"ca": False}), False),
                      (u"key_usage",
                       x509.KeyUsage({"digital_signature",
                                      "key_encipherment"}), True),
                      (u"extended_key_usage",
                       x509.ExtKeyUsageSyntax([u"client_auth"]), False)]
        if sans:
            names = x509.GeneralNames()
            for san in sans:
                names.append(
                    x509.GeneralName("dns_name", _bytes_to_unicode(san)))
            extensions.append((u"subject_alt_name", names, False))

        return csr.CertificationRequestInfo({
            "version":
            u"v1",
            "subject":
            x509_subject,
            "subject_pk_info":
            public_key.asn1,
            "attributes": [{
                "type":
                u"extension_request",
                "values": [[self._create_extension(x) for x in extensions]]
            }]
        })
예제 #4
0
    def url(self, value):
        if not isinstance(value, str_cls):
            raise TypeError(
                _pretty_message(
                    '''
                url must be a unicode string, not %s
                ''', _type_name(value)))

        if self._issuing_distribution_point is None:
            general_names = x509.GeneralNames([
                x509.GeneralName(name='uniform_resource_identifier',
                                 value=value)
            ])
            distribution_point_name = x509.DistributionPointName(
                name='full_name', value=general_names)
            self._issuing_distribution_point = crl.IssuingDistributionPoint(
                {'distribution_point': distribution_point_name})
        else:
            distribution_point_name = self._issuing_distribution_point[
                'distribution_point']
            general_names = distribution_point_name.chosen
            general_names[0] = x509.GeneralName(
                name='uniform_resource_identifier', value=value)
예제 #5
0
    def _make_crl_distribution_points(self, name, value):
        """
        Constructs an asn1crypto.x509.CRLDistributionPoints object

        :param name:
            A unicode string of the attribute name to use in exceptions

        :param value:
            Either a unicode string of a URL, or a 2-element tuple of a
            unicode string of a URL, plus an asn1crypto.x509.Certificate
            object that will be signing the CRL (for indirect CRLs).

        :return:
            None or an asn1crypto.x509.CRLDistributionPoints object
        """

        if value is None:
            return None

        is_tuple = isinstance(value, tuple)
        if not is_tuple and not isinstance(value, str_cls):
            raise TypeError(
                _pretty_message(
                    '''
                %s must be a unicode string or tuple of (unicode string,
                asn1crypto.x509.Certificate), not %s
                ''', name, _type_name(value)))

        issuer = None
        if is_tuple:
            if len(value) != 2:
                raise ValueError(
                    _pretty_message(
                        '''
                    %s must be a unicode string or 2-element tuple, not a
                    %s-element tuple
                    ''', name, len(value)))

            if not isinstance(value[0], str_cls) or not isinstance(
                    value[1], x509.Certificate):
                raise TypeError(
                    _pretty_message(
                        '''
                    %s must be a tuple of (unicode string,
                    ans1crypto.x509.Certificate), not (%s, %s)
                    ''', name, _type_name(value[0]), _type_name(value[1])))

            url = value[0]
            issuer = value[1].subject
        else:
            url = value

        general_names = x509.GeneralNames(
            [x509.GeneralName(name='uniform_resource_identifier', value=url)])
        distribution_point_name = x509.DistributionPointName(
            name='full_name', value=general_names)
        distribution_point = x509.DistributionPoint(
            {'distribution_point': distribution_point_name})
        if issuer:
            distribution_point['crl_issuer'] = x509.GeneralNames(
                [x509.GeneralName(name='directory_name', value=issuer)])

        return x509.CRLDistributionPoints([distribution_point])
예제 #6
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
        })