我需要在Golang应用程序中创建一个pem编码的证书签名请求(CSR),该请求指定keyUsage certSign。
在Golang中,函数x509。CreateCertificateRequest可以帮助解决这个问题,它接受一个x509。CertificateRequest输入参数。Type CertificateRequest没有KeyUsage属性,所以我假设必须使用它的Extensions
属性在CSR中嵌入KeyUsage。这个Extensions
属性是[]pkix.Extension
类型的,并且pkix Go包并没有真正帮助我构建KeyUsage扩展。
KeyUsage在RFC5280节4.2.1.3中作为具有对象标识符id-ce 15的位字符串记录。下面是创建KeyUsage的正确方法吗?有没有更简单的方法来利用pkix或x509 Go包并避免我自己进行位序列化?我的位序列化是否符合RFC,我该如何测试?
asn1KeyUsage, err := asn1.Marshal(asn1.BitString{
Bytes: []byte{byte(x509.KeyUsageCertSign)},
BitLength: 8,
})
if err != nil { ... }
csrTemplate := x509.CertificateRequest{
SignatureAlgorithm: ...,
PublicKeyAlgorithm: ...,
PublicKey: ...,
Subject: ...,
ExtraExtensions: []pkix.Extension{
{
Id: asn1.ObjectIdentifier([]int{2, 5, 29, 15}),
Critical: true,
Value: asn1KeyUsage,
},
},
}
asn1, err = x509.CreateCertificateRequest(
rand.Reader,
csrTemplate,
privateKey,
)
// Convert asn1 to PEM below
我也没有找到一个很好的简短的方法来添加KeyUsage
到我的csr。我查看了golang的代码,发现了这个。
我最终提取了以下代码:
func marshalKeyUsage(ku x509.KeyUsage) (pkix.Extension, error) {
ext := pkix.Extension{Id: asn1.ObjectIdentifier{2, 5, 29, 15}, Critical: true}
var a [2]byte
a[0] = reverseBitsInAByte(byte(ku))
a[1] = reverseBitsInAByte(byte(ku >> 8))
l := 1
if a[1] != 0 {
l = 2
}
bitString := a[:l]
var err error
ext.Value, err = asn1.Marshal(asn1.BitString{Bytes: bitString, BitLength: asn1BitLength(bitString)})
if err != nil {
return ext, err
}
return ext, nil
}
func reverseBitsInAByte(in byte) byte {
b1 := in>>4 | in<<4
b2 := b1>>2&0x33 | b1<<2&0xcc
b3 := b2>>1&0x55 | b2<<1&0xaa
return b3
}
func asn1BitLength(bitString []byte) int {
bitLen := len(bitString) * 8
for i := range bitString {
b := bitString[len(bitString)-i-1]
for bit := uint(0); bit < 8; bit++ {
if (b>>bit)&1 == 1 {
return bitLen
}
bitLen--
}
}
return 0
}
你可以这样使用:
keyUsage := x509.KeyUsage(x509.KeyUsageDigitalSignature)
extKeyUsage, err := marshalKeyUsage(keyUsage)
if err != nil {
log.Fatal(err)
}
// add this extension to csr like below
template.ExtraExtensions = []pkix.Extension{extKeyUsage}