首页 > 解决方案 > 如何在 Golang 中将 keyUsage 添加到证书签名请求中

问题描述

我需要创建一个 PEM 编码的证书签名请求 (CSR),在 Golang 应用程序中指定 keyUsage certSign。

在 Golang 中,函数x509.CreateCertificateRequest 对此有所帮助,它需要一个x509.CertificateRequest输入参数。类型 CertificateRequest 没有 KeyUsage 属性,所以我假设我必须使用它的Extensions属性在该 CSR 中嵌入 KeyUsage。该Extensions属性是类型[]pkix.Extension的,pkix Go 包并没有太多帮助我构建 KeyUsage 扩展。

KeyUsage 在RFC5280 第 4.2.1.3 节中记录为带有 OBJECT IDENTIFIER id-ce 15 的 BIT STRING。以下是创建该 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

标签: gox509certificatex509pki

解决方案


我也找不到添加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}


推荐阅读