
本文详解如何通过 PHP 的 openssl_csr_sign() 函数,利用自有 CA 证书和私钥对 CSR 文件进行签名,生成受信任的非自签名证书,并解决常见的 PEM 格式“no start line”错误。
本文详解如何通过 php 的 `openssl_csr_sign()` 函数,利用自有 ca 证书和私钥对 csr 文件进行签名,生成受信任的非自签名证书,并解决常见的 pem 格式“no start line”错误。
在 PHP 中使用 OpenSSL 创建非自签名证书(即由你自己的证书颁发机构 CA 签发的证书),关键在于正确加载 CSR、CA 证书及私钥——而最常见的失败原因,正是 openssl_csr_sign() 对文件路径格式的严格要求。
❌ 错误写法:直接传入文件名字符串
原始代码中:
$csrdata = "client.crt"; // ⚠️ 错误!这不是 CSR,且未指定协议
$cacert = "CA.crt";
$privkey = array("CA.key", "la_cle_secrete_de_votre_certificat");
会导致 PEM routines:PEM_read_bio:no start line 错误。原因有二:
- openssl_csr_sign() 不接受裸文件名作为参数;它要求 CSR 和 CA 证书必须以 file:// 协议显式声明路径(PHP ≥ 5.6.0);
- 变量名 $csrdata = "client.crt" 存在逻辑错误:.crt 是证书文件,而此处应传入 CSR(Certificate Signing Request)文件,扩展名通常为 .csr 或 .pem。
✅ 正确写法:使用 file:// 协议 + 合法 CSR 文件
修复后的完整示例:
<?php // ✅ 正确:使用 file:// 前缀明确指定本地文件路径
$csrdata = "file://client.csr"; // ← 必须是有效的 PEM 格式 CSR 文件
$cacert = "file://CA.crt"; // ← CA 的公钥证书(X.509)
$privkey = array("file://CA.key", "your_ca_private_key_passphrase"); // ← CA 私钥(含密码,若加密)
// 签发证书:有效期 365 天
$usercert = openssl_csr_sign($csrdata, $cacert, $privkey, 365);
if ($usercert === false) {
die("Certificate signing failed.\n");
}
// 导出为 PEM 字符串
openssl_x509_export($usercert, $certout);
echo "<br>FINAL RESULT:<br><pre class="brush:php;toolbar:false;">" . htmlspecialchars($certout) . "";
// 输出所有 OpenSSL 错误(调试必备)
while (($e = openssl_error_string()) !== false) {
echo "OpenSSL Error: " . htmlspecialchars($e) . ""; } ?>
? 关键注意事项
- CSR 文件必须合法:使用 openssl req -new -key client.key -out client.csr 生成,内容以 -----BEGIN CERTIFICATE REQUEST----- 开头;
- CA 证书与私钥需匹配:CA.crt 必须由 CA.key 对应的私钥签发(或本身就是自签名根 CA);
- 私钥密码不可省略:若 CA.key 被密码保护,$privkey[1] 必须提供正确密码;若无密码,可设为空字符串 "";
- 权限与路径安全:确保 Web 服务器有读取 .csr/.crt/.key 文件的权限,且私钥文件严禁放在 Web 可访问目录下(如 public_html);
- 验证签名结果:用 openssl x509 -in signed.crt -text -noout 检查 Issuer 是否为你 CA 的 DN,Subject 是否匹配 CSR 内容。
通过规范路径协议、校验输入文件类型与格式,并启用错误捕获,即可稳定实现 PHP 层的 CA 级证书签发流程,为内部系统或开发环境构建可信 TLS 基础设施。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











