PHP调用openssl_pkcs12_read报错error:0308010C的解决方法
解决Ubuntu 22.04下PHP读取.pfx文件报错"error:0308010C"的问题
这个错误的核心原因是Ubuntu 22.04搭载的OpenSSL 3.0默认禁用了RC4、DES这类旧版加密算法,而你的.pfx文件恰好使用了这类算法。终端加-legacy参数是强制启用旧算法兼容,PHP里可以通过以下几种方式解决:
方法一:动态在PHP代码中启用兼容配置
在调用openssl_pkcs12_read前,设置临时的OpenSSL兼容配置,降低安全级别并启用旧算法支持:
// 生成临时OpenSSL兼容配置 $opensslConf = <<<CONF openssl_conf = default_conf [default_conf] ssl_conf = ssl_sect [ssl_sect] system_default = system_default_sect [system_default_sect] CipherString = DEFAULT@SECLEVEL=1 MinProtocol = TLSv1.0 CONF; // 将配置写入临时文件 $tmpConf = tempnam(sys_get_temp_dir(), 'openssl_'); file_put_contents($tmpConf, $opensslConf); putenv("OPENSSL_CONF={$tmpConf}"); // 执行PFX读取操作 $pfxContent = file_get_contents('/path/to/your/file.pfx'); $password = 'your-pfx-password'; $certData = []; $success = openssl_pkcs12_read($pfxContent, $certData, $password); // 清理临时资源 unlink($tmpConf); putenv('OPENSSL_CONF'); if (!$success) { die('读取PFX失败:' . openssl_error_string()); }
方法二:修改系统全局OpenSSL配置(不推荐)
编辑/etc/ssl/openssl.cnf,添加或修改以下内容,让系统默认启用兼容模式:
openssl_conf = default_conf [default_conf] ssl_conf = ssl_sect [ssl_sect] system_default = system_default_sect [system_default_sect] CipherString = DEFAULT@SECLEVEL=1 MinProtocol = TLSv1.0
修改后重启PHP服务(如systemctl restart php8.1-fpm)即可生效。此方法会影响所有依赖OpenSSL的系统程序,可能降低整体安全性,仅在必要时使用。
方法三:调用系统openssl命令(带-legacy参数)
绕开PHP的openssl函数,直接调用终端命令读取,效果和手动加-legacy完全一致:
$pfxPath = '/path/to/your/file.pfx'; $password = 'your-pfx-password'; $passwordEscaped = escapeshellarg($password); // 提取私钥 exec("openssl pkcs12 -in {$pfxPath} -nocerts -nodes -legacy -passin pass:{$passwordEscaped}", $privateKeyOutput, $status); if ($status !== 0) { die('提取私钥失败:' . implode("\n", $privateKeyOutput)); } $privateKey = implode("\n", $privateKeyOutput); // 提取证书 exec("openssl pkcs12 -in {$pfxPath} -clcerts -nokeys -legacy -passin pass:{$passwordEscaped}", $certOutput, $status); if ($status !== 0) { die('提取证书失败:' . implode("\n", $certOutput)); } $certificate = implode("\n", $certOutput); // 后续可使用PHP openssl函数处理资源 $privateKeyResource = openssl_pkey_get_private($privateKey); $certInfo = openssl_x509_parse($certificate);
注意:必须用escapeshellarg()转义密码等用户输入内容,避免命令注入风险。
内容的提问来源于stack exchange,提问作者Fantasmic
相关产品推荐
相关产品推荐

