php小编草莓将为您介绍如何将DirName和序列号添加到X509v3授权密钥标识符。在网络通信中,授权密钥标识符(X509v3)是一种数字证书,用于验证通信方的身份。DirName指的是证书持有者的名称,而序列号是用于唯一标识证书的编号。通过添加DirName和序列号,可以增加证书的可读性和唯一性,提高通信的安全性和可靠性。接下来,我们将详细讲解如何进行操作。
问题内容
我正在尝试使用 openssl 和 go 代码生成客户端证书。我有一个 openssl 脚本,可以生成具有所需扩展名的证书,并且我想使用 go 代码实现相同的结果。
使用 openssl
选项.ext
openssl 使用的 options.ext 文件包含以下扩展名:
basicconstraints=ca:false
authoritykeyidentifier=keyid,issuer
subjectkeyidentifier=hash
keyusage=digitalsignature
extendedkeyusage=clientauth
生成-client-cert.sh
我目前拥有的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 授权密钥标识符?
相关
- http://oid-info.com/get/2.5.29.35
- https://github.com/golang/go/issues/47096(原始问题)
当我尝试这个时:
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 5280authkeyid > 并使用此结构生成值:
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 授权密钥标识符的详细内容,更多请关注编程网其它相关文章!