【问题标题】:RSACryptoServiceProvider error occurred while decoding OAEP padding解码 OAEP 填充时发生 RSACryptoServiceProvider 错误
【发布时间】:2015-09-01 01:10:57
【问题描述】:

我已经阅读了很多关于这个问题的文章,但我似乎找不到解决我的错误的答案。
我有 WCF 服务;我的应用程序发送生成的公钥 RSA 密钥,服务返回一组用公钥加密的 AES 密钥+IV,但是当我的应用程序尝试解密密钥时,我要么得到“解码 OAEP 填充时出错”(如果我将 true 传递给 useOAEP)或“参数不正确”(如果我将 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)
私钥在设置后永远不会发送/修改,因此不可能。
我没有想法,调试 WCF 服务非常糟糕。

【问题讨论】:

  • @zespri,我说我正在使用 RSA 加密 AES 密钥。此外,我没有收到任何关于错误长度的错误。
  • @zespri 我正在修改整个代码以寻找可能的错误,我找不到任何会导致这种情况的东西。此外,这曾经在实现 WCF 服务之前起作用。
  • @zespri 我刚刚使用我当前的解决方案进行了测试:加密中从 Convert.ToBase64String(encryptedkey) 返回的内容与解密方法接收到的完全相同相同,即 128 字节-长字节[]。此外,我在 RSA 解密之前运行了一个 HMAC 函数,以保证消息在任何时候都不会改变。我明天(这里几乎是午夜)尝试创建一个测试用例。

标签: c# wcf encryption rsa


【解决方案1】:

您描述的问题可能是由于使用了与公钥不同的私钥引起的。

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

string publicRSAKey = null;
string publicPlusPrivateRSAKey = null;

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

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

string publicRSAKey = null;
string publicPlusPrivateRSAKey = null;

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

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

当键匹配时,我可以毫无问题地往返。当密钥不匹配时,我得到“解码 OAEP 填充时发生错误。”。

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

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

【讨论】:

  • 我想知道您是否几乎在我的帖子末尾阅读过:“(RSA_Private_Key 在静态构造函数中使用 rsa.ToXmlString(true) 生成)(publicRSAKey 通过发送 rsa.ToXmlString 传递给服务) (false) 在静态构造函数中)"。我的字面意思是 RSA_Private_Key 和 RSA_Public_Key 是在同一个 RSACryptoServiceProvider 实例上创建的,一行在另一行之上。正如它应该包含的那样,私钥确实包含公钥。
【解决方案2】:

我终于发现了错误所在。我的实现如下,简化:

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

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

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

由于我使用一个 Visual Studio 实例来调试 2 个进程(服务和 Visual Studio 调试器),我没有意识到私钥/公钥是不同的。

感谢@zespri 提供的测试想法。

【讨论】:

    猜你喜欢
    • 2010-10-31
    • 2018-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    • 2021-07-14
    相关资源
    最近更新 更多