前三篇分别回答了三个问题:为什么需要 PKI,证书如何变成 DER 字节,以及 X.509 v3 的字段和扩展在声明什么。真正把证书接入服务器、浏览器或签名系统时,接下来遇到的通常不是某个字段,而是一桌子相似的文件:
它们有的只有公开证书,有的保存一把私钥,有的能把私钥和证书链一起带走;还有一些根本不是文件格式,而是操作系统或密码设备提供的访问接口。
如果只靠扩展名判断,很容易发生两类相反的事故:把没有私钥的证书链当成完整身份备份,或者把包含私钥的 PFX 当成普通证书公开传递。
这篇文章不再重复 DER 和 PEM 的编码细节,而是建立一条更实用的主线:
先确认对象,再确认容器,最后追问私钥会在哪里以什么形式出现。
一、先分清四个层次:对象、编码、容器和存储边界
很多“证书格式”问题难以沟通,是因为四个层次被压成了同一个词。
例如,一张 X.509 证书可以是 DER 二进制,也可以是带 BEGIN CERTIFICATE 边界的文本。编码变了,证书对象没有变。
PKCS#12 则不同。它不是给同一张证书换一种编码,而是提供一个更大的容器,可以同时装入私钥、终端证书、中间证书和属性,并对其中的内容提供隐私与完整性保护。
Windows Certificate Store、Java KeyStore 和硬件 Token 又增加了一层:它们不仅保存对象,还规定应用怎样查找对象、取得句柄和调用私钥。
| 层次 | 回答的问题 | 典型例子 |
|---|---|---|
| 对象 | 里面究竟是什么 | X.509 证书、私钥、CMS SignedData |
| 编码 | 结构怎样变成字节 | DER、BER |
| 文本表示 | 怎样放进文本环境 | Base64、PEM 边界 |
| 容器 | 多个对象如何组合和保护 | PKCS#7/CMS、PKCS#8、PKCS#12 |
| 存储与接口 | 应用如何找到并使用对象 | Windows Store、Java KeyStore、PKCS#11 |
文件能被解析,只说明语法和编码大致匹配;不说明私钥受到了足够保护,也不说明其中的证书链可信。
二、先做对象盘点:你究竟准备搬什么
在讨论 PKCS 编号之前,先把常见对象列出来。
1. 单张 X.509 证书
证书包含主体公钥、身份声明、用途约束和 CA 签名,本身是公开对象,不包含主体私钥。它可以独立保存为 DER 或文本形式。
2. 证书链
证书链通常是多张证书的集合:终端证书、一个或多个中间 CA 证书,有时还会带上根证书。集合中出现一张根证书,不会自动让接收方信任它;信任锚仍由接收方的本地策略决定。
3. 单个私钥
RSA、EC 等算法各自有算法专用的私钥结构。PKCS#8 在外面增加算法标识和可选属性,让“这是什么算法的私钥”可以由容器自描述。
私钥可能是明文结构,也可能被口令派生密钥加密。两者都可以再用文本边界表示,所以看到 .pem 不能判断它是否加密。
4. 个人身份包
很多系统要迁移的不是一把孤立私钥,而是以下对象的组合:
PKCS#12/PFX 正是为这类个人身份信息交换设计的。
5. 密码设备中的不可导出密钥
如果私钥生成在 HSM、USB Key、智能卡或云密码服务中,并被策略标记为不可导出,那么它就不应被转换成 PFX。应用通过 PKCS#11、CNG/KSP 或厂商接口提交签名、解密请求,只拿到运算结果。
“我要一个证书文件”和“我要把身份迁移到另一台机器”不是同一个需求。后者往往涉及私钥,授权和风险等级完全不同。
三、PKCS#7、CMS 与 P7B:前身、继任者和市场名称
先给结论:PKCS#7 v1.5 是旧规范,CMS 是由 IETF 维护的继任规范,P7B 则是市场上沿用至今的证书包名称。 三者不在同一个维度。
规范升级后,内部语法叫 CMS;但扩展名、MIME 类型和产品界面为了兼容,仍可能写着 P7、P7B 或 PKCS#7。
1. 先按时间线看:CMS 从 PKCS#7 演进而来
PKCS#7 和 CMS 都不是单纯的“证书格式”。它们定义的是密码消息语法:同一个顶层容器可以装普通数据、签名消息、加密信封,也可以只装证书和 CRL。
CMS 不是只给 PKCS#7 改了名字。它保留 ContentInfo、SignedData、EnvelopedData 等核心骨架,同时扩展证书类型、吊销信息和密钥管理方式。
因此,旧 PKCS#7 文件往往能被 CMS 实现读取,但使用 CMS 新能力生成的消息,不保证能被只支持 PKCS#7 v1.5 的旧程序处理。
2. 结构上改了什么
| 对比项 | PKCS#7 v1.5 | CMS |
|---|---|---|
| 顶层入口 | ContentInfo | 继续使用 ContentInfo |
| 签名结构 | SignedData | 保留并扩展 SignedData |
| 加密信封 | EnvelopedData,主要面向密钥传输 | 扩展到密钥传输、密钥协商、预共享密钥和口令等方式 |
| 签名后加密 | 有单独的 signedAndEnvelopedData | 通常通过嵌套 SignedData 与 EnvelopedData 组合 |
| 证书与吊销信息 | X.509 证书、PKCS#6 扩展证书和 CRL | 支持更可扩展的证书与吊销信息选择 |
| 新旧兼容 | 旧基线 | 尽量兼容旧基线,但 CMS 新能力可能无法向下兼容 |
两者的 SignedData 仍共享下面这条主干:
附带内容的 SignedData 通常同时有内容和签名者;分离签名也会省略 eContent,但 signerInfos 仍然非空。因此,不能看到“内容省略”就把对象判断成 P7B。
证书管理所用的“退化 SignedData”条件更严格:digestAlgorithms 和 signerInfos 都为空,eContentType 是 id-data,eContent 必须省略;certificates 和 crls 则可按需要携带证书和/或 CRL。
3. P7B 在哪里:它是常见用法,不是第三套规范
这种结构在 PKCS#7 v1.5 中已经存在,CMS 也保留了它。如果只装普通 X.509 证书和传统 CRL,不使用 CMS 扩展的证书或吊销信息格式,它就落在两代规范的共有子集中,因此证书工具通常仍把它称为 PKCS#7 证书链或 P7B。
所以,P7B 与 CMS 的关系可以记成:
P7B 通常是 PKCS#7/CMS 共有结构中的“只装证书”用法;CMS 则是完整的现行消息语法。
P7B 可以包含多张证书和 CRL,但通常不含私钥。证书被装进同一个集合,也不代表它们已经形成可信链。
4. 规范叫 CMS,为什么市场还在叫 P7?
没有统一答案,要看使用场景。
| 场景 | 市面上的常见叫法 | 实际含义 |
|---|---|---|
| Windows 导入、导出证书链 | P7B、PKCS#7 | 通常是只含证书的 SignedData |
Java keytool 接收 CA 回复 | PKCS#7 certificate chain | 终端证书和 CA 链 |
| OpenSSL 创建兼容证书包 | crl2pkcs7、pkcs7 | 明确按 PKCS#7 v1.5 处理 |
| 新协议、签名或加密接口 | CMS、SignedData、EnvelopedData | 按 RFC 5652 及其扩展处理 |
| S/MIME 邮件附件 | .p7s、.p7m、application/pkcs7-* | 名字保留 P7,但里面承载的是 CMS 对象 |
RFC 8551 的 S/MIME 4.0 就是典型例子:规范明确使用 CMS,却继续保留 application/pkcs7-mime、.p7m 和 .p7s,以兼容已有邮件系统。
如果使用文本封装,RFC 7468 会严格区分标签:旧 PKCS#7 使用 BEGIN PKCS7,CMS 使用 BEGIN CMS。DER 文件没有这层文本标签,此时更不能只靠 .p7b 等扩展名判断规范版本。
因此,“这是 P7 文件”只说明了生态名称,不能证明它严格遵循旧 PKCS#7,还是使用了 CMS。解析内部结构可以判断对象装了什么、是否使用 CMS 专有能力,并据此评估旧工具能否兼容;但 signedData 等 OID 和部分版本号由两代规范共享,不能反推出生成方采用的规范名称。
如果对象只使用共有子集,单靠 DER 二进制通常无法给它唯一贴上“PKCS#7”或“CMS”标签,还要结合 PEM 文本标签、所在协议的约定和生成工具文档。RFC 5652 对兼容输入的建议也是按 CMS 与 PKCS#7 两套内部语法解码,而不是只看 ContentInfo 和版本号。
实务上可以这样沟通:交换证书链时说“P7B 证书包”最容易被运维和 Windows/Java 工具理解;开发新的签名或加密协议时,应使用“CMS”及具体内容类型。
5. 分离签名里的 P1 和 P7 是什么关系
在不少 CA 和电子签章 SDK 中,P1 是“PKCS#1 裸签名”的简称,P7 则指 PKCS#7/CMS SignedData。两者不是互相替代的两种文件格式:P1 位于签名算法层,P7 位于消息封装层。
严格来说,PKCS#1 是 RSA 规范。若某个国密产品把 SM2 的裸签名值也称为“P1”,那是沿用产品接口术语,并不表示它符合 PKCS#1;联调时仍要确认实际算法、签名输入以及 (r, s) 的编码方式。
| 形式 | 包内是否有原文 | 证书与算法上下文 | 验签还需外部原文 |
|---|---|---|---|
| P1 裸签名 | 没有 | 通常由调用方另存 | 需要 |
| P7/CMS 分离式签名 | 没有,eContent 省略 | 可携带证书、算法和签名属性 | 需要 |
| P7/CMS 非分离式签名 | 有,eContent 存在 | 可携带证书、算法和签名属性 | 不需要另传 |
“分离”只描述原文是否放进签名容器,与底层用了哪种签名算法无关。一个分离式 P7 在 RSA 场景下,可以把 PKCS#1 v1.5 的签名值放进 SignerInfo.signature;P7 也可以承载 RSA-PSS、ECDSA、SM2 等其他算法的签名值。
这里还有一个不能忽略的转换边界。CMS 没有 signedAttrs 时,底层签名直接作用于原文;存在 signedAttrs 时,真正被签名的是它们的完整 DER 编码,messageDigest 属性才保存原文摘要。
因此,已有的 P1 签名如果签的是原文,不能直接塞进一个要求 signedAttrs 的 P7 外壳。要么一开始就让密码设备签正确的 CMS 属性字节,要么选择与原签名输入一致的结构;仅仅“补证书、套 ASN.1”可能得到无法验签的对象。
CFCA 的应用指南也体现了这个保存边界:P1 需要连同签名原文和签名证书保存;分离式 P7 需要另存原文;非分离式 P7 已经把原文放进签名对象。无论采用哪种形式,原文的字符集、换行或编码发生变化,都可能导致验签失败。
P1 回答“底层签名值怎样算”,P7 回答“签名值、证书、算法、属性和原文怎样组织”;分离式只回答“原文是否放在包内”。
电子签章还可能在此之上绑定印章数据、版面位置、签署意愿和时间证据。P1 或 P7 只解决其中的密码签名与封装问题,不能单独代表完整的电子签章证据。
6. 用 OpenSSL 创建和查看 P7B 证书包
假设 leaf.pem 是终端证书,chain.pem 包含中间 CA 证书。这里故意使用 crl2pkcs7,因为目标是生成兼容面较广的 P7B 证书包,而不是创建使用 CMS 新能力的签名或加密消息。
使用 openssl pkcs7 查看其中的证书:
OpenSSL 3.6 明确区分两个命令:openssl pkcs7 只处理 PKCS#7 v1.5,openssl cms 处理 CMS。需要签名、验签、加密或解密 CMS 消息时,应使用后者。
输出了几张证书,只能证明容器中有这些对象。是否缺少中间证书、是否混入无关证书,以及链能否到达本地信任锚,仍要单独验证。
四、PKCS#8:让一把私钥带上算法说明
算法专用私钥只描述本算法的参数。例如,传统 RSA 私钥结构里有 n、e、d、p、q 等字段,但接收方仍需要从外部上下文知道它是 RSA。
PKCS#8 在算法专用结构外再包一层:
privateKeyAlgorithm 用 OID 和参数说明怎样解释 privateKey 里的字节。对 RSA,内部仍可能是 PKCS#1 的 RSAPrivateKey;对椭圆曲线,内部是相应 EC 私钥结构。
RFC 5958 用 OneAsymmetricKey 更新了早期 PKCS#8 的 PrivateKeyInfo,保留兼容性的同时允许携带可选公钥。但日常工具仍普遍把这类对象统称为 PKCS#8。
未加密和已加密不是一回事
文本边界可以直接提示对象类型:
表示未加密的 PrivateKeyInfo 或 OneAsymmetricKey。而:
表示 EncryptedPrivateKeyInfo,其中记录加密算法及密文。
| PKCS#8 形式 | 是否加密 | 主要风险 |
|---|---|---|
PrivateKeyInfo / OneAsymmetricKey | 否 | 文件泄露即私钥泄露 |
EncryptedPrivateKeyInfo | 是 | 安全性取决于口令、KDF、参数和使用环境 |
PKCS#8 解决的是“一把私钥怎样自描述和受到文件级保护”,不负责携带完整证书链,也不会自动把私钥与某张证书配成一个可迁移身份。
用 OpenSSL 转换为加密 PKCS#8
下面的命令让 OpenSSL 交互式读取输出口令,避免把口令直接写进命令历史:
生产环境还应根据组织策略和性能基准显式确定 KDF 与迭代参数,并记录生成工具版本。不要为了兼容旧系统默认退回 PKCS#5 v1.5、DES 或其他遗留算法。
检查结构时仍会提示输入口令:
加密私钥文件只保护“静态文件”。应用解锁私钥后,明文密钥仍可能进入进程内存;这与硬件设备中的不可导出密钥不是同一级别的边界。
五、PKCS#12/PFX:把私钥、证书和属性装进迁移包
PKCS#12、P12 和 PFX 在当前实现中通常指同一种交换语法,.p12 与 .pfx 基本可以互换使用。
它的结构比“私钥加证书压成一个文件”更丰富:
friendlyName 可以给对象提供可读名称,localKeyId 常用于把私钥 Bag 与对应证书 Bag 关联起来。因此,PFX 不只是把文件拼接在一起,还保存对象之间的关系。
口令同时面对两类问题
PKCS#12 需要区分隐私保护和完整性保护:
- 私钥或 SafeContents 可以使用口令派生密钥加密,防止不知道口令的人直接读取;
macData可以对AuthenticatedSafe做 MAC,检测内容是否被修改。
有 MAC 不等于所有内容都加密;能通过口令校验也不等于容器里的证书可信。PFX 只保护传输包本身,不能替代证书路径验证。
这里必须把两条保护链分开。RFC 7292 附录 B 明确弃用的是口令隐私模式中的旧 PKCS#12 派生方法;新系统应使用 PKCS#5 的 PBES2 和 PBKDF2。传统 MacData 的完整性保护仍使用 PKCS#12 专用 KDF,不能因为 MAC 摘要是 SHA-256,就说它已经使用 PBKDF2。
2025 年 9 月发布的 RFC 9879 更新了 RFC 7292:它允许在 PKCS#12 的完整性保护中使用 PBMAC1,从而为 MAC 密钥使用 PBKDF2、scrypt 等现代 KDF。该规范要求实现至少支持 PBKDF2 与 HMAC-SHA-256 的组合,但旧软件未必认识这种新结构,生成前仍要确认接收端兼容性。
OpenSSL 3.6 创建 PKCS#12 时,默认使用 PBKDF2 与 AES-256-CBC 加密私钥和证书,并以 SHA-256 作为 MAC 摘要;默认 MAC 仍走传统 PKCS12KDF。只有显式使用 -pbmac1_pbkdf2,才会为完整性保护启用 PBMAC1/PBKDF2。-legacy 是读取 RC2、旧式 3DES 等历史文件的兼容入口,不应成为新文件的默认生成方式。
用 OpenSSL 创建 PFX
命令会交互式询问输出口令。不要用 -password pass:明文 把真实口令写进脚本、进程参数或终端历史。
如果接收端明确支持 RFC 9879,可以在导出命令中增加 -pbmac1_pbkdf2,让 MAC 的密钥派生也使用 PBKDF2。它不是可以盲目启用的“更安全开关”:目标系统若只认识传统 MacData,可能无法验证或导入该文件。
检查算法、Bag 和证书数量:
如果为了排障把私钥导出成未加密文件,普通主机、终端日志、临时目录和备份系统都会进入信任边界。OpenSSL 3 已将旧的 -nodes 标记为弃用,并使用更直白的 -noenc;生产流程不应把这类选项当成常规步骤。
六、证书库与密码设备:文件之外还有访问边界
容器回答“对象怎样放在一起”,证书库和密码接口还要回答“应用怎样使用它们”。
Windows Certificate Store
Windows 区分 Current User 与 Local Machine 等位置,并按 Personal/My、Root、CA 等逻辑存储区组织证书。
“个人证书”经常关联一把私钥,但证书与私钥仍是两个对象:证书保存在 Store 中,私钥可能由传统 CSP、CNG Key Storage Provider、智能卡或虚拟智能卡管理。应用通过证书上下文找到关联的密钥句柄。
导入 PFX 时,还可以决定私钥是否允许再次导出。Microsoft 当前 certutil -importPFX 文档提供 NoExport 等修饰符,说明“是否可导出”是导入策略,不是 .pfx 扩展名天然保证的属性。
Java KeyStore
Java KeyStore 是 KeyStore API 和 Provider 实现的抽象,不等于 JKS 文件格式。JKS 是一种 Java 专有实现;从 JDK 9 开始,默认 KeyStore 类型已经是跨平台的 PKCS12。
因此,看到 keystore.jks 不能推断程序一定按 JKS 加载,看到没有扩展名的 keystore 也不能推断实际类型。检查时应显式指定候选类型;例如先按 PKCS12 尝试:
如果来源明确是旧 JKS,再使用 -storetype JKS 检查。不要仅因为命令使用默认类型失败,就判断文件已经损坏。
迁移时显式指定源和目标类型:
不同 JDK、Provider 和下游产品对算法、口令及可信证书条目的支持可能不同,转换成功后仍要在目标运行时执行真实加载和签名测试。
PKCS#11 与硬件 Token
PKCS#11 不是 .p11 文件格式,而是一套访问密码 Token 的 API。它把设备抽象成 slot、token、session 和 object,私钥对象通过属性限制用途与导出能力。
当前 PKCS#11 v3.2 中,CKA_SENSITIVE、CKA_EXTRACTABLE、CKA_NEVER_EXTRACTABLE 等属性共同描述私钥能否暴露或被包装导出。
所谓“密钥不出设备”需要设备能力、对象属性、角色权限和管理流程共同实现,不能仅凭“使用了 HSM”得出结论。
| 形态 | 私钥在什么地方 | 应用拿到什么 |
|---|---|---|
| PKCS#8 文件 | 文件和应用进程 | 解密后的私钥对象 |
| PKCS#12 文件 | 容器和导入后的密钥存储 | 私钥对象或句柄,取决于导入目标 |
| Windows Store + KSP | 软件或硬件 Provider | 密钥句柄 |
| Java KeyStore | 文件、Provider 或硬件 | Key 对象或 Provider 引用 |
| PKCS#11 Token | Token 内部 | 对象句柄和运算结果 |
七、为什么不能根据扩展名判断真实格式
扩展名只是生态习惯,不是可靠的类型系统。
| 常见扩展名 | 可能内容 | 不能据此推断 |
|---|---|---|
.cer / .crt | DER 或文本 X.509 证书 | 编码一定是 DER 或 PEM |
.pem | 证书、公钥、私钥、CSR、CMS 等文本对象 | 是否含私钥、私钥是否加密 |
.p7b / .p7c | PKCS#7/CMS 证书集合 | 链可信、一定没有其他 CMS 内容 |
.key / .pk8 | 算法专用私钥或 PKCS#8,可能加密 | 算法和保护方式 |
.p12 / .pfx | PKCS#12 个人信息交换包 | 一定含私钥、算法足够安全 |
.jks | 通常是 JKS,也可能只是人为命名 | Java 实际使用的 KeyStore 类型 |
更可靠的检查顺序是:
- 用十六进制或文本边界初步识别表示方式;
- 用与目标结构对应的解析器读取 ASN.1;
- 列出容器中的对象、算法和保护参数;
- 验证私钥与终端证书的公钥是否匹配;
- 独立构建和验证证书链;
- 在目标系统中做导入、加载和真实密码运算。
只改文件后缀,任何一层都没有发生变化。
八、一次可靠迁移应该验证什么
假设现在有一张终端证书 leaf.pem、一份中间证书集合 chain.pem 和一把私钥 private-key.pem,目标是生成可导入的 identity.p12。
1. 先证明私钥和证书匹配
不要只对 RSA 比较 modulus。把两边都转换成统一的 SPKI DER,再比较摘要,可以同时适用于 RSA 和 EC:
两行摘要相同,说明证书中的公钥与私钥推导出的公钥一致;它仍不证明证书链可信。
2. 单独验证链
这里的根证书来自明确的信任配置,而不是因为它恰好出现在某个 P7B 或 PFX 中。
3. 生成并检查 PFX
使用前面的 openssl pkcs12 -export 生成容器,然后至少核对:
- 私钥 Bag 是否存在且只有预期数量;
- 终端证书与私钥是否正确关联;
- 中间证书是否齐全,是否误带无关或不应分发的根证书;
- PBE、KDF、迭代次数和 MAC 算法是否符合目标环境策略;
- 目标系统能否导入,并能否使用私钥完成一次签名或解密测试。
4. 处理临时文件和口令
迁移包只应存在于受控时间窗口和受控位置。口令通过独立安全通道传递,不写入命令行、日志、工单正文或版本库。迁移完成后,应确认备份、临时目录和自动同步系统没有留下额外副本。
如果源私钥被标记为不可导出,正确结果通常不是“想办法导出 PFX”,而是在目标边界重新生成密钥、申请新证书,或者使用经过批准的密钥包装与迁移机制。
九、按需求选择,而不是按后缀选择
| 实际需求 | 优先考虑 | 原因 |
|---|---|---|
| 分发单张公开证书 | X.509 DER 或文本证书 | 对象最小,不涉及私钥 |
| 分发证书和中间链 | CMS/PKCS#7 证书包或约定好的证书集合 | 可承载多张证书,不需要私钥 |
| 保存单把可导出私钥 | 加密 PKCS#8 | 算法自描述,保护参数明确 |
| 跨系统迁移私钥和证书链 | PKCS#12/PFX | 能关联私钥、证书和属性 |
| Java 应用保存身份 | 显式配置的 PKCS12 或其他 KeyStore Provider | 不依赖扩展名和历史默认值 |
| 生产环境使用不可导出私钥 | HSM/Token/KSP/云密码服务接口 | 应用只持有句柄,不复制明文私钥 |
这里没有一个“最先进格式”能替代需求分析。PKCS#12 比单证书复杂,不代表它更适合公开分发;HSM 比文件隔离更强,也不代表它自动解决 PIN、备份、授权和审计问题。
格式决定怎样表达,容器决定怎样组合,Provider 决定怎样访问;真正的安全边界取决于私钥是否会离开受控环境。
下一篇将从“文件里装什么”转向“系统里谁负责什么”:CA 如何审核和签发证书,KMC 为什么只托管需要恢复的加密密钥,以及协同签名怎样让客户端和服务端各持密钥分量、共同签名却不还原完整私钥。
参考资料
- RFC 2315:PKCS #7 Cryptographic Message Syntax v1.5,1998-03
- RFC 5652:Cryptographic Message Syntax(CMS),2009-09
- RFC 8017:PKCS #1 RSA Cryptography Specifications v2.2,2016-11
- RFC 5958:Asymmetric Key Packages(PKCS#8 更新),2010-08
- RFC 7292:PKCS #12 Personal Information Exchange Syntax v1.1,2014-07
- RFC 7468:PKIX、PKCS 与 CMS 的文本编码,2015-04
- RFC 9879:在 PKCS#12 中使用 PBMAC1,2025-09
- RFC 8551:S/MIME 4.0 Message Specification,2019-04
- CFCA 应用开发指南:PKCS#1、分离式 PKCS#7 与非分离式 PKCS#7 的保存要求
- OpenSSL 3.6 官方文档:pkcs7、cms、pkcs8、pkcs12、crl2pkcs7
- Oracle Java SE 17 keytool 文档:JDK 9 起默认 KeyStore 类型为 PKCS12
- Microsoft certutil 文档:PFX 导入导出与私钥策略,更新于 2025-05-01
- OASIS PKCS #11 Specification v3.2,OASIS Standard,2026-06-03
现行工具行为核验于 2026-08-04:OpenSSL 3.6 官方文档与本机 OpenSSL 3.6.3、Oracle Java SE 17 文档、Microsoft Learn、OASIS PKCS#11 v3.2。具体默认值仍应在目标版本和 Provider 上复核。
系列文章
- 理解PKI(一):从密码学历史到公钥基础设施
- 理解PKI(二):从 ASN.1 到 DER,数字证书为什么是一串字节
- 上一篇:拆开 X.509 v3,读懂证书的核心字段与扩展
- 本篇:证书、私钥与容器——PKCS#7、PKCS#8、PKCS#12 有什么区别
笔记整理自《PKI_CA与数字证书技术大全》第三部分第 11~13 章,并按现行 RFC、OpenSSL、Java、Windows 与 PKCS#11 文档校正和补充。
