【问题标题】:How to add keyUsage to certificate signing request in Golang如何在 Golang 中将 keyUsage 添加到证书签名请求中
【发布时间】:2021-10-01 21:55:42
【问题描述】:

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

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

KeyUsage 在RFC5280 section 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

【问题讨论】:

  • 您可以使用openssl req 作为调试工具以文本形式打印出CSR。但是为什么在 CSR 中需要 keyUsage 呢?密钥使用通常由您购买的密钥类型指定,而不是 CSR。出于这个原因,大多数 CA 完全忽略 keyUsage 并在颁发证书时分配您有权使用的密钥。
  • 我认为 CSR 需要 certSign keyUsage 因为这个 CSR 包含一个 basicConstraint (IsCA=true, MaxPathLen=) 来获取具有 MaxPathLength 约束的 CA 证书,以及 RFC 5280 第 4.2 节。 1.9 说明在这种情况下必须声明 keyUsage certSign。当我不在 CSR 中声明 certSign 时,GCP CertificateAuthorityService CreateCertificate 返回一个不受 MaxPathLen 约束的 CA。

标签: go x509certificate x509 pki


【解决方案1】:

我也找不到将KeyUsage 添加到我的 CSR 的好方法。我查看了golang的代码,发现this

我终于提取了以下代码:

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}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    • 2015-12-18
    • 1970-01-01
    • 2016-12-16
    相关资源
    最近更新 更多