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
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])
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]] }] })
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)
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])
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 })