当前位置:首页 > 文章列表 > Golang > Go教程 > Go crypto/x509.ParseRevocationList 怎样读取 CRL 撤销条目

Go crypto/x509.ParseRevocationList 怎样读取 CRL 撤销条目

来源:17golang原创 2026-11-10 23:01:57 0浏览 收藏

处理证书吊销列表(CRL)时,真正传给 x509.ParseRevocationList 的不是整段 PEM 文本,而是去掉 PEM 外壳后的 ASN.1 DER 字节。解析成功后得到 *x509.RevocationList,可以读取签发者、更新时间和被撤销证书条目。

最容易混淆的地方有三个:PEM 与 DER 是两层格式;解析 CRL 不等于验证签名;旧的 ParseDERCRL 返回 pkix.CertificateList,新代码应优先使用 ParseRevocationList。

落地结论
  • 先用 pem.Decode 取出 block.Bytes,再传给 ParseRevocationList。
  • 读取条目时优先看 RevokedCertificateEntries,可得到序列号、撤销时间和原因码。
  • 解析只说明编码结构可读;需要确认签发者时,再单独调用 CheckSignatureFrom。

一、先把 PEM 外壳和 DER 内容分开

CRL 文件经常以 -----BEGIN X509 CRL----- 开头。这个文本外壳便于传输,但标准库解析函数接收的是 DER 内容。若把整段 PEM 字符串直接转成字节传入,通常会得到 ASN.1 解析错误。

Go 读取 CRL 时从 PEM 外壳提取 DER 内容再进入 ParseRevocationList 的静态流程说明图
图1:CRL 输入结构说明图,观察 PEM 外壳、DER 字节与 ParseRevocationList 的输入关系。
func decodeCRL(data []byte) ([]byte, error) {
	// PEM 只是编码外壳,先取出其中真正的 DER 字节。
	block, rest := pem.Decode(data)
	if block == nil {
		return nil, errors.New("没有找到 PEM 数据块")
	}
	// 允许调用方检查文件中是否意外拼接了第二段内容。
	if len(bytes.TrimSpace(rest)) != 0 {
		return nil, errors.New("CRL 后仍有未处理的数据")
	}
	if block.Type != "X509 CRL" {
		return nil, fmt.Errorf("不是 X509 CRL: %s", block.Type)
	}
	return block.Bytes, nil
}

如果上游已经提供 DER 文件,就不需要 pem.Decode,直接把文件字节交给解析函数即可。输入层完成后,后面的代码不应再关心文件是 PEM 还是 DER。

二、用 ParseRevocationList 得到结构化 CRL

ParseRevocationList 解析的是 X.509 v2 CRL 的 ASN.1 DER 数据,返回 *x509.RevocationList。它能提供 Issuer、ThisUpdate、NextUpdate、编号以及撤销条目等结构化字段。

func parseCRL(data []byte) (*x509.RevocationList, error) {
	// 解析阶段只负责确认 DER 结构可读,不代表签名已经可信。
	der, err := decodeCRL(data)
	if err != nil {
		return nil, err
	}
	list, err := x509.ParseRevocationList(der)
	if err != nil {
		return nil, fmt.Errorf("解析 CRL 失败: %w", err)
	}
	return list, nil
}

旧代码可能还在使用已弃用的 ParseDERCRL。迁移时不要只把函数名替换掉就结束:返回对象的字段模型也应改为 x509.RevocationList,并明确后续是读取条目还是做签名检查。

三、读取撤销条目的序列号、时间和原因

一张 CRL 可以包含多个被撤销证书。对每个条目,最常用的信息是证书序列号和撤销时间;如果发布方带有原因码,还可以读取 ReasonCode。Go 1.21 起,RevocationListEntry 提供了更适合新代码使用的条目类型。

Go RevocationList 拆分为多个撤销条目并读取序列号时间原因码的静态关系说明图
图2:撤销条目关系说明图,查看一张 CRL 如何对应多个序列号、时间和原因字段。
func summarize(list *x509.RevocationList) []string {
	result := make([]string, 0, len(list.RevokedCertificateEntries))
	for _, entry := range list.RevokedCertificateEntries {
		// 序列号用于和待检查证书建立对应关系,时间用于判断撤销发生时点。
		result = append(result, fmt.Sprintf(
			"serial=%s revoked_at=%s reason=%d",
			entry.SerialNumber.Text(16),
			entry.RevocationTime.Format(time.RFC3339),
			entry.ReasonCode,
		))
	}
	return result
}

不要把 RevokedCertificateEntries 当成“当前仍然有效的黑名单”直接长期缓存。它表达的是这张 CRL 发布时包含的撤销记录,业务还需要结合 ThisUpdate、NextUpdate 和自己的缓存刷新策略判断新鲜度。

四、解析、签名和旧字段要分别处理

解析成功只代表 DER 结构符合标准库能识别的格式。要确认 CRL 是由预期的签发者发布的,应取得对应的 *x509.Certificate,再调用 list.CheckSignatureFrom(issuer)。这个调用仍然不是完整的证书路径验证,它只处理 CRL 签名与签发者之间的关系。

目标使用方式不要混淆
从文件获得 DERpem.DecodePEM 外壳不是 ASN.1 内容
读取 CRL 字段ParseRevocationList解析成功不等于可信
读取被撤销证书RevokedCertificateEntries条目不是完整证书对象
确认签发者CheckSignatureFrom不替代整条证书链验证

如果需要兼容旧数据结构,可暂时读取已弃用的 RevokedCertificates 字段,但新代码应优先围绕 RevocationListEntry 组织结果。这样后续处理原因码和扩展字段时,边界更清楚。

相关问题

DER 文件还需要调用 pem.Decode 吗?

不需要。只有输入带 PEM 文本外壳时才先解码;已经是 DER 的字节可以直接传给 ParseRevocationList。

ParseRevocationList 成功后就能信任 CRL 吗?

不能。它只完成格式解析;需要确认来源时,还要用预期签发者调用 CheckSignatureFrom,并按业务要求处理 CRL 新鲜度。

为什么不继续使用 ParseDERCRL?

ParseDERCRL 已被官方标记为弃用,推荐迁移到 ParseRevocationList,以使用新的 RevocationList 与条目模型。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go net.Resolver.LookupHost 怎样带上下文解析主机地址Go net.Resolver.LookupHost 怎样带上下文解析主机地址
上一篇
Go net.Resolver.LookupHost 怎样带上下文解析主机地址
Go debug/dwarf.Reader 怎么跳过无关调试信息条目
下一篇
Go debug/dwarf.Reader 怎么跳过无关调试信息条目
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    971次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    980次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1090次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1063次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    903次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码