def stringToDN(string, tag=None): """Takes a string representing a distinguished name or directory name and returns a Name for use by pyasn1. See the documentation for the issuer and subject fields for more details. Takes an optional implicit tag in cases where the Name needs to be tagged differently.""" if string and '/' not in string: string = '/CN=%s' % string rdns = rfc2459.RDNSequence() pattern = '/(C|ST|L|O|OU|CN|emailAddress)=' split = re.split(pattern, string) # split should now be [[encoding], <type>, <value>, <type>, <value>, ...] if split[0]: encoding = split[0] else: encoding = 'utf8String' for pos, (nameType, value) in enumerate(zip(split[1::2], split[2::2])): ava = rfc2459.AttributeTypeAndValue() if nameType == 'C': ava.setComponentByName('type', rfc2459.id_at_countryName) nameComponent = rfc2459.X520countryName(value) elif nameType == 'ST': ava.setComponentByName('type', rfc2459.id_at_stateOrProvinceName) nameComponent = rfc2459.X520StateOrProvinceName() elif nameType == 'L': ava.setComponentByName('type', rfc2459.id_at_localityName) nameComponent = rfc2459.X520LocalityName() elif nameType == 'O': ava.setComponentByName('type', rfc2459.id_at_organizationName) nameComponent = rfc2459.X520OrganizationName() elif nameType == 'OU': ava.setComponentByName('type', rfc2459.id_at_organizationalUnitName) nameComponent = rfc2459.X520OrganizationalUnitName() elif nameType == 'CN': ava.setComponentByName('type', rfc2459.id_at_commonName) nameComponent = rfc2459.X520CommonName() elif nameType == 'emailAddress': ava.setComponentByName('type', rfc2459.emailAddress) nameComponent = rfc2459.Pkcs9email(value) else: raise UnknownDNTypeError(nameType) if not nameType == 'C' and not nameType == 'emailAddress': # The value may have things like '\0' (i.e. a slash followed by # the number zero) that have to be decoded into the resulting # '\x00' (i.e. a byte with value zero). nameComponent.setComponentByName( encoding, value.decode(encoding='string_escape')) ava.setComponentByName('value', nameComponent) rdn = rfc2459.RelativeDistinguishedName() rdn.setComponentByPosition(0, ava) rdns.setComponentByPosition(pos, rdn) if tag: name = rfc2459.Name().subtype(implicitTag=tag) else: name = rfc2459.Name() name.setComponentByPosition(0, rdns) return name
class TBSCertificate(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.DefaultedNamedType('version', rfc2459.Version('v1', tagSet=rfc2459.Version.tagSet.tagExplicitly(tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)))), namedtype.NamedType('serialNumber', rfc2459.CertificateSerialNumber()), namedtype.NamedType('signature', AlgorithmIdentifier()), namedtype.NamedType('issuer', rfc2459.Name()), namedtype.NamedType('validity', rfc2459.Validity()), namedtype.NamedType('subject', rfc2459.Name()), namedtype.NamedType('subjectPublicKeyInfo', SubjectPublicKeyInfo()), namedtype.OptionalNamedType('issuerUniqueID', rfc2459.UniqueIdentifier().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), namedtype.OptionalNamedType('subjectUniqueID', rfc2459.UniqueIdentifier().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), namedtype.OptionalNamedType('extensions', rfc2459.Extensions().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))) )
class ResponderID(univ.Choice): componentType = namedtype.NamedTypes( namedtype.NamedType('byName', rfc2459.Name().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), namedtype.NamedType('byKey', KeyHash().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) )
def __init__(self, attrs): if isinstance(attrs, list): self.asn = rfc2459.Name() vals = rfc2459.RDNSequence() for (i, attr) in enumerate(attrs): if not isinstance(attr, list): attr = [attr] pairset = rfc2459.RelativeDistinguishedName() for (j, (oid, val)) in enumerate(attr): pair = rfc2459.AttributeTypeAndValue() pair.setComponentByName('type', rfc2459.AttributeType(str(oid))) code, enc = self.special_encs.get( oid, (char.UTF8String, 'utf-8')) pair.setComponentByName( 'value', rfc2459.AttributeValue( univ.OctetString( encoder.encode( code(unicode(val).encode(enc, 'replace')))))) pairset.setComponentByPosition(j, pair) vals.setComponentByPosition(i, pairset) self.asn.setComponentByPosition(0, vals) else: self.asn = attrs
def set_issuer(self, issuer): """Set the issuer name field value. :param issuer: An X509Name object instance """ val = issuer._name_obj if self._cert['tbsCertificate']['issuer'] is None: self._cert['tbsCertificate']['issuer'] = rfc2459.Name() self._cert['tbsCertificate']['issuer'][0] = val
def set_subject(self, subject): """Set the subject name filed value. :param subject: An X509Name object instance """ val = subject._name_obj if self._cert['tbsCertificate']['subject'] is None: self._cert['tbsCertificate']['subject'] = rfc2459.Name() self._cert['tbsCertificate']['subject'][0] = val
def directoryName(self, rdn): ''' :rdn: [(OID, value), (OID, value) ...] ''' elt = rfc2459.Name().subtype( implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) elt.setComponentByName('', Attributes(rdn).asn[0]) return elt
def _RDNSeqFromTuple(values): seq = rfc2459.RDNSequence() for i, v in enumerate(values): oi_type = '.'.join([str(x) for x in v[0]]) typevalue = rfc2459.AttributeTypeAndValue() typevalue.setComponentByPosition(0, rfc2459.AttributeType(oi_type)) typevalue.setComponentByPosition(1, rfc2459.AttributeValue(v[1])) seq.setComponentByPosition( i, rfc2459.RelativeDistinguishedName().setComponentByPosition( 0, typevalue)) return rfc2459.Name().setComponentByPosition(0, seq)
def stringToCommonName(string): """Helper function for taking a string and building an x520 name representation usable by the pyasn1 package. Currently returns one RDN with one AVA consisting of a Common Name encoded as a UTF8String.""" commonName = rfc2459.X520CommonName() commonName.setComponentByName('utf8String', string) ava = rfc2459.AttributeTypeAndValue() ava.setComponentByName('type', rfc2459.id_at_commonName) ava.setComponentByName('value', commonName) rdn = rfc2459.RelativeDistinguishedName() rdn.setComponentByPosition(0, ava) rdns = rfc2459.RDNSequence() rdns.setComponentByPosition(0, rdn) name = rfc2459.Name() name.setComponentByPosition(0, rdns) return name
def stringToCommonName(string): """Helper function for taking a string and building an x520 name representation usable by the pyasn1 package. Currently returns one RDN with one AVA consisting of a Common Name encoded as a UTF8String.""" commonName = rfc2459.X520CommonName() # The string may have things like '\0' (i.e. a slash followed by # the number zero) that have to be decoded into the resulting # '\x00' (i.e. a byte with value zero). commonName.setComponentByName('utf8String', string.decode(encoding='string_escape')) ava = rfc2459.AttributeTypeAndValue() ava.setComponentByName('type', rfc2459.id_at_commonName) ava.setComponentByName('value', commonName) rdn = rfc2459.RelativeDistinguishedName() rdn.setComponentByPosition(0, ava) rdns = rfc2459.RDNSequence() rdns.setComponentByPosition(0, rdn) name = rfc2459.Name() name.setComponentByPosition(0, rdns) return name
def encode(cls, pki_key: object, **kwargs): # Algorithm ID alg_oid = cls.ALG_OID if type( cls.ALG_OID) is str else cls.ALG_OID(pki_key) alg_id = rfc2459.AlgorithmIdentifier() alg_id['algorithm'] = ObjectIdentifier(alg_oid) if cls.PARAM_ENCODER: alg_id['parameters'] = Any( encoder.encode(cls.PARAM_ENCODER.encode(pki_key))) # Serial number serial_num = rfc2459.CertificateSerialNumber( kwargs.get('serial_number') or 0) # Validity (time valid) not_before = kwargs.get('not_before') or datetime.now() not_after = kwargs.get('not_after') or not_before.replace( year=not_before.year + 1) validity = rfc2459.Validity() validity['notBefore'] = rfc2459.Time() validity['notBefore']['utcTime'] = UTCTime.fromDateTime(not_before) validity['notAfter'] = rfc2459.Time() validity['notAfter']['utcTime'] = UTCTime.fromDateTime(not_after) # Public key serialization pub_info = rfc2459.SubjectPublicKeyInfo() pub_info['algorithm'] = alg_id pub_info['subjectPublicKey'] = cls.PUB_KEY_ENCODER.encode(pki_key) # Issuer RDN issuer = rfc2459.Name() issuer.setComponentByPosition( 0, parse_rdn(kwargs.get('issuer') or 'CN=ca')) # Subject RDN subject = rfc2459.Name() subject.setComponentByPosition( 0, parse_rdn(kwargs.get('subject') or 'CN=ca')) # Signature algorithm signing_key = kwargs.get('signing_key') or pki_key if not (kwargs.get('signing_alg') or hasattr(signing_key, "X509_SIGNING_DEFAULT")): raise ValueError( "'signing_alg' not specified and 'signing_key' has no default algorithm" ) signing_alg = (kwargs.get('signing_alg') or signing_key.X509_SIGNING_DEFAULT).value signature_alg = rfc2459.AlgorithmIdentifier() signature_alg['algorithm'] = SIGNING_ALG_OIDS[signing_alg.name] if cls.PARAM_ENCODER: signature_alg['parameters'] = Any( encoder.encode(cls.PARAM_ENCODER.encode(pki_key))) # Extensions extensions = rfc2459.Extensions().subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)) if kwargs.get('ca') and kwargs.get('ca') == True: # SKI pkey_bytes = Bytes(int(pub_info['subjectPublicKey'])) ski_ext = rfc2459.Extension() ski_ext['extnID'] = ObjectIdentifier([2, 5, 29, 14]) ski_ext['extnValue'] = OctetString( encoder.encode( rfc2459.SubjectKeyIdentifier(SHA1().hash(pkey_bytes)))) # CA basic constraint ca_value = rfc2459.BasicConstraints() ca_value.setComponentByName('cA', True) ca_ext = rfc2459.Extension() ca_ext.setComponentByName('extnID', '2.5.29.19') ca_ext.setComponentByName('critical', True) ca_ext.setComponentByName('extnValue', OctetString(encoder.encode(ca_value))) extensions.setComponentByPosition(0, ski_ext) extensions.setComponentByPosition(1, ca_ext) # Put together the TBSCert tbs_cert = rfc2459.TBSCertificate() tbs_cert['version'] = 2 tbs_cert['serialNumber'] = serial_num tbs_cert['signature'] = signature_alg tbs_cert['issuer'] = issuer tbs_cert['validity'] = validity tbs_cert['subject'] = subject tbs_cert['subjectPublicKeyInfo'] = pub_info tbs_cert['issuerUniqueID'] = kwargs.get('issuer_unique_id') or 10 tbs_cert['subjectUniqueID'] = kwargs.get('subject_unique_id') or 11 if len(extensions): tbs_cert['extensions'] = extensions # Inject or compute the TBSCert signature if kwargs.get('signature_value') is not None: sig_value = Bytes.wrap(kwargs.get('signature_value')).int() else: encoded_tbs = encoder.encode(tbs_cert, asn1Spec=rfc2459.TBSCertificate()) sig_value = signing_alg.sign(signing_key, encoded_tbs) # Build the Cert object cert = rfc2459.Certificate() cert['tbsCertificate'] = tbs_cert cert['signatureAlgorithm'] = signature_alg cert['signatureValue'] = sig_value encoded = encoder.encode(cert, asn1Spec=rfc2459.Certificate()) return X509Certificate.transport_encode(encoded, **kwargs)
def test_decoded_asn1_different_types_umlaut(self): (utf8, _) = pyasn1.codec.der.decoder.decode(bytes.fromhex("30 17 31 15 30 13 06 03 55 04 03 0c 0c 43 c3 b6 6d 6d 6f 6e 20 4e 61 6d 65"), asn1Spec = rfc2459.Name()) (bmp, _) = pyasn1.codec.der.decoder.decode(bytes.fromhex("30 21 31 1f 30 1d 06 03 55 04 03 1e 16 00 43 00 f6 00 6d 00 6d 00 6f 00 6e 00 20 00 4e 00 61 00 6d 00 65"), asn1Spec = rfc2459.Name()) utf8dn = DistinguishedName.from_asn1(utf8) bmpdn = DistinguishedName.from_asn1(bmp) self.assertEqual(utf8dn, bmpdn)
def test_decoded_asn1_different_types(self): (utf8, _) = pyasn1.codec.der.decoder.decode(bytes.fromhex("30 16 31 14 30 12 06 03 55 04 03 0c 0b 43 6f 6d 6d 6f 6e 20 4e 61 6d 65"), asn1Spec = rfc2459.Name()) (ia5, _) = pyasn1.codec.der.decoder.decode(bytes.fromhex("30 16 31 14 30 12 06 03 55 04 03 16 0b 43 6f 6d 6d 6f 6e 20 4e 61 6d 65"), asn1Spec = rfc2459.Name()) utf8dn = DistinguishedName.from_asn1(utf8) ia5dn = DistinguishedName.from_asn1(ia5) self.assertEqual(utf8dn, ia5dn)
def test_json_DNs(self): for testcase in self._load_json("misc/dn_tests.json"): rdn_sequence_derdata = base64.b64decode(testcase["rdn_sequence"].encode()) (rdn_sequence_asn1, _) = pyasn1.codec.der.decoder.decode(rdn_sequence_derdata, asn1Spec = rfc2459.Name()) dn = DistinguishedName.from_asn1(rdn_sequence_asn1) self.assertEqual(dn.rfc2253_str, testcase["rfc2253"])
def load(cls, value): return (cls(decoder.decode(value, asn1Spec=rfc2459.Name())[0]))