You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:08:29