# SSL_CTX_use_PrivateKey failed：Nginx 私钥加载失败

> Nginx 加载私钥失败，原因可能是私钥不匹配、格式不对、私钥有密码或文件权限问题。看括号里的 OpenSSL 原因，按原因修复。

Source: https://ssl.sh/zh/errors/nginx-ssl-ctx-use-privatekey-failed/
Last updated: 2026-11-10

**Nginx 用不了 `ssl_certificate_key` 指定的私钥时，就会打印这条报错，或者与之相近的 `cannot load certificate key "...": PEM_read_bio_PrivateKey() failed`。** `failed` 后面括号里的内容说明原因：私钥和证书不是一对、文件不是 PEM 私钥、私钥加了密码，或者 Nginx 没权限读这个文件。

## 快速修复

日志括号里的原因决定修法，对照下表就能找到对应的原因。先在 Nginx 之外单独检查[私钥](https://ssl.sh/zh/glossary/private-key/)和证书：

```bash
sudo openssl pkey -in /etc/nginx/ssl/example.com.key -noout && echo "私钥能解析"
sudo openssl x509 -in /etc/nginx/ssl/example.com.crt -noout -pubkey | openssl sha256
sudo openssl pkey -in /etc/nginx/ssl/example.com.key -pubout | openssl sha256
```

再对照日志里括号中的原因：

| 日志里的原因 | 含义 | 看哪里 |
|---|---|---|
| `key values mismatch` | 私钥属于另一张证书 | [key values mismatch](https://ssl.sh/zh/errors/nginx-key-values-mismatch/) |
| `no start line`、`DECODER routines::unsupported` | 不是 PEM 私钥 | 原因 2 |
| `bad decrypt`、`bad password read`、提示输入密码 | 私钥被加密 | 原因 3 |
| `Permission denied`、`No such file or directory` | 文件访问问题 | 原因 4 |

修好后执行 `sudo nginx -t && sudo systemctl reload nginx`。

## 原因

私钥和证书不匹配最常见，其次是格式不对、私钥加密和文件权限。

### 1. 私钥和证书不匹配

- **确认：** 上面两个哈希不一样，或者[密钥匹配工具](https://ssl.sh/zh/tools/key-matcher/)提示证书和 CSR 不是一对。
- **修复：** 见 [Nginx key values mismatch](https://ssl.sh/zh/errors/nginx-key-values-mismatch/)。

### 2. 文件不是 PEM 格式的私钥

Nginx 要求 [PEM](https://ssl.sh/zh/glossary/pem/) 格式，开头是 `-----BEGIN PRIVATE KEY-----`、`BEGIN RSA PRIVATE KEY` 或 `BEGIN EC PRIVATE KEY`。DER 二进制文件、PKCS#12（`.pfx`/`.p12`）、把证书当成私钥、空文件，都会出现 `no start line`（OpenSSL 1.1.1）或 `DECODER routines::unsupported`（OpenSSL 3）这类解码错误。

- **确认：** `head -1 example.com.key` 看不到 `BEGIN ... PRIVATE KEY`，或者 `file example.com.key` 显示是二进制数据。
- **修复：** 转换格式：

```bash
# DER 转 PEM
openssl pkey -inform DER -in example.com.der -out example.com.key
# PFX 中导出 PEM 私钥
openssl pkcs12 -in site.pfx -nocerts -nodes -out example.com.key
```

另外检查文件开头有没有被 Windows 记事本加上的 BOM，或者 CRLF 换行（用 `dos2unix` 处理）。

### 3. 私钥是加密的

带密码的私钥开头是 `BEGIN ENCRYPTED PRIVATE KEY`（或含 `Proc-Type: 4,ENCRYPTED`）。Nginx 会在终端提示输入密码，用 systemd 或面板启动时就报 `bad decrypt` 或 `bad password read`。部分 CA 平台生成 CSR 时会让你设私钥密码，下载下来的私钥就是加密的。

- **修复：** 把密码写进只有 root 可读的文件并引用：

```nginx
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_password_file   /etc/nginx/ssl/example.com.pass;
```

或者用 `openssl pkey -in enc.key -out example.com.key` 解密一次，并 `chmod 600`。

### 4. 文件权限、路径或 SELinux

- **确认：** 报错里有 `BIO_new_file() failed`，并带 `Permission denied` 或 `No such file or directory`。CentOS、Rocky 等系统上，`ls -Z` 显示文件标签是 `user_home_t`（从家目录 mv 过来的文件常见）。
- **修复：** 修正路径，`chown root:root`、`chmod 600`；开启 SELinux 的系统执行 `sudo restorecon -Rv /etc/nginx/ssl` 恢复标签。

### 5. OpenSSL 版本不支持该私钥类型

很老的 OpenSSL 不认识较新的密钥类型，部分 FIPS 模式的构建会拒绝不合规的密钥。

- **修复：** 使用 RSA 2048 位以上或 ECDSA P-256/P-384 私钥，现有版本都支持。

## 各环境修法

Nginx 在任何系统上都要求私钥是未加密的 PEM 文件（或配好密码文件）、路径正确、权限收紧。

**宝塔面板：** 在站点“SSL → 其他证书”里粘贴，不要直接改 `/www/server/panel/vhost/cert/` 下的文件权限。粘贴的私钥若带 `ENCRYPTED` 字样，先在本地解密再粘贴。

**Debian / Ubuntu：** 私钥一般放在 `/etc/ssl/private/` 或 `/etc/nginx/ssl/`。

**CentOS / Rocky / AlmaLinux / Alibaba Cloud Linux：** 放在 `/etc/pki/tls/private/` 或 `/etc/nginx/ssl/`，复制后执行 `restorecon`。

**Docker：** 以只读方式挂载私钥，注意容器以什么用户启动；官方 Nginx 镜像主进程是 root，rootless 镜像可能需要私钥对其运行用户可读。

**Let's Encrypt：** 引用 `/etc/letsencrypt/live/<名称>/privkey.pem`，Certbot 生成的是未加密的 PEM 私钥，权限已经收紧。

## 不要这样做

放宽私钥权限、明文存密码、把私钥放进网站目录，都会增加私钥泄露的风险。

- **为了“解决权限问题”把私钥改成 644 或 777。** 本机任何用户、被入侵的网站程序都能把私钥拷走。
- **把私钥密码写在 Nginx 配置里或所有人可读的文件里。** 用 `ssl_password_file`，并且只给 root 读权限。
- **把证书和私钥放在网站根目录下。** 一条写错的 location 规则就可能让所有人下载到私钥。
