openssl_pkey_new() 是 PHP 原生生成 RSA 密钥对最直接方式,需显式设置 private_key_bits≥2048(推荐 4096)和 private_key_type=OPENSSL_KEYTYPE_RSA,再通过 openssl_pkey_export() 和 openssl_pkey_get_details() 分别导出 PEM 格式私钥与公钥。

用 openssl_pkey_new() 生成密钥对最直接
PHP 原生支持 OpenSSL 密钥生成,openssl_pkey_new() 是最常用、最可控的方式。它返回一个资源(resource),后续可导出私钥和公钥。
关键点在于传入配置参数:不指定配置时默认生成 1024 位 RSA 密钥(已不安全),必须显式设置 private_key_bits 和 private_key_type:
-
private_key_bits至少设为2048,推荐4096 -
private_key_type显式设为OPENSSL_KEYTYPE_RSA(PHP 8.0+ 默认仍是 RSA,但显式声明更稳妥) - 若需 ECC 密钥,改用
OPENSSL_KEYTYPE_EC并配合curve_name(如secp384r1)
示例:
$config = [
'private_key_bits' => 4096,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
$resource = openssl_pkey_new($config);
if (!$resource) {
throw new RuntimeException('密钥生成失败:' . openssl_error_string());
}
导出 PEM 格式密钥时注意密码和格式
生成的资源不能直接使用,需用 openssl_pkey_export() 和 openssl_pkey_get_details() 分别导出私钥(含可选密码)和提取公钥。
立即学习“PHP免费学习笔记(深入)”;
常见疏漏:
-
openssl_pkey_export()第二个参数是引用变量,不是返回值;第三个参数是密码(null表示无密码,空字符串''会被当作真实密码处理) - 公钥不能从私钥字符串“截取”,必须用
openssl_pkey_get_details()获取key字段,否则可能导出错误格式(如 ASN.1 DER 而非 PEM) - PEM 公钥以
-----BEGIN PUBLIC KEY-----开头,不是-----BEGIN RSA PUBLIC KEY-----(后者是 PKCS#1,兼容性差)
导出片段:
$privateKey = ''; openssl_pkey_export($resource, $privateKey, null, $config); $details = openssl_pkey_get_details($resource); $publicKey = $details['key']; // 这才是标准 PEM 公钥
命令行 openssl genrsa 与 PHP 的差异要清楚
有人倾向用 exec('openssl genrsa ...'),这在某些共享主机上可能是唯一选择,但有明显限制:
- 无法在内存中完成全流程,私钥会落地到文件,增加泄露风险
- 密码保护用的是
-aes256等参数,PHP 侧无法直接解密——openssl_pkey_get_private()不支持从带密码的 PKCS#1 私钥(即genrsa默认输出)中加载,必须先转成 PKCS#8:openssl pkcs8 -topk8 -in key.pem -out key_pkcs8.pem -v2 aes256 - PHP 8.0+ 对
openssl_pkey_get_private()加载加密私钥的支持仍有限,容易报failed to load private key
结论:除非环境强制限制,否则优先用 PHP 原生函数,控制力更强、路径更清晰。
私钥权限和存储是实际部署中最容易翻车的地方
生成后的私钥字符串本质是敏感凭据,PHP 层面做完导出只是第一步:
- 写入文件时,务必用
chmod 600设置权限(PHP 中可用chmod($file, 0600)),尤其在 CLI 或 Web 服务共用账户时 - 避免把私钥硬编码进配置文件或数据库;如需持久化,应由部署流程注入,或使用密钥管理服务(如 HashiCorp Vault)动态获取
- Web 环境下切勿通过 HTTP 响应输出私钥内容,即使是一次性调试——浏览器缓存、代理日志、CDN 都可能留存
真正麻烦的从来不是“怎么生成”,而是“生成之后怎么不把它搞丢、不让人拿到”。











