如何将RSA模数与指数转换为适配PHP openssl_encrypt()的PEM格式
嘿,我之前也踩过这个坑!单独的RSA模数(Modulus)和指数(Exponent)确实没法直接给openssl_encrypt()用,得把它们转换成标准的PEM格式公钥才行,下面给你两种简单的实现方法:
将RSA模数+指数转换为PHP可识别的公钥格式
PHP的OpenSSL系列函数只认X.509或PKCS#8标准的PEM编码公钥,而单独的Modulus和Exponent是RSA公钥的原始核心组件,我们需要把它们组装成符合ASN.1规范的结构,再编码成PEM格式。
方法1:PHP代码直接生成(最简便,无需额外工具)
直接用PHP代码把组件组装成合法的PEM公钥,这里有个现成的可复用函数:
function rsaComponentsToPem($modulusHex, $exponentHex) { // 将十六进制的模数和指数转成二进制 $modulus = hex2bin($modulusHex); $exponent = hex2bin($exponentHex); // 构建RSA公钥的ASN.1基本结构 $modLen = strlen($modulus); $expLen = strlen($exponent); // 组装RSA公钥的SEQUENCE $rsaSeq = chr(0x30) . chr(0x82) . chr(($modLen + $expLen + 10) >> 8) . chr(($modLen + $expLen + 10) & 0xFF); $rsaSeq .= chr(0x02) . chr(0x82) . chr($modLen >> 8) . chr($modLen & 0xFF) . $modulus; $rsaSeq .= chr(0x02) . chr($expLen >> 8) . chr($expLen & 0xFF) . $exponent; // 包装成X.509 SubjectPublicKeyInfo结构 $spki = chr(0x30) . chr(0x82) . chr((strlen($rsaSeq) + 2) >> 8) . chr((strlen($rsaSeq) + 2) & 0xFF); // 添加上RSA算法标识符 $spki .= chr(0x30) . chr(0x0D) . chr(0x06) . chr(0x09) . chr(0x2A) . chr(0x86) . chr(0x48) . chr(0x86) . chr(0xF7) . chr(0x0D) . chr(0x01) . chr(0x01) . chr(0x01) . chr(0x05) . chr(0x00); $spki .= chr(0x03) . chr(0x82) . chr((strlen($rsaSeq) + 1) >> 8) . chr((strlen($rsaSeq) + 1) & 0xFF) . chr(0x00) . $rsaSeq; // 转成PEM格式 $pem = "-----BEGIN PUBLIC KEY-----\n" . chunk_split(base64_encode($spki), 64, "\n") . "-----END PUBLIC KEY-----\n"; return $pem; } // 使用示例 // 替换成你的模数和指数(十六进制字符串,指数通常是010001即65537) $myModulus = "你的模数十六进制字符串"; $myExponent = "你的指数十六进制字符串"; $publicKeyPem = rsaComponentsToPem($myModulus, $myExponent); // 测试加密是否正常 $testStr = "测试加密内容"; $encrypted = openssl_encrypt($testStr, "RSAES-PKCS1-v1_5", $publicKeyPem, OPENSSL_PKCS1_PADDING); if ($encrypted) { echo "公钥转换成功!加密结果(Base64):" . base64_encode($encrypted); } else { // 打印错误信息排查问题 echo "出错了:" . openssl_error_string(); }
方法2:用OpenSSL命令行辅助(适合调试或批量转换)
如果你不想写代码,也可以用OpenSSL命令行快速生成PEM公钥:
- 第一步:创建一个文本文件(比如
rsa-keys.txt),写入以下内容:Modulus=你的模数十六进制字符串 Exponent=你的指数十六进制字符串 - 第二步:执行命令生成PEM公钥:
openssl rsa -pubin -inform RSAPublicKey_in -in rsa-keys.txt -outform PEM -out public-key.pem - 第三步:在PHP中直接读取这个PEM文件:
$publicKey = file_get_contents('public-key.pem'); // 接下来就可以正常用openssl_encrypt()了
关键注意事项
- 确保你的模数和指数是十六进制字符串,如果拿到的是二进制数据,先用
bin2hex()转成十六进制再传入。 - 加密时要选对填充方式:
OPENSSL_PKCS1_PADDING是最常用的(对应RSAES-PKCS1-v1_5),如果需要更安全的OAEP填充,用OPENSSL_PKCS1_OAEP_PADDING。 - 遇到错误时,一定要用
openssl_error_string()查看具体错误,大部分问题都是组件格式不对或者ASN.1组装时的长度计算错误。
内容的提问来源于stack exchange,提问作者Introser
相关产品推荐
相关产品推荐

