// 安全研究 · 2025-05-09

SSL 证书格式指南:PEM、DER、PKCS#12、JKS 等格式详解

1. 引言:为什么证书格式如此重要?

在配置 HTTPS、开发 Java 应用、或迁移证书时,你是否曾被这些问题困扰:

  • 为什么 Nginx 要 .crt 和 .key 两个文件,而 Tomcat 只需要一个 .jks?
  • 为什么从 CA 拿到的 .pem 文件,直接改名成 .cer 也能用?
  • 为什么有些证书能用文本编辑器打开,有些打开全是乱码?

这些问题的答案都指向同一个主题:证书的存储格式。理解这些格式,是掌握 SSL/TLS 工程实践的必修课。

核心认知:证书格式 ≠ 文件扩展名。同一个证书内容,可以用不同编码格式保存到不同扩展名的文件中。文件扩展名只是“建议”,真正的区别在于编码方式和是否包含私钥。

2. 格式分类体系

SSL/TLS 相关格式可以从两个维度进行分类:

graph TD
    A[证书格式] --> B[按编码方式]
    A --> C[按容器类型]
    
    B --> B1[PEM 文本格式]
    B --> B2[DER 二进制格式]
    
    C --> C1[仅证书<br>单文件/证书链]
    C --> C2[证书+私钥<br>加密打包]
    
    C1 --> D1[.crt / .cer / .pem]
    C1 --> D2[.p7b / .p7c]
    
    C2 --> E1[.p12 / .pfx]
    C2 --> E2[.jks / .keystore]

2.1 两大编码格式

格式 全称 特征 可读性
PEM Privacy Enhanced Mail 文本格式,有头尾标记 ✅ 可用文本编辑器打开
DER Distinguished Encoding Rules 二进制格式 ❌ 打开是乱码

2.2 三大容器类型

类型 包含内容 代表格式
纯证书 仅公钥证书 PEM/DER 编码的 .crt, .cer
证书链 多个证书串联 .p7b, .p7c,或拼接的 .pem
密钥库 证书 + 私钥(加密打包) .p12, .pfx, .jks

3. PEM 格式:互联网上最通用的标准

3.1 什么是 PEM?

PEM(Privacy Enhanced Mail)是一种基于文本的编码格式,它使用 Base64 编码将二进制数据转换为 ASCII 字符,并用明确的头尾标记进行分隔。

PEM 格式的特征:

  • 纯文本,以 -----BEGIN XXX----- 开头,以 -----END XXX----- 结尾
  • 中间是 Base64 编码的数据
  • 可包含证书、私钥、证书链等多种内容
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJ...
...(中间是 Base64 编码的数据)...
-----END CERTIFICATE-----

3.2 PEM 能装什么?

内容类型 头尾标记 典型文件
证书 BEGIN CERTIFICATE / END CERTIFICATE .crt, .cer, .pem
证书链 多个 BEGIN CERTIFICATE 块连续排列 .pem, fullchain.pem
私钥(RSA) BEGIN RSA PRIVATE KEY / END RSA PRIVATE KEY .key
私钥(PKCS#8) BEGIN PRIVATE KEY / END PRIVATE KEY .key
CSR BEGIN CERTIFICATE REQUEST / END CERTIFICATE REQUEST .csr
CRL BEGIN X509 CRL / END X509 CRL .crl

3.3 PEM 的常见扩展名

扩展名 常见内容 说明
.pem 证书/私钥/证书链 最通用,命名最模糊
.crt 证书 Linux/Unix 系统常用
.cer 证书 Windows 平台常用
.key 私钥 命名明确,需严格保护
.csr 证书签名请求 提交给 CA 的申请文件

关键理解:.pem、.crt、.cer 这三个扩展名经常混用。在 Linux 系统中习惯用 .crt,Windows 习惯用 .cer,而 .pem 则是更通用的“兜底”名称。

3.4 PEM 格式示例

单个证书:

-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKJQlJ...
-----END CERTIFICATE-----

证书链(多个证书拼接):

-----BEGIN CERTIFICATE-----
(服务器证书内容)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(中级证书内容)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(根证书内容)
-----END CERTIFICATE-----

私钥:

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0B...
-----END PRIVATE KEY-----

4. DER 格式:PEM 的二进制“兄弟”

4.1 什么是 DER?

DER(Distinguished Encoding Rules)是 ASN.1(Abstract Syntax Notation One)的一种二进制编码规则。简单理解:DER 就是去掉 PEM 的“头尾标记 + Base64 包裹”,直接把二进制数据保存下来。

PEM 与 DER 的关系:

PEM = "-----BEGIN CERTIFICATE-----\n" + Base64(DER) + "\n-----END CERTIFICATE-----\n"

4.2 识别与查看

特征 PEM DER
文件头 -----BEGIN 二进制数据
用文本编辑器打开 可读 乱码
文件大小 约比 DER 大 33%(Base64 膨胀) 较小
# 查看 DER 文件内容(用十六进制查看器)
hexdump -C certificate.der | head

# 判断是 PEM 还是 DER
file certificate.crt
# 输出 "PEM certificate" 或 "data"

4.3 DER 的使用场景

场景 说明
Windows 系统 双击 .cer 文件时,Windows 默认期望 DER 格式
Java 平台 Keytool 导入证书时需要 DER 格式
嵌入式设备 二进制格式解析更简单
证书交换 某些协议要求二进制传输

5. PKCS#7 / P7B:证书链的“公文包”

5.1 什么是 PKCS#7?

PKCS#7(Public-Key Cryptography Standards #7)是一种用于封装加密数据的标准。在证书领域,它常用于存放证书链(多个证书打包)。

特点:

  • 不包含私钥(仅包含证书)
  • 可打包证书链(服务器证书 + 中级证书 + 根证书)
  • 通常使用 DER 编码,但也可以转换为 PEM
扩展名 编码 说明
.p7b 通常 DER Windows 常用
.p7c 通常 DER 同 .p7b
.p7b.pem PEM 转换后的文本版本

5.2 查看与转换

# 查看 P7B 内容(DER)
openssl pkcs7 -in certificate.p7b -print_certs -text -noout

# 查看 P7B 内容(PEM)
openssl pkcs7 -in certificate.pem -print_certs -text -noout

# P7B → PEM 证书链
openssl pkcs7 -in certificate.p7b -print_certs -out fullchain.pem

# PEM 证书链 → P7B
openssl crl2pkcs7 -nocrl -certfile server.crt -certfile intermediate.crt -out certificate.p7b

6. PKCS#12 / PFX:携带私钥的“保险箱”

6.1 什么是 PKCS#12?

PKCS#12(Public-Key Cryptography Standards #12)是一种可同时存储证书和私钥的加密容器格式。它就像一个加密的“保险箱”,用一个密码保护里面的所有内容。

特点:

  • 可包含:服务器证书、中级证书、根证书、私钥
  • 有密码保护,私钥不会明文暴露
  • 用于证书迁移和导入(如 Tomcat、IIS、Exchange)
扩展名 说明
.p12 标准扩展名
.pfx Microsoft 专用名称(同 PKCS#12)

6.2 PKCS#12 的内部结构

一个 PFX 文件内部可以包含多个证书和私钥:

PFX 容器 (密码: 123456)
├── 服务器证书 (CN=example.com)
├── 中级证书 (CA - Intermediate)
├── 根证书 (CA - Root)
└── 私钥 (对应服务器证书)

6.3 PFX 的常用操作

# 查看 PFX 内容(需密码)
openssl pkcs12 -in certificate.pfx -info -noout

# 列出 PFX 中的所有证书(含友好名)
openssl pkcs12 -in certificate.pfx -clcerts -nokeys -password pass:123456

# 从 PFX 提取证书(不含私钥)
openssl pkcs12 -in certificate.pfx -nokeys -out cert.pem -password pass:123456

# 从 PFX 提取私钥(需设置新密码)
openssl pkcs12 -in certificate.pfx -nocerts -out key.pem -nodes

# 创建 PFX(从 PEM 证书和私钥)
openssl pkcs12 -export -in server.crt -inkey server.key \
  -certfile chain.crt -out certificate.pfx -password pass:yourpassword

7. JKS / JCEKS / BKS:Java 生态的密钥库

7.1 什么是 JKS?

JKS(Java KeyStore)是 Java 平台专用的密钥库格式,用于存储证书和私钥。它是 Java 的 keytool 工具默认生成的格式。

格式 全称 特点
JKS Java KeyStore 传统 Java 格式,不支持私钥加密强度高
JCEKS Java Cryptography Extension KeyStore JKS 增强版,支持更强大的加密算法
BKS Bouncy Castle KeyStore 第三方库实现,常用于 Android

重要趋势:从 Java 9 开始,PKCS#12 已成为 Java 的默认密钥库格式,JKS 正在被逐步淘汰。

7.2 JKS 的常用操作

# 查看 JKS 内容
keytool -list -v -keystore keystore.jks -storepass password

# 导入证书到 JKS
keytool -import -trustcacerts -alias example \
  -file server.crt -keystore keystore.jks -storepass password

# 生成密钥对并创建 JKS
keytool -genkey -alias example -keyalg RSA -keysize 2048 \
  -keystore keystore.jks -validity 365

# JKS → PKCS#12
keytool -importkeystore -srckeystore keystore.jks \
  -destkeystore keystore.p12 -deststoretype PKCS12

# 查看 JKS 中的私钥(需额外工具,keytool 不直接支持)
# 推荐先转换为 PKCS#12 再提取

7.3 JKS 与 PKCS#12 对比

对比项 JKS PKCS#12
专有程度 Java 专有 跨平台标准
私钥导出 困难(需转换) 简单(openssl)
密码保护 支持 支持
证书链 支持多别名 每个文件一个主证书
迁移性 仅限 Java 任何平台
Java 9+ 推荐 不推荐 推荐

8. 格式选择指南

8.1 根据服务器选格式

服务器/平台 推荐格式 说明
Nginx PEM(.crt + .key) 分开的两个文本文件
Apache PEM(.crt + .key) 同上
Tomcat PKCS#12(.p12) 推荐,也可用 JKS
IIS PKCS#12(.pfx) Windows 原生支持
Node.js PEM(.crt + .key) 同 Nginx
Java 应用 PKCS#12(.p12) 不再推荐 JKS
Windows 系统 PKCS#12(.pfx)或 DER(.cer) 导入时选择
Android BKS 或 PKCS#12 Bouncy Castle
iOS/macOS PKCS#12(.p12) 钥匙串导入

8.2 根据任务选格式

任务 推荐使用 原因
将证书部署到 Nginx PEM(.crt) 服务器原生支持
将证书导入 Windows PKCS#12(.pfx)或 DER(.cer) Windows 原生支持
迁移证书到另一台服务器 PKCS#12(.p12) 一次性打包证书+私钥+密码
备份证书供后续使用 PKCS#12(.p12) 有密码保护,便于归档
在 Java 应用中使用 PKCS#12(.p12) Java 9+ 标准
分享证书给第三方验证 PEM(.crt) 不含私钥,可公开

9. 格式转换快速参考

9.1 转换大全

源格式 目标格式 命令
PEM (.crt) DER (.cer) openssl x509 -in cert.pem -outform DER -out cert.der
DER (.cer) PEM (.crt) openssl x509 -in cert.der -inform DER -outform PEM -out cert.pem
PEM + KEY PKCS#12 (.pfx) openssl pkcs12 -export -in cert.pem -inkey key.pem -out cert.pfx
PKCS#12 (.pfx) PEM (.crt) openssl pkcs12 -in cert.pfx -nokeys -out cert.pem
PKCS#12 (.pfx) KEY (PEM) openssl pkcs12 -in cert.pfx -nocerts -nodes -out key.pem
PKCS#12 (.pfx) JKS keytool -importkeystore -srckeystore cert.pfx -srcstoretype PKCS12 -destkeystore keystore.jks
JKS PKCS#12 (.pfx) keytool -importkeystore -srckeystore keystore.jks -destkeystore cert.p12 -deststoretype PKCS12
P7B (.p7b) PEM openssl pkcs7 -in cert.p7b -print_certs -out cert.pem

9.2 快速识别当前格式

# 看文件内容
file certificate.crt
# 输出判断:
# "PEM certificate" → 是 PEM 格式
# "data" → 大概率是 DER 格式

# 看文件头(前 20 字节)
hexdump -C certificate.crt | head -1
# 如果看到 "2d 2d 2d 2d 2d"(----) → PEM
# 如果看到 "30 82" → DER(ASN.1 序列开始)

# 尝试用 openssl 读取(万能判断)
openssl x509 -in certificate.crt -text -noout 2>/dev/null && echo "PEM/DER 证书"
openssl pkcs12 -in certificate.pfx -noout 2>/dev/null && echo "PKCS#12 证书"
keytool -list -keystore keystore.jks 2>/dev/null && echo "JKS 密钥库"

10. 常见陷阱与误区

10.1 误区:改扩展名就能转换格式

错误认知:把 cert.pem 改成 cert.cer 就能变成 DER 格式。

真相:扩展名只影响操作系统如何识别文件,不改变文件的实际编码。转换必须使用 openssl 等工具重新编码。

10.2 陷阱:PFX 提取私钥时忘记 -nodes

# 错误方式:私钥再次被加密
openssl pkcs12 -in cert.pfx -nocerts -out key.pem

# 正确方式:-nodes = no DES,输出未加密的私钥
openssl pkcs12 -in cert.pfx -nocerts -nodes -out key.pem

10.3 陷阱:证书链顺序错误

在 Nginx 的 fullchain.pem 中,证书顺序必须是:服务器证书 → 中级证书 → 根证书。顺序错误会导致浏览器报“证书链不完整”。

10.4 陷阱:PEM 文件中的多余空白

PEM 文件如果有多余的空格或换行,可能导致解析失败。确保格式规范,或用工具验证:

openssl x509 -in certificate.pem -text -noout
# 无报错即格式正确

11. 总结:选择格式的本质是理解场景

SSL/TLS 证书的格式看似繁多,但理解后会发现它们服务于不同的使用场景:

场景需求 推荐格式 理由
需要文本可读、便于传输 PEM 纯文本,可复制粘贴
需要在 Windows 中双击查看 DER (.cer) Windows 原生关联
需要打包证书和私钥迁移 PKCS#12 (.pfx) 有密码保护,跨平台
需要在 Java 应用中使用 PKCS#12 Java 9+ 官方推荐
需要部署到 Nginx/Apache PEM 服务器原生支持
需要分享证书链给他人 P7B (.p7b) 不含私钥,适合分发

核心要点:

  1. PEM 和 DER 是编码方式,不是容器格式——它们决定了数据以文本还是二进制存储
  2. PKCS#12 是带私钥的保险箱——适合备份、迁移和导入
  3. JKS 是 Java 的专属格式——在新项目中应避免使用,改用 PKCS#12
  4. 文件扩展名只是建议——真正重要的是文件内容和用途

掌握这些格式,你就能在 Nginx、Tomcat、Apache、IIS 等不同服务器之间自如切换,顺利完成证书部署与迁移任务。

原文 https://blog.csdn.net/2301_79518550/article/details/147495561