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

PHP实现C# RSA SHA1签名功能求助(银行支付场景)

银行支付场景下C# RSA SHA1签名转PHP实现问题解决

原C#签名代码(ASCII编码RSA SHA1)

ASCIIEncoding ByteConverter = new ASCIIEncoding();

string dataString = "Data to Sign";

byte[] originalData = ByteConverter.GetBytes(dataString);

byte[] signedData;

RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider();

String PrivateKey= File.ReadAllText(Application.StartupPath + "\\PrivateKey.xml");

RSAalg.FromXmlString(PrivateKey);

signedData = RSAalg.SignData(originalData,SHA1.Create()); // 注:原代码中Key应为RSAalg

String base64String = Convert.ToBase64String(signedData, 0, signedData.Length);

尝试的PHP代码(签名失败)

$baseString = "Data to Sign";
$signedData = null;
$privateKey = file_get_contents(config_path("PrivateKey.pem"));
$privateKeyResource = openssl_pkey_get_private($privateKey);

$signature = null;

if (openssl_sign($baseString, $signedData, $privateKeyResource, OPENSSL_ALGO_SHA1))
            $signature = base64_encode($signedData);

问题分析与修正方案

1. 密钥格式不匹配

C#使用XML格式私钥,而PHP的openssl扩展仅支持PEM格式密钥,这是核心问题之一。需先将XML私钥转换为PEM格式:

  • 方法1:通过C#代码导出PEM私钥
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
    rsa.FromXmlString("你的XML私钥内容");
    // 导出PKCS#1格式的PEM私钥
    string pemPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\n" + 
        Convert.ToBase64String(rsa.ExportRSAPrivateKey(), Base64FormattingOptions.InsertLineBreaks) + 
        "\n-----END RSA PRIVATE KEY-----";
    File.WriteAllText("PrivateKey.pem", pemPrivateKey);
    
  • 方法2:使用OpenSSL工具或离线转换工具完成格式转换

2. 数据编码不一致

C#用ASCIIEncoding.GetBytes()将字符串转成ASCII编码字节,PHP默认字符串编码多为UTF-8,需手动转换为ASCII确保字节一致:

$asciiData = mb_convert_encoding($baseString, 'ASCII');

3. 修正后的PHP代码

$originalData = "Data to Sign";
// 转换为ASCII编码,和C#逻辑对齐
$asciiData = mb_convert_encoding($originalData, 'ASCII');

// 读取转换后的PEM格式私钥
$privateKeyPath = config_path("PrivateKey.pem");
$privateKey = file_get_contents($privateKeyPath);
// 若私钥设置了密码,需添加第二个参数:openssl_pkey_get_private($privateKey, "你的密码")
$privateKeyResource = openssl_pkey_get_private($privateKey);

$signedData = '';
$signature = '';

// 使用SHA1签名,默认PKCS#1 v1.5填充(与C# RSACryptoServiceProvider默认填充一致)
if (openssl_sign($asciiData, $signedData, $privateKeyResource, OPENSSL_ALGO_SHA1)) {
    $signature = base64_encode($signedData);
} else {
    // 打印错误信息用于排查
    error_log(openssl_error_string());
}

// 输出最终签名
echo $signature;

额外排查点

  • 检查私钥是否完整,PEM格式的首尾标记(-----BEGIN RSA PRIVATE KEY-----和-----END RSA PRIVATE KEY-----)是否正确
  • 确认PHP环境已启用openssl扩展
  • 若签名仍失败,可通过openssl_error_string()获取具体错误信息定位问题

内容的提问来源于stack exchange,提问作者masood jooibar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 23:02:42