php小编草莓将为您介绍如何将DirName和序列号添加到X509v3授权密钥标识符。在网络通信中,授权密钥标识符(X509v3)是一种数字证书,用于验证通信方的身份。DirName指的是证书持有者的名称,而序列号是用于唯一标识证书的编号。通过添加DirName和序列号,可以增加证书的可读性和唯一性,提高通信的安全性和可靠性。接下来,我们将详细讲解如何进行操作。
我正在尝试使用 openssl 和 go 代码生成客户端证书。我有一个 openssl 脚本,可以生成具有所需扩展名的证书,并且我想使用 go 代码实现相同的结果。
openssl 使用的 options.ext 文件包含以下扩展名:
basicconstraints=ca:false authoritykeyidentifier=keyid,issuer subjectkeyidentifier=hash keyusage=digitalsignature extendedkeyusage=clientauth
我目前拥有的openssl脚本如下:
openssl req \ -newkey rsa:2048 \ -keyout cert.crt \ -out cert.csr \ -nodes \ -sha256 openssl x509 \ -req \ -ca ca.crt \ -cakey ca.key \ -in cert.csr \ -out cert.crt \ -days 365 \ -cacreateserial \ -extfile options.ext \ -sha256
生成证书后,我可以使用以下命令查看其详细信息:
openssl x509 -in cert.crt -text -noout
生成的证书具有以下结构:
certificate: data: version: 3 (0x2) serial number: xx:xx:xx:xx:xx:xx:xx:xx signature algorithm: sha256withrsaencryption issuer: cn=xxx validity not before: jan 1 00:00:00 2023 gmt not after : jan 1 00:00:00 2024 gmt subject: cn=xxx subject public key info: public key algorithm: rsaencryption rsa public-key: (2048 bit) modulus: ... exponent: 65537 (0x10001) x509v3 extensions: x509v3 basic constraints: ca:false x509v3 authority key identifier: dirname:cn=xxx serial:xx:xx:xx:xx:xx:xx:xx:xx x509v3 subject key identifier: ... x509v3 key usage: digital signature x509v3 extended key usage: tls web client authentication signature algorithm: sha256withrsaencryption
它应该看起来像这样:
x509v3 authority key identifier: dirname:cn=xxx serial:xx:xx:xx:xx:xx:xx:xx:xx
在我的 go 代码中,我使用 x509 包来生成证书。但是,我不确定如何设置 x509v3 授权密钥标识符扩展。这是我的 go 代码的相关部分:
import ( "crypto/rand" "crypto/rsa" "crypto/sha1" "crypto/x509" "crypto/x509/pkix" "encoding/asn1" "os" "time" ) ... var cacertificate *x509.certificate var caprivatekey *rsa.privatekey var authoritykeyidentifiervalue []byte // how to write this? template := &x509.certificate{ subject: pkix.name{ commonname: "xxx", }, extraextensions: []pkix.extension{ { id: asn1.objectidentifier{2, 5, 29, 35}, value: authoritykeyidentifiervalue, }, }, keyusage: x509.keyusagedigitalsignature, extkeyusage: []x509.extkeyusage{x509.extkeyusageclientauth}, notbefore: time.now(), notafter: time.now().adddate(0, 0, 365), isca: false, basicconstraintsvalid: true, } privatekey, err := rsa.generatekey(rand.reader, 2048) if err != nil { // err } certificatebytes, err := x509.createcertificate(rand.reader, template, cacertificate, &privatekey.publickey, caprivatekey) if err != nil { // err } // out
如何将 dirname 和序列号添加到 x509v3 授权密钥标识符?
当我尝试这个时:
var capublickeybytes []byte publickeyhash := (sha1.sum(capublickeybytes))[:] var dirname string authoritykeyidentifiervalue := []byte{0x30, len(publickeyhash)} authoritykeyidentifiervalue = append(authoritykeyidentifiervalue, publickeyhash...) authoritykeyidentifiervalue = append(authoritykeyidentifiervalue, 0x80, len(dirname)) authoritykeyidentifiervalue = append(authoritykeyidentifiervalue, []byte(dirname)...) ...
结果是:
X509v3 Authority Key Identifier: 0....0...<....).!.r[..F.....".hCN=xxx.....$...D
authoritykeyidentifiervalue
可以使用 asn1.marshal 生成。下面的演示根据 rfc 5280定义了 struct authkeyid
> 并使用此结构生成值:
package main import ( "crypto/x509" "crypto/x509/pkix" "encoding/asn1" "encoding/hex" "encoding/pem" "fmt" "math/big" ) // rfc 5280, a.2. implicitly tagged module, 1988 syntax // // authoritykeyidentifier ::= sequence { // keyidentifier [0] keyidentifier optional, // authoritycertissuer [1] generalnames optional, // authoritycertserialnumber [2] certificateserialnumber optional } // -- authoritycertissuer and authoritycertserialnumber must both // -- be present or both be absent type authkeyid struct { keyidentifier []byte `asn1:"optional,tag:0"` authoritycertissuer generalnames `asn1:"optional,tag:1"` authoritycertserialnumber *big.int `asn1:"optional,tag:2"` } // rfc 5280, a.2. implicitly tagged module, 1988 syntax // // generalnames ::= sequence size (1..max) of generalname // // generalname ::= choice { // othername [0] anothername, // rfc822name [1] ia5string, // dnsname [2] ia5string, // x400address [3] oraddress, // directoryname [4] name, // edipartyname [5] edipartyname, // uniformresourceidentifier [6] ia5string, // ipaddress [7] octet string, // registeredid [8] object identifier } type generalnames struct { name []pkix.rdnsequence `asn1:"tag:4"` } func gen(issuer *x509.certificate) ([]byte, error) { return asn1.marshal(authkeyid{ keyidentifier: issuer.subjectkeyid, authoritycertissuer: generalnames{name: []pkix.rdnsequence{issuer.issuer.tordnsequence()}}, authoritycertserialnumber: issuer.serialnumber, }) } func main() { cacert := `-----begin certificate----- miibotccauegawibagiqgocjdjn1y6rgwebxw8v8mdakbggqhkjopqqdajammq8w dqydvqqkewznesbpcmcxezarbgnvbamtck15ifjvb3qgq0ewhhcnmjmwnte2mtqy ntuwwhcnmjmwnte3mtuyntuwwjammq8wdqydvqqkewznesbpcmcxezarbgnvbamt ck15ifjvb3qgq0ewwtatbgcqhkjopqibbggqhkjopqmbbwncaarzqz2ka7fi6w9/ 32sjhtajrke+vqyx7hfnmtx1inpbajnfvonf2silh5nqms50jpnvgivehtbfl0a0 dcurufhno1cwvtaobgnvhq8baf8ebamcaqqwewydvr0lbawwcgyikwybbquhawew dwydvr0taqh/bauwaweb/zadbgnvhq4efgqu5y48dj96lqwvh3s/anj/6sgy/j4w cgyikozizj0eawidsaawrqihanqdh6sgz014wvfdh0zhbeghdb2tqxzujxa7ymo3 80unaiapzp4wlzqlb+j4fipnep+txru01jgfaksml2yhv3mewg== -----end certificate-----` b, _ := pem.decode([]byte(cacert)) if b == nil { panic("couldn't decode test certificate") } issuer, err := x509.parsecertificate(b.bytes) if err != nil { panic(err) } authoritykeyidentifiervalue, err := gen(issuer) if err != nil { panic(err) } fmt.println(hex.encodetostring(authoritykeyidentifiervalue)) }
十六进制编码值为:
30548014e58e3c0c9f7a2d05958774bf68d27fe921b2fe3ea12aa4283026310f300d060355040a13064d79204f7267311330110603550403130a4d7920526f6f7420434182101a80a30c937563aac65846d75bc57c30
十六进制字符串可以使用诸如 asn.1 javascript 解码器:
以下 c# 演示给出相同的结果:
using system.security.cryptography.x509certificates; using system.text; internal class program { private static void main(string[] args) { var certbytes = encoding.ascii.getbytes(@"-----begin certificate----- miibotccauegawibagiqgocjdjn1y6rgwebxw8v8mdakbggqhkjopqqdajammq8w dqydvqqkewznesbpcmcxezarbgnvbamtck15ifjvb3qgq0ewhhcnmjmwnte2mtqy ntuwwhcnmjmwnte3mtuyntuwwjammq8wdqydvqqkewznesbpcmcxezarbgnvbamt ck15ifjvb3qgq0ewwtatbgcqhkjopqibbggqhkjopqmbbwncaarzqz2ka7fi6w9/ 32sjhtajrke+vqyx7hfnmtx1inpbajnfvonf2silh5nqms50jpnvgivehtbfl0a0 dcurufhno1cwvtaobgnvhq8baf8ebamcaqqwewydvr0lbawwcgyikwybbquhawew dwydvr0taqh/bauwaweb/zadbgnvhq4efgqu5y48dj96lqwvh3s/anj/6sgy/j4w cgyikozizj0eawidsaawrqihanqdh6sgz014wvfdh0zhbeghdb2tqxzujxa7ymo3 80unaiapzp4wlzqlb+j4fipnep+txru01jgfaksml2yhv3mewg== -----end certificate-----"); using var issuer = new x509certificate2(certbytes); var e = x509authoritykeyidentifierextension.createfromcertificate(issuer, true, true); console.writeline(bytearraytohex(e.rawdata)); } private static string bytearraytohex(byte[] bytes) { var builder = new stringbuilder(bytes.length * 2); for (int i = 0; i < bytes.length; i++) { builder.append($"{bytes[i]:x2}"); } return builder.tostring(); } }
更新:
这是 gen
的更新版本,其中包含电子邮件地址:
func gen(issuer *x509.Certificate) ([]byte, error) { rdnSequence := issuer.Issuer.ToRDNSequence() if len(issuer.EmailAddresses) > 0 { oidEmail := asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1} emails := make([]pkix.AttributeTypeAndValue, len(issuer.EmailAddresses)) for i, value := range issuer.EmailAddresses { emails[i].Type = oidEmail emails[i].Value = value } rdnSequence = append(rdnSequence, emails) } return asn1.Marshal(authKeyId{ KeyIdentifier: issuer.SubjectKeyId, AuthorityCertIssuer: generalNames{Name: []pkix.RDNSequence{rdnSequence}}, AuthorityCertSerialNumber: issuer.SerialNumber, }) }
请注意,oid 已弃用(请参阅 http://oid- info.com/get/1.2.840.113549.1.9.1)。 .net 也不包含它。
以上是如何将 DirName 和序列号添加到 X509v3 授权密钥标识符的详细内容。更多信息请关注PHP中文网其他相关文章!