来自x509证书的golang主题dn

tgo*_*tgo 4 go x509

有没有简单的方法从x509证书中获取完整的主题DN(或发行者DN)作为字符串?

我无法在pkix.Name中找到任何类似".String()"的方法

Tra*_*991 7

In order to get complete subject DN (or issuer DN) from an x509 certificate, you may use next code:

cert, err := x509.ParseCertificate(certData)
if err != nil {
    return err
}

var subject pkix.RDNSequence
if _, err := asn1.Unmarshal(cert.RawSubject, &subject); err != nil {
    return err
}

fmt.Plrintln(subject.String()
Run Code Online (Sandbox Code Playgroud)

Similarly, if you need to get only some specific object value from the subject (or issuer) you may use next approach. Example below retrieves UID from subject (which is not defined in the stdlib https://github.com/golang/go/issues/25667)

// http://www.alvestrand.no/objectid/0.9.2342.19200300.100.1.1.html
const oidUserID = "0.9.2342.19200300.100.1.1"
var UID string

cert, err := x509.ParseCertificate(certData)
if err != nil {
    return err
}

// manually parsing the Certificate subject to get the
// UID field, which is being ignored by the stdlib
// https://github.com/golang/go/issues/25667
var subject pkix.RDNSequence
if _, err := asn1.Unmarshal(cert.RawSubject, &subject); err != nil {
    return err
}

for _, s := range subject {
    for _, i := range s {
        if i.Type.String() == oidUserID {
            if v, ok := i.Value.(string); ok {
                UID = v
            }
        }
    }
}

fmt.Println(UID)
Run Code Online (Sandbox Code Playgroud)

UPDATE: Simplified way to get the UID, thanks to @FiloSottile:

// http://www.alvestrand.no/objectid/0.9.2342.19200300.100.1.1.html
var oidUserID = []int{0, 9, 2342, 19200300, 100, 1, 1}
var UID string

cert, err := x509.ParseCertificate(certData)
if err != nil {
    return err
}

// reading the UID from list of unprased 
// objects from Subject
for _, n := range cert.Subject.Names {
    if n.Type.Equal(oidUserID) {
        if v, ok := n.Value.(string); ok {
            UID = v
        }
    }
}

fmt.Println(UID)
Run Code Online (Sandbox Code Playgroud)


tgo*_*tgo 6

解决方案(感谢同事):

var oid = map[string]string{
    "2.5.4.3":                    "CN",
    "2.5.4.4":                    "SN",
    "2.5.4.5":                    "serialNumber",
    "2.5.4.6":                    "C",
    "2.5.4.7":                    "L",
    "2.5.4.8":                    "ST",
    "2.5.4.9":                    "streetAddress",
    "2.5.4.10":                   "O",
    "2.5.4.11":                   "OU",
    "2.5.4.12":                   "title",
    "2.5.4.17":                   "postalCode",
    "2.5.4.42":                   "GN",
    "2.5.4.43":                   "initials",
    "2.5.4.44":                   "generationQualifier",
    "2.5.4.46":                   "dnQualifier",
    "2.5.4.65":                   "pseudonym",
    "0.9.2342.19200300.100.1.25": "DC",
    "1.2.840.113549.1.9.1":       "emailAddress",
    "0.9.2342.19200300.100.1.1":  "userid",
}

func getDNFromCert(namespace pkix.Name, sep string) (string, error) {
    subject := []string{}
    for _, s := range namespace.ToRDNSequence() {
        for _, i := range s {
            if v, ok := i.Value.(string); ok {
                if name, ok := oid[i.Type.String()]; ok {
                    // <oid name>=<value>
                    subject = append(subject, fmt.Sprintf("%s=%s", name, v))
                } else {
                    // <oid>=<value> if no <oid name> is found
                    subject = append(subject, fmt.Sprintf("%s=%s", i.Type.String(), v))
                }
            } else {
                // <oid>=<value in default format> if value is not string
                subject = append(subject, fmt.Sprintf("%s=%v", i.Type.String, v))
            }
        }
    }
    return sep + strings.Join(subject, sep), nil
}
Run Code Online (Sandbox Code Playgroud)

调用函数:

subj, err := getDNFromCert(x509Cert.Subject, "/")
if err != nil {
   // do error handling
}
fmt.Println(subj)
Run Code Online (Sandbox Code Playgroud)

输出(例子):

/C=US/O=some organization/OU=unit/CN=common name
Run Code Online (Sandbox Code Playgroud)

这似乎是唯一"简单"的解决方案