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

从RSACryptoServiceProvider迁移至RSACng:旧加密数据解密问题

解决RSACng解密RSACryptoServiceProvider加密数据的字节序与填充问题

我来帮你梳理下这个问题,其实核心是填充算法不匹配和字节序处理细节没搞对,咱们一步步解决:

问题根源拆解

  1. 填充算法不匹配(最关键)
    RSACryptoServiceProvider调用Encrypt(plainBytes, true)时,默认使用的是OAEP填充 + SHA-1哈希算法,而你在RSACng解密时错误地用了RSAEncryptionPadding.OaepSHA512,这是抛出"参数不正确"异常的核心原因。

  2. 字节序处理逻辑混乱
    CAPI(RSACryptoServiceProvider)的RSA密文是小端字节序(低位字节在前),CNG(RSACng)则用大端字节序(高位字节在前)。你的加密代码已经对密文做了反转转大端,但解密时的字节转换环节可能没对应上。

  3. 密钥导入冗余且易出错
    你通过RSACryptoServiceProvider导出密钥再导入RSACng的方式完全没必要,直接用CNG API打开密钥容器更可靠,还能避免导出导入的潜在问题。

修正后的解决方案

步骤1:统一填充算法

将RSACng解密时的填充改为RSAEncryptionPadding.OaepSHA1,和RSACryptoServiceProvider的默认OAEP填充完全匹配。

步骤2:修正字节序与字符串转换

你的加密代码已经把CAPI的小端密文反转成大端,再转成十六进制字符串。解密时只需把十六进制字符串转回字节数组(这个数组已经是CNG需要的大端格式),不需要再次反转。

步骤3:简化密钥导入逻辑

直接用CNG API打开密钥容器,跳过RSACryptoServiceProvider中转环节。

修正后的代码示例

解密代码(核心修正)

private static byte[] DecryptWithRSACng(string cipherHexText)
{
    // 将加密时生成的十六进制字符串转回字节数组(已为大端格式)
    byte[] cipherBytes = HexStringToByteArray(cipherHexText);
    
    // 直接通过CNG打开机器密钥库中的密钥容器
    CngKeyOpenParameters openParams = new CngKeyOpenParameters(regValue.ToString())
    {
        KeyStoreProviderName = CngProvider.MicrosoftSoftwareKeyStorageProvider.Provider,
        Flags = CngKeyOpenOptions.MachineKeyStore,
        KeyType = CngKeyType.Rsa
    };
    
    using (CngKey cngKey = CngKey.Open(openParams))
    using (RSACng rsacng = new RSACng(cngKey))
    {
        // 使用与CAPI一致的OAEP SHA-1填充
        return rsacng.Decrypt(cipherBytes, RSAEncryptionPadding.OaepSHA1);
    }
}

// 辅助方法:十六进制字符串转字节数组(处理小写格式)
private static byte[] HexStringToByteArray(string hex)
{
    int byteCount = hex.Length / 2;
    byte[] result = new byte[byteCount];
    for (int i = 0; i < byteCount; i++)
    {
        result[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
    }
    return result;
}

加密代码的验证(无需修改)

你的加密代码中反转字节数组的逻辑是正确的,把CAPI的小端密文转成了CNG兼容的大端格式:

// 正确:将CAPI小端密文反转成大端,再转十六进制字符串
Array.Reverse(encBlockData);
cypherText = BitConverter.ToString(encBlockData).Replace("-", "").ToLower();

常见错误排查

  • 若你曾经通过SetOaepParameters修改过CAPI的OAEP哈希算法,需要同步修改RSACng的填充参数。
  • 确保运行代码的用户有权限访问机器密钥库中的密钥容器,否则会出现密钥找不到或访问被拒绝的错误。
  • 检查十六进制字符串转字节数组的逻辑,避免因大小写、字符遗漏导致的字节数组错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:22:28