来自x509证书的golang主题dn

时间:2016-08-24 14:17:48

标签: go x509

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

我无法在pkix.Name

中找到任何类似“.String()”的方法

7 个答案:

答案 0 :(得分: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
}

调用函数:

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

输出(示例):

/C=US/O=some organization/OU=unit/CN=common name

这似乎是唯一的&#34; easy&#34;溶液

答案 1 :(得分:1)

我今天面临同样的任务。你可以通过这种方式从证书中获得主题:

// d is []byte with your certificate
cert, err := x509.ParseCertificate(d)
fmt.Printf("%+v\n", cert.Subject.ToRDNSequence())

// Output: CN=client1,OU=MyClients,O=MongoDB-Cluster,L=Austin,ST=TX,C=US

答案 2 :(得分:1)

要从x509证书中获取完整的主题DN(或颁发者DN),您可以使用下一个代码:

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()

同样,如果您只需要从主题(或发行人)获得某些特定的对象值,您可以使用下一种方法。下面的示例从subject(未在stdlib https://github.com/golang/go/issues/25667中定义)

中检索UID
// 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)

<强>更新: 感谢@FiloSottile

,简化了获取UID的方法
// 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)

答案 3 :(得分:0)

直接使用   fmt.Sprintf("%+v", cert.Subject.ToRDNSequence())

在1.9中完成工作。 对于高级版本的go(> = 1.10),它可以与pkix.Name中的“ .String()”一起使用

答案 4 :(得分:0)

现在您可以使用:

cert, _ := x509.ParseCertificate(certDERBlock.Bytes)
fmt.Println(cert.Subject.CommonName)

https://golang.org/pkg/crypto/x509/#Certificate
https://golang.org/pkg/crypto/x509/pkix/#Name

答案 5 :(得分:0)

这是我使用的功能。

date_month

这是获取RDNSequence的代码。该示例获取主题名称。

channel

答案 6 :(得分:0)

这是我最终用来直接解析字符串的函数,而没有使用任何go内部库。

if (document.getElementById('element-id')) {
// if exist must do something }