向 X509v3 授权密钥标识符添加 DirName 和序列号的方法
本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《向 X509v3 授权密钥标识符添加 DirName 和序列号的方法》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~
我正在尝试使用 openssl 和 go 代码生成客户端证书。我有一个 openssl 脚本,可以生成具有所需扩展名的证书,并且我想使用 go 代码实现相同的结果。
使用 openssl
选项.ext
openssl 使用的 options.ext 文件包含以下扩展名:
basicconstraints=ca:false authoritykeyidentifier=keyid,issuer subjectkeyidentifier=hash keyusage=digitalsignature extendedkeyusage=clientauth
生成-client-cert.sh
我目前拥有的openssl脚本如下:
openssl req \ -newkey rsa:2048 \ -keyout cert.crt \ -out cert.csr \ -nodes \ -sha256 openssl x509 \ -req \ -ca ca.crt \ -cakey ca.key \ -in cert.csr \ -out cert.crt \ -days 365 \ -cacreateserial \ -extfile options.ext \ -sha256
生成证书后,我可以使用以下命令查看其详细信息:
openssl x509 -in cert.crt -text -noout
生成的证书具有以下结构:
certificate:
data:
version: 3 (0x2)
serial number:
xx:xx:xx:xx:xx:xx:xx:xx
signature algorithm: sha256withrsaencryption
issuer: cn=xxx
validity
not before: jan 1 00:00:00 2023 gmt
not after : jan 1 00:00:00 2024 gmt
subject: cn=xxx
subject public key info:
public key algorithm: rsaencryption
rsa public-key: (2048 bit)
modulus:
...
exponent: 65537 (0x10001)
x509v3 extensions:
x509v3 basic constraints:
ca:false
x509v3 authority key identifier:
dirname:cn=xxx
serial:xx:xx:xx:xx:xx:xx:xx:xx
x509v3 subject key identifier:
...
x509v3 key usage:
digital signature
x509v3 extended key usage:
tls web client authentication
signature algorithm: sha256withrsaencryption
它应该看起来像这样:
x509v3 authority key identifier:
dirname:cn=xxx
serial:xx:xx:xx:xx:xx:xx:xx:xx
执行代码
在我的 go 代码中,我使用 x509 包来生成证书。但是,我不确定如何设置 x509v3 授权密钥标识符扩展。这是我的 go 代码的相关部分:
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"os"
"time"
)
...
var cacertificate *x509.certificate
var caprivatekey *rsa.privatekey
var authoritykeyidentifiervalue []byte // how to write this?
template := &x509.certificate{
subject: pkix.name{
commonname: "xxx",
},
extraextensions: []pkix.extension{
{
id: asn1.objectidentifier{2, 5, 29, 35},
value: authoritykeyidentifiervalue,
},
},
keyusage: x509.keyusagedigitalsignature,
extkeyusage: []x509.extkeyusage{x509.extkeyusageclientauth},
notbefore: time.now(),
notafter: time.now().adddate(0, 0, 365),
isca: false,
basicconstraintsvalid: true,
}
privatekey, err := rsa.generatekey(rand.reader, 2048)
if err != nil {
// err
}
certificatebytes, err := x509.createcertificate(rand.reader, template, cacertificate, &privatekey.publickey, caprivatekey)
if err != nil {
// err
}
// out
如何将 dirname 和序列号添加到 x509v3 授权密钥标识符?
相关
- http://oid-info.com/get/2.5.29.35
- https://github.com/golang/go/issues/47096(原始问题)
当我尝试这个时:
var capublickeybytes []byte
publickeyhash := (sha1.sum(capublickeybytes))[:]
var dirname string
authoritykeyidentifiervalue := []byte{0x30, len(publickeyhash)}
authoritykeyidentifiervalue = append(authoritykeyidentifiervalue, publickeyhash...)
authoritykeyidentifiervalue = append(authoritykeyidentifiervalue, 0x80, len(dirname))
authoritykeyidentifiervalue = append(authoritykeyidentifiervalue, []byte(dirname)...)
...
结果是:
X509v3 Authority Key Identifier:
0....0...<....).!.r[..F.....".hCN=xxx.....$...D正确答案
authoritykeyidentifiervalue 可以使用 asn1.marshal 生成。下面的演示根据 rfc 5280定义了 struct authkeyid > 并使用此结构生成值:
package main
import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/hex"
"encoding/pem"
"fmt"
"math/big"
)
// rfc 5280, a.2. implicitly tagged module, 1988 syntax
//
// authoritykeyidentifier ::= sequence {
// keyidentifier [0] keyidentifier optional,
// authoritycertissuer [1] generalnames optional,
// authoritycertserialnumber [2] certificateserialnumber optional }
// -- authoritycertissuer and authoritycertserialnumber must both
// -- be present or both be absent
type authkeyid struct {
keyidentifier []byte `asn1:"optional,tag:0"`
authoritycertissuer generalnames `asn1:"optional,tag:1"`
authoritycertserialnumber *big.int `asn1:"optional,tag:2"`
}
// rfc 5280, a.2. implicitly tagged module, 1988 syntax
//
// generalnames ::= sequence size (1..max) of generalname
//
// generalname ::= choice {
// othername [0] anothername,
// rfc822name [1] ia5string,
// dnsname [2] ia5string,
// x400address [3] oraddress,
// directoryname [4] name,
// edipartyname [5] edipartyname,
// uniformresourceidentifier [6] ia5string,
// ipaddress [7] octet string,
// registeredid [8] object identifier }
type generalnames struct {
name []pkix.rdnsequence `asn1:"tag:4"`
}
func gen(issuer *x509.certificate) ([]byte, error) {
return asn1.marshal(authkeyid{
keyidentifier: issuer.subjectkeyid,
authoritycertissuer: generalnames{name: []pkix.rdnsequence{issuer.issuer.tordnsequence()}},
authoritycertserialnumber: issuer.serialnumber,
})
}
func main() {
cacert := `-----begin certificate-----
miibotccauegawibagiqgocjdjn1y6rgwebxw8v8mdakbggqhkjopqqdajammq8w
dqydvqqkewznesbpcmcxezarbgnvbamtck15ifjvb3qgq0ewhhcnmjmwnte2mtqy
ntuwwhcnmjmwnte3mtuyntuwwjammq8wdqydvqqkewznesbpcmcxezarbgnvbamt
ck15ifjvb3qgq0ewwtatbgcqhkjopqibbggqhkjopqmbbwncaarzqz2ka7fi6w9/
32sjhtajrke+vqyx7hfnmtx1inpbajnfvonf2silh5nqms50jpnvgivehtbfl0a0
dcurufhno1cwvtaobgnvhq8baf8ebamcaqqwewydvr0lbawwcgyikwybbquhawew
dwydvr0taqh/bauwaweb/zadbgnvhq4efgqu5y48dj96lqwvh3s/anj/6sgy/j4w
cgyikozizj0eawidsaawrqihanqdh6sgz014wvfdh0zhbeghdb2tqxzujxa7ymo3
80unaiapzp4wlzqlb+j4fipnep+txru01jgfaksml2yhv3mewg==
-----end certificate-----`
b, _ := pem.decode([]byte(cacert))
if b == nil {
panic("couldn't decode test certificate")
}
issuer, err := x509.parsecertificate(b.bytes)
if err != nil {
panic(err)
}
authoritykeyidentifiervalue, err := gen(issuer)
if err != nil {
panic(err)
}
fmt.println(hex.encodetostring(authoritykeyidentifiervalue))
}
十六进制编码值为:
30548014e58e3c0c9f7a2d05958774bf68d27fe921b2fe3ea12aa4283026310f300d060355040a13064d79204f7267311330110603550403130a4d7920526f6f7420434182101a80a30c937563aac65846d75bc57c30
十六进制字符串可以使用诸如 asn.1 javascript 解码器:
以下 c# 演示给出相同的结果:
using system.security.cryptography.x509certificates;
using system.text;
internal class program
{
private static void main(string[] args)
{
var certbytes = encoding.ascii.getbytes(@"-----begin certificate-----
miibotccauegawibagiqgocjdjn1y6rgwebxw8v8mdakbggqhkjopqqdajammq8w
dqydvqqkewznesbpcmcxezarbgnvbamtck15ifjvb3qgq0ewhhcnmjmwnte2mtqy
ntuwwhcnmjmwnte3mtuyntuwwjammq8wdqydvqqkewznesbpcmcxezarbgnvbamt
ck15ifjvb3qgq0ewwtatbgcqhkjopqibbggqhkjopqmbbwncaarzqz2ka7fi6w9/
32sjhtajrke+vqyx7hfnmtx1inpbajnfvonf2silh5nqms50jpnvgivehtbfl0a0
dcurufhno1cwvtaobgnvhq8baf8ebamcaqqwewydvr0lbawwcgyikwybbquhawew
dwydvr0taqh/bauwaweb/zadbgnvhq4efgqu5y48dj96lqwvh3s/anj/6sgy/j4w
cgyikozizj0eawidsaawrqihanqdh6sgz014wvfdh0zhbeghdb2tqxzujxa7ymo3
80unaiapzp4wlzqlb+j4fipnep+txru01jgfaksml2yhv3mewg==
-----end certificate-----");
using var issuer = new x509certificate2(certbytes);
var e = x509authoritykeyidentifierextension.createfromcertificate(issuer, true, true);
console.writeline(bytearraytohex(e.rawdata));
}
private static string bytearraytohex(byte[] bytes)
{
var builder = new stringbuilder(bytes.length * 2);
for (int i = 0; i < bytes.length; i++)
{
builder.append($"{bytes[i]:x2}");
}
return builder.tostring();
}
}
更新:
这是 gen 的更新版本,其中包含电子邮件地址:
func gen(issuer *x509.Certificate) ([]byte, error) {
rdnSequence := issuer.Issuer.ToRDNSequence()
if len(issuer.EmailAddresses) > 0 {
oidEmail := asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}
emails := make([]pkix.AttributeTypeAndValue, len(issuer.EmailAddresses))
for i, value := range issuer.EmailAddresses {
emails[i].Type = oidEmail
emails[i].Value = value
}
rdnSequence = append(rdnSequence, emails)
}
return asn1.Marshal(authKeyId{
KeyIdentifier: issuer.SubjectKeyId,
AuthorityCertIssuer: generalNames{Name: []pkix.RDNSequence{rdnSequence}},
AuthorityCertSerialNumber: issuer.SerialNumber,
})
}
请注意,oid 已弃用(请参阅 http://oid- info.com/get/1.2.840.113549.1.9.1)。 .net 也不包含它。
理论要掌握,实操不能落!以上关于《向 X509v3 授权密钥标识符添加 DirName 和序列号的方法》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!
mac文件格式转换技巧
- 上一篇
- mac文件格式转换技巧
- 下一篇
- 了解 Go 中的 net 包中使用的“接口”一词的含义
-
- Golang · Go问答 | 1年前 |
- 在读取缓冲通道中的内容之前退出
- 139浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 戈兰岛的全球 GOPRIVATE 设置
- 204浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何将结构作为参数传递给 xml-rpc
- 325浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何用golang获得小数点以下两位长度?
- 478浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何通过 client-go 和 golang 检索 Kubernetes 指标
- 486浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 将多个“参数”映射到单个可变参数的习惯用法
- 439浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 将 HTTP 响应正文写入文件后出现 EOF 错误
- 357浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 结构中映射的匿名列表的“复合文字中缺少类型”
- 352浏览 收藏
-
- Golang · Go问答 | 1年前 |
- NATS Jetstream 的性能
- 101浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何将复杂的字符串输入转换为mapstring?
- 440浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 相当于GoLang中Java将Object作为方法参数传递
- 212浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何确保所有 goroutine 在没有 time.Sleep 的情况下终止?
- 143浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3186次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3398次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3429次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4535次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3807次使用
-
- GoLand调式动态执行代码
- 2023-01-13 502浏览
-
- 用Nginx反向代理部署go写的网站。
- 2023-01-17 502浏览
-
- Golang取得代码运行时间的问题
- 2023-02-24 501浏览
-
- 请问 go 代码如何实现在代码改动后不需要Ctrl+c,然后重新 go run *.go 文件?
- 2023-01-08 501浏览
-
- 如何从同一个 io.Reader 读取多次
- 2023-04-11 501浏览

