How to add keyUsage to certificate signing request in Golang

huangapple go评论90阅读模式
英文:

How to add keyUsage to certificate signing request in Golang

问题

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

在 Golang 中,函数 x509.CreateCertificateRequest 可以帮助实现这一目标,它接受一个 x509.CertificateRequest 输入参数。CertificateRequest 类型没有 KeyUsage 属性,所以我假设我必须使用它的 Extensions 属性来嵌入一个 KeyUsage 到 CSR 中。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,
)

// 将 asn1 转换为 PEM
英文:

I need to create a PEM-encoded Certificate Signing Request (CSR) that specifies keyUsage certSign in a Golang application.

In Golang, function x509.CreateCertificateRequest helps with this, and it takes an x509.CertificateRequest input parameter. Type CertificateRequest does not have a KeyUsage attribute, so I assume I must use its Extensions attribute to embed a KeyUsage in that CSR. That Extensions attribute is of type []pkix.Extension and the pkix Go package does not really have much to help me build a KeyUsage extension.

KeyUsage is documented in RFC5280 section 4.2.1.3 as a BIT STRING with OBJECT IDENTIFIER id-ce 15. Would the following be the right way to create that KeyUsage? Is there no easier way that leverages the pkix or x509 Go packages and avoids doing my own bit serialization? Is my bit serialization even in compliance with that RFC, how can I test this?

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

答案1

得分: 1

我也没有找到一种简洁的方法来向我的证书签名请求(CSR)中添加KeyUsage。我查看了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)
}

// 将此扩展添加到CSR中,如下所示

template.ExtraExtensions = []pkix.Extension{extKeyUsage}
英文:

I'm also not find a nice short way of adding KeyUsage to my CSRs. I looked into golang's code and found this.

I finally ended up extracting following piece of code:

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 &gt;&gt; 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&gt;&gt;4 | in&lt;&lt;4
	b2 := b1&gt;&gt;2&amp;0x33 | b1&lt;&lt;2&amp;0xcc
	b3 := b2&gt;&gt;1&amp;0x55 | b2&lt;&lt;1&amp;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 &lt; 8; bit++ {
			if (b&gt;&gt;bit)&amp;1 == 1 {
				return bitLen
			}
			bitLen--
		}
	}

	return 0
}

You can use this as:

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}

huangapple
  • 本文由 发表于 2021年10月2日 05:55:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/69412331.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定