-
Notifications
You must be signed in to change notification settings - Fork 211
Description
[WIP] Issue
Summary
This issue is intended to serve as a point of discussion related to the effort to standardize our handling of the distinguished name values found in x.509 certificate subject and issuer fields. The intent is to arrive at a field ordering that is
- portable across programming languages (at least Java, Python, and Go)
- deterministic even when processing unknown fields
Commentary from HD about handling in Go:
Lines 4 to 38 in 94c2576
| This fingerprint set matches the Subject field of x509 certificates. These x509 | |
| certificates may be sourced from any SSL or TLS service. If a particular system | |
| has identical subject and issuer fields, the subject field should be preferred. | |
| The format of the Subject field is built from the x509 distinguished names using | |
| a specific order. This order matches the Go implementation at the URL: | |
| https://golang.org/src/crypto/x509/pkix/pkix.go#203 | |
| The ToRDNSequence() function builds the string in reverse order: | |
| func (n Name) ToRDNSequence() (ret RDNSequence) { | |
| ret = n.appendRDNs(ret, n.Country, oidCountry) | |
| ret = n.appendRDNs(ret, n.Province, oidProvince) | |
| ret = n.appendRDNs(ret, n.Locality, oidLocality) | |
| ret = n.appendRDNs(ret, n.StreetAddress, oidStreetAddress) | |
| ret = n.appendRDNs(ret, n.PostalCode, oidPostalCode) | |
| ret = n.appendRDNs(ret, n.Organization, oidOrganization) | |
| ret = n.appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit) | |
| if len(n.CommonName) > 0 { | |
| ret = n.appendRDNs(ret, []string{n.CommonName}, oidCommonName) | |
| } | |
| if len(n.SerialNumber) > 0 { | |
| ret = n.appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber) | |
| } | |
| for _, atv := range n.ExtraNames { | |
| ret = append(ret, []AttributeTypeAndValue{atv}) | |
| } | |
| return ret | |
| } | |
| All names are separated by commas and any commas inside a name are escaped with a | |
| single backslash character. See RFC 2253 for additional details on formatting. | |
| Practically, most Subjects start with the Common Name (CN=) and then step through | |
| Organization Unit (OU), Organization (O), and then some level of location, but | |
| typically Locality (L) and Country (C). Names are guaranteed to be listed in | |
| the order described above, but may start at any point in the list. For example, | |
| Subjects may start with a Serial Number (SERIALNUMBER=) or even Extra Names, but | |
| these are somewhat rare. Keep this name order in mind when working on these | |
| fingerprints. |
Commentary and example from HD on handling of extra fields in Go:
The relevant Go code for extra name handling:
oidString := tv.Type.String() typeName, ok := attributeTypeNames[oidString] if !ok { derBytes, err := asn1.Marshal(tv.Value) if err == nil { s += oidString + "=#" + hex.EncodeToString(derBytes) continue // No value escaping necessary. } typeName = oidString }In practice this looks like:
CN=device.corp.com,OU=VMware Engineering,O=VMware,L=Palo Alto,ST=California,C=US,1.2.840.113549.1.9.1=#0c0f766d636140766d776172652e636f6d1.2.840.113549.1.9.1 is the OID of the EMAILADDRESS attribute. The value includes the DER bytes, including the Type and Length before the value (vmca@vmware.com).
TODO before requesting feedback from others:
- Build simple Python, Ruby, Go, and Rust tools that connect to an HTTP endpoint and emit the certificate with the least amount of processing
- Use the tools above to provide reference examples to show the differences
Examples
Some example subject values that haven't been accounted for in our prior discussions.
unstructuredName
{
"C": "US",
"CN": "foo.bar",
"L": "Palo Alto",
"O": "VMware, Inc",
"OU": "VMware ESX Server Default Certificate",
"ST": "California",
"emailAddress": "ssl-certificates@vmware.com",
"unstructuredName": "1617207215,564d7761726520496e632e"
}businessCategory, jurisdictionC , jurisdictionL, jurisdictionST
{
"C": "DE",
"CN": "foo.bar",
"L": "Hannover",
"O": "TUI AG",
"ST": "Niedersachsen",
"businessCategory": "Private Organization",
"jurisdictionC": "DE",
"jurisdictionL": "Charlottenburg",
"jurisdictionST": "Berlin",
"serialNumber": "HRB 000"
}name
{
"name": "AR2220-Self-Signed-Certificate-2102352934DMGA000458"
}description
{
"CN": "00:09:52:05:b9:73",
"O": "Auerswald",
"description": "Vendor=Auerswald;SN=0000000000;MAC=00:00:00:00:00:00;DevClass=PBX;DevTyp=COMpact5200"
}`From Microsoft Active Directory, DC
{
"CN": "foo.bar.local",
"DC": "va",
"OU": "devices"
}