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

从模数和指数生成RSA公钥:Java转C#实现遇阻求助

解决C#复刻Java RSA加密对接Clover支付API的问题

你的核心问题在于RSA密钥参数的字节序处理错误以及不必要的BigInteger转换导致的格式混乱,以下是修正后的实现步骤和代码:

关键问题分析

  1. 模数处理错误:你将模数转成BigInteger再转回字节数组,会导致字节序从大端变为小端,而RSAParameters要求模数是大端字节数组(与Java的公钥规范一致)。
  2. 指数解析错误:硬编码指数不可靠,应从原始256字节中提取有效部分(去掉前导零),且RSAParameters.Exponent需要指数的大端字节数组(无多余前导零)。
  3. BigInteger符号处理差异:Java的BigInteger是有符号类型,需加0前缀避免负数;而C#的RSAParameters直接使用原始字节数组,无需额外处理符号。

修正后的C#代码

string taPublicKey = "vyYRQA3cS4wV9yk+6bFzA7KLDmE+D/SOP+Q5bNOPG9nUDkAPalRBz12KA5SDxTw2vO1BIeSFUQlYTpzEDb/XkfNNm5e6nqf12M4kdHP1F2EXW4WArilUZegAVw/Y7FvAkA8PQFbfgmBirSa5GS/fuAHjemqEf0DxIgq552IDeFw3nB0vccK6ePue5sVB9Sm2vWpKm/lj2UE4P6z2ngZr5V31cSAVN08USxHvz+MEnoUBKt6aKvfRUAp4iFyIpxlp4eylxY8zizPekS29lcRMsI9hGug2CoKFhhUJ1gD8G280zIoWCxysNvl40k/l8OTtPKrnlhAzQcIyy/RB0lwb6QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGVTU=";

byte[] publicKeyBytes = Convert.FromBase64String(taPublicKey);

// 1. 提取模数:直接取前256字节(大端格式,与Java一致)
byte[] modulus = new byte[256];
Array.Copy(publicKeyBytes, 0, modulus, 0, 256);

// 2. 提取指数:从后256字节中去掉前导零,得到有效大端字节数组
byte[] exponentRaw = new byte[256];
Array.Copy(publicKeyBytes, 256, exponentRaw, 0, 256);
// 找到第一个非零字节的位置(跳过前导零)
int firstNonZeroIndex = Array.FindIndex(exponentRaw, b => b != 0);
byte[] exponent = exponentRaw.Skip(firstNonZeroIndex).ToArray();

// 3. 配置RSA参数
RSAParameters rsaParams = new RSAParameters
{
    Modulus = modulus,
    Exponent = exponent
};

// 4. 加密银行卡数据(保持与Java一致的编码和填充方式)
string cardToEncrypt = "00000000" + "6011361000006668";
string base64EncryptedCard = null;

// 注意:若Java使用的是PKCS#1 v1.5填充,需将第二个参数改为false
using (var rsa = new RSACryptoServiceProvider(2048))
{
    try
    {
        rsa.PersistKeyInCsp = false;
        rsa.ImportParameters(rsaParams);

        // 转换为UTF-8字节(与Java保持一致)
        byte[] cardBytes = Encoding.UTF8.GetBytes(cardToEncrypt);
        // 使用OAEP填充(若Java用PKCS#1则改为false)
        byte[] encryptedBytes = rsa.Encrypt(cardBytes, true);

        base64EncryptedCard = Convert.ToBase64String(encryptedBytes);
    }
    catch (Exception ex)
    {
        // 处理异常,比如日志记录
        Console.WriteLine($"加密失败:{ex.Message}");
    }
    finally
    {
        rsa.PersistKeyInCsp = false;
    }
}

return base64EncryptedCard;

额外注意事项

  • 填充方式一致性:若Java示例中使用的是RSA/ECB/PKCS1Padding(而非OAEP),需将rsa.Encrypt的第二个参数改为false。
  • 字节编码验证:确认Java中是使用UTF-8转换字符串为字节数组,若为其他编码(如ASCII),需同步修改C#中的Encoding类型。
  • 密钥长度匹配:确保RSACryptoServiceProvider的初始化长度(2048)与Clover提供的公钥长度一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 19:57:03