You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Go中为X509v3 Authority Key Identifier添加DirName与Serial

正确实现Go语言生成带DirName和Serial的Authority Key Identifier扩展证书

问题分析

Go的x509包默认不会自动生成包含DirName和Serial的Authority Key Identifier扩展,直接通过ExtraExtensions构造时,必须严格遵循ASN.1编码格式,否则会出现格式异常。

正确实现步骤

1. 明确Authority Key Identifier的ASN.1结构

该扩展的ASN.1定义为:

AuthorityKeyIdentifier ::= SEQUENCE {
    keyIdentifier             [0] KeyIdentifier           OPTIONAL,
    authorityCertIssuer       [1] GeneralNames            OPTIONAL,
    authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL
}

要生成包含DirName(对应authorityCertIssuer)和Serial(对应authorityCertSerialNumber)的扩展,需严格按照此结构进行DER编码。

2. Go代码实现

以下是完整的可运行示例,通过asn1包构造合规的编码值,再添加到证书扩展中:

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/asn1"
	"math/big"
	"time"
)

// 对应ASN.1结构的Go语言结构体
type authorityKeyIdentifier struct {
	AuthorityCertIssuer       []pkix.RDNSequence `asn1:"optional,tag:1"`
	AuthorityCertSerialNumber *big.Int           `asn1:"optional,tag:2"`
}

func main() {
	// 替换为实际的CA证书和CA私钥
	// caCert, caPrivKey := loadCA()

	// 生成客户端私钥
	clientPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		panic(err)
	}

	// 构造客户端证书模板
	clientTemplate := &x509.Certificate{
		SerialNumber: big.NewInt(123456),
		Subject: pkix.Name{
			CommonName: "client.example.com",
		},
		NotBefore:             time.Now(),
		NotAfter:              time.Now().AddDate(1, 0, 0),
		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
		BasicConstraintsValid: true,
	}

	// 构造Authority Key Identifier内容
	aki := authorityKeyIdentifier{
		AuthorityCertIssuer:       caCert.Subject.ToRDNSequences(),
		AuthorityCertSerialNumber: caCert.SerialNumber,
	}

	// 进行DER编码
	akiDer, err := asn1.Marshal(aki)
	if err != nil {
		panic(err)
	}

	// 添加到证书扩展,OID为2.5.29.35
	clientTemplate.ExtraExtensions = append(clientTemplate.ExtraExtensions, pkix.Extension{
		Id:       asn1.ObjectIdentifier{2, 5, 29, 35},
		Critical: false,
		Value:    akiDer,
	})

	// CA签名生成客户端证书
	clientCertDer, err := x509.CreateCertificate(rand.Reader, clientTemplate, caCert, &clientPrivKey.PublicKey, caPrivKey)
	if err != nil {
		panic(err)
	}

	// 后续可将clientCertDer转为PEM格式保存
	// saveCertToPEM(clientCertDer, "client.crt")
}

3. 验证结果

生成证书后,用OpenSSL命令验证:

openssl x509 -in client.crt -text -noout

会看到符合预期的输出:

X509v3 Authority Key Identifier: 
    DirName:CN=xxx
    serial:xx:xx:xx:xx:xx:xx:xx:xx

注意事项

  • 禁止手动拼接字符串构造扩展值,必须通过ASN.1编码保证格式合规。
  • AuthorityCertIssuer直接使用CA证书Subject的RDN序列,通过caCert.Subject.ToRDNSequences()获取即可。
  • 若需添加KeyIdentifier字段,可在结构体中追加KeyIdentifier []byte asn1:"optional,tag:0"`,并传入CA公钥的SHA-1哈希值。

内容的提问来源于stack exchange,提问作者Hyeonsoo David Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 12:05:35