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 定义了 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中文網其他相關文章!