解码 OAEP 填充时出现 RSACryptoServiceProvider 错误

RSACryptoServiceProvider error occurred while decoding OAEP padding

我已经阅读了很多关于这个问题的文章,但我似乎找不到解决我的错误的答案。
我有一个 WCF 服务;我的应用程序发送生成的 public RSA 密钥和服务 returns 一组使用 public 密钥加密的 AES 密钥 + IV,但是当我的应用程序随后尝试解密密钥时,我要么获取 "Error occurred while decoding OAEP padding"(如果我将 true 传递给 useOAEP)或 "The parameter is incorrect"(如果我将 false 传递给 useOAEP)。为简单起见,这是使用的全部代码,将异常处理放在一边:

public static string EncryptAES(byte[] aesKey, byte[] aesIV, string publicRSAKey)
{
    using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
    {
        rsa.FromXmlString(publicRSAKey);
        byte[] encryptedKey = rsa.Encrypt(aesKey, true);
        byte[] encryptedIV = rsa.Encrypt(aesIV, true);
        return string.Format("{0}{1}{2}", Convert.ToBase64String(encryptedKey), "\n", Convert.ToBase64String(encryptedIV));
    }
}
public static byte[] Decrypt(string aesKeyorIV)
{
    using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
    {
         byte[] buffer = Convert.FromBase64String(aesKeyorIV);
         rsa.FromXmlString(RSA_Private_Key);
         return rsa.Decrypt(buffer, true); //Exception thrown here
    }
}

(RSA_Private_Key是在静态构造函数中使用rsa.ToXmlString(true)生成的)
publicRSAKey 通过在静态构造函数中发送 rsa.ToXmlString(false) 传递给服务)
我尝试使用 Encrypt/Decrypt(byte[], false) 但它没有任何区别。我也尝试了 Array.Reverse(encryptedKey) 然后 Array.Reverse(buffer)
私钥在设置后永远不会 sent/modified 所以不可能。
我没有想法,调试 WCF 服务非常糟糕。

您描述的问题可能是由于使用了与 Public 密钥不同的私钥造成的。

如果您使用 RSA 提供程序的相同实例生成 public 和 public+私钥,则密钥将匹配。例如

string publicRSAKey = null;
string publicPlusPrivateRSAKey = null;

using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
    publicRSAKey = rsa.ToXmlString(false);
    publicPlusPrivateRSAKey = rsa.ToXmlString(true);
}

如果您从 RSA 提供商的两个不同实例创建密钥,则 public 和 public+私钥将不匹配。例如

string publicRSAKey = null;
string publicPlusPrivateRSAKey = null;

using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
    publicRSAKey = rsa.ToXmlString(false);
}

using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
    publicPlusPrivateRSAKey = rsa.ToXmlString(true);
}

当密钥匹配时,我可以毫无问题地往返。当键不匹配时,我得到 "Error occured while decoding OAEP padding.".

你能验证密钥在运行时是否匹配吗?

由于私钥也将包含 Public 密钥,您可以查看 xml 字符串形式的每个密钥变量的内容,特别是 XML 路径 /RSAKeyValue/Modulus 和 /RSAKeyValue/Exponent,因为它们应该在两者之间匹配。

我终于找到bug了。我的实施如下,经过简化:

  1. 应用程序创建 public+私钥并将 public 密钥发送到服务
  2. 该服务使用 AES 生成的密钥进行响应,该密钥使用 public 密钥加密。
  3. 服务随后尝试解密密钥,然后引发事件以提醒应用程序

我更改了我的实现,例如:

  1. 服务使用加密消息引发事件
  2. 应用程序使用私钥解密消息。

因为我使用一个 Visual Studio 实例来调试 2 个进程(服务的和 visual studio 调试器的),所以我没有意识到 private/public 键是不同的。

感谢@zespri 提供测试思路。