如何在Go中生成指定Subject顺序的CSR证书签名请求
如何在Go中自定义CSR Subject字段顺序
Go标准库的crypto/x509/pkix包中,pkix.Name的默认处理逻辑会按固定顺序(Country → Locality → Organization → OrganizationalUnit → ... → CommonName)生成Subject的RDN序列,无法直接通过修改pkix.Name的字段来调整输出顺序。要实现自定义顺序,需要手动构造pkix.RDNSequence并直接指定Subject的原始ASN.1编码。
实现步骤
明确字段对应OID:每个Subject字段都有对应的ASN.1 OID,常用字段的OID如下:
- 国家(C):
2.5.4.6 - 组织(O):
2.5.4.10 - 组织单元(OU):
2.5.4.11 - 地区(L):
2.5.4.7 - 通用名称(CN):
2.5.4.3
- 国家(C):
按目标顺序构造RDN序列:
- 每个
RelativeDistinguishedNameSET对应Subject中的一个逗号分隔项 - 多个同类型字段(如多个OU)需要放在同一个
RelativeDistinguishedNameSET中,这样会生成OU=OU1 + OU=OU2的格式
- 每个
编码RDN序列并赋值给Subject.Raw:
- 将构造好的
pkix.RDNSequence编码为ASN.1 DER格式 - 把编码后的数据赋值给
pkix.Name.Raw,这样生成CSR时会直接使用该原始数据,而非默认排序后的内容
- 将构造好的
完整代码示例
package main import ( "crypto/rand" "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "encoding/asn1" "encoding/pem" "os" ) func main() { // 生成RSA私钥 privateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { panic(err) } // 按目标顺序构造RDN序列 rdnSequence := pkix.RDNSequence{ // C = IN {{Type: []int{2, 5, 4, 6}, Value: "IN"}}, // O = Example Org {{Type: []int{2, 5, 4, 10}, Value: "Example Org"}}, // OU = OU1 + OU = OU2 { {Type: []int{2, 5, 4, 11}, Value: "OU1"}, {Type: []int{2, 5, 4, 11}, Value: "OU2"}, }, // L = loc {{Type: []int{2, 5, 4, 7}, Value: "loc"}}, // CN = example.com {{Type: []int{2, 5, 4, 3}, Value: "example.com"}}, } // 将RDN序列编码为ASN.1 DER rawSubject, err := asn1.Marshal(rdnSequence) if err != nil { panic(err) } // 构造CSR模板 csrTemplate := &x509.CertificateRequest{ Subject: pkix.Name{ Raw: rawSubject, // 使用自定义的原始Subject数据 }, SignatureAlgorithm: x509.SHA256WithRSA, } // 生成CSR的DER编码 csrDER, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, privateKey) if err != nil { panic(err) } // 将DER编码转为PEM格式并写入文件 csrPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER}) if err := os.WriteFile("custom_order.csr", csrPEM, 0644); err != nil { panic(err) } }
验证结果
运行代码后,使用OpenSSL命令查看CSR的Subject:
openssl req -in custom_order.csr -text -noout
输出的Subject会符合预期顺序:
Subject: C = IN, O = Example Org, OU = OU1 + OU = OU2, L = loc, CN = example.com
内容的提问来源于stack exchange,提问作者Shailendra Kirtikar
相关产品推荐
相关产品推荐

