# unable to load certificate：OpenSSL 证书格式不对怎么办

> OpenSSL 报 no start line 或 DECODER unsupported，说明给它的文件不是 PEM 证书。这页教你认出 DER、PKCS#7、PKCS#12、私钥和损坏的 PEM，并给出转换命令。

Source: https://ssl.sh/zh/errors/openssl-unable-to-load-certificate/
Last updated: 2026-11-10

**`unable to load certificate` 的意思是：你给 OpenSSL 的文件里，没有它期望的 PEM 格式证书。** 证书本身通常没问题，只是格式不同（DER、PKCS#7、PKCS#12），或者用错了文件（私钥、CSR），或者 PEM 文本在复制时被破坏了。

## 快速修复

修法是先认出文件格式，再用对应的命令转成 PEM。先看文件到底是什么：

```bash
file cert.crt
head -c 64 cert.crt | xxd | head -3
grep -- "-----BEGIN" cert.crt
```

再用对应的命令：

| 看到的内容 | 格式 | 命令 |
|---|---|---|
| `-----BEGIN CERTIFICATE-----` | PEM 证书 | 检查是否损坏（见下文） |
| 二进制，以 `30 82` 开头 | DER 证书 | `openssl x509 -inform DER -in cert.crt -out cert.pem` |
| `-----BEGIN PKCS7-----` 或 `.p7b` | PKCS#7 证书包 | `openssl pkcs7 -print_certs -in cert.p7b -out chain.pem` |
| 二进制 `.pfx` / `.p12` | PKCS#12 | `openssl pkcs12 -in cert.pfx -nokeys -out chain.pem` |
| `BEGIN PRIVATE KEY` / `CERTIFICATE REQUEST` | 不是证书 | 换成正确的文件 |

各种格式和转换方法见 [SSL 格式转换工具](https://ssl.sh/zh/tools/ssl-converter/)。

## 原因

前 3 种是证书用了 PEM 以外的格式，后 3 种是用错文件、PEM 文本损坏和 OpenSSL 1.1.1 的提示写法。

### 1. 证书是 DER 编码

Windows 导出时选了“DER 编码二进制 X.509”（[DER](https://ssl.sh/zh/glossary/der/) 是二进制编码），Java 工具和部分 CA 也会给二进制证书，扩展名常常是 `.cer` 或 `.crt`。

- **确认：** `grep BEGIN` 什么都找不到；`openssl x509 -inform DER -in cert.crt -noout -subject` 能正常输出。
- **修复：** 用表格里的命令转成 PEM。

### 2. 是 PKCS#7 证书包

[PKCS#7](https://ssl.sh/zh/glossary/pkcs7/) 的 `.p7b` / `.p7c` 文件只装证书不装私钥，Windows 和一些 CA 平台常用这种格式。

- **确认：** 文件以 `-----BEGIN PKCS7-----` 开头；或者是二进制，`openssl pkcs7 -inform DER -in file -print_certs` 能用。
- **修复：** 用 `-print_certs` 导出，给 Web 服务器用时站点证书放最前，中间证书在后。

### 3. 是 PKCS#12 文件

[PKCS#12](https://ssl.sh/zh/glossary/pkcs12/) 的 `.pfx` / `.p12` 文件同时包含私钥和证书，有密码保护。阿里云、腾讯云下载 IIS 或 Tomcat 格式时拿到的就是它。

- **修复：** 证书用 `openssl pkcs12 -in cert.pfx -nokeys -out chain.pem`，私钥用 `-nocerts -nodes -out key.pem`。用旧算法（如 RC2）生成的文件，在 OpenSSL 3 上可能需要加 `-legacy`。更省事的办法是在云控制台直接下载 Nginx 或 Apache 格式。

### 4. 用错了文件

把私钥、CSR 或公钥文件传给 `openssl x509`，报错相同。

- **确认：** `grep BEGIN` 显示 `PRIVATE KEY`、`CERTIFICATE REQUEST` 或 `PUBLIC KEY`。
- **修复：** 换成证书文件；查看 CSR 用 `openssl req -in file -noout -text`。

### 5. PEM 文本被破坏

从邮件、微信、网页上复制，可能多了空格、行被合并、`BEGIN`/`END` 行丢了，或者加了 UTF-8 BOM、Windows 换行符。

- **确认：** `cat -A cert.pem | head` 能看到 `^M` 或奇怪字符；`BEGIN` 行的横线数量不对或多了空格。
- **修复：** 执行 `dos2unix`，去掉 BOM，确认每行 64 个 base64 字符，或者重新下载文件。

### 6. Expecting: TRUSTED CERTIFICATE

这只是 OpenSSL 1.1.1 的 `openssl x509` 在找不到可用内容时，报出它在找的 PEM 类型名。它同样接受普通的 `BEGIN CERTIFICATE` 块，所以这句话并不表示你需要一种特殊的“受信任证书”，原因仍是上面几条之一。

## 各环境修法

各环境最后都要得到 PEM 文件，Nginx、Apache 和宝塔只接受 PEM。

**Windows：** 证书导出向导里选“Base64 编码 X.509 (.CER)”，直接得到 PEM。

**Java：** `keytool -exportcert -rfc -alias 名称 -keystore store.jks` 输出 PEM；不加 `-rfc` 输出的是 DER。

**Nginx / Apache / 宝塔：** 只接受 PEM。先转换，再让 `ssl_certificate` / `SSLCertificateFile` 指向 PEM 证书链；宝塔里粘贴的也必须是 PEM 文本。

**在 Windows 上转换：** 没有装 OpenSSL 的 Windows 电脑，可以用 Git for Windows 自带的 openssl，或者在 WSL 里执行上面的命令；也可以在证书管理器（certmgr.msc）里重新导出为 Base64 格式。

**Kubernetes：** TLS Secret 里存的是 PEM 内容的 base64；把 DER 文件 base64 后放进去，控制器加载不了。

## 不要这样做

下面 3 种做法解决不了格式问题，其中一种还会泄露私钥。

- **把扩展名改成 `.pem` 就指望能用。** 扩展名改变不了编码。
- **因为一个文件加载不了，就重新生成私钥和证书。** 转换现有文件即可，很少需要重新签发。
- **把 `.pfx` 和它的密码通过同一个渠道发送。** 里面有私钥。
