使用 Crypto++ 进行 RSA 编码并使用 c# RSACryptoServiceProvider 进行解码

Posted

技术标签:

【中文标题】使用 Crypto++ 进行 RSA 编码并使用 c# RSACryptoServiceProvider 进行解码【英文标题】:RSA Encode with Crypto++ and Decode with c# RSACryptoServiceProvider 【发布时间】:2019-02-18 13:44:35 【问题描述】:

早上好,

我有一个通过 UDP 套接字进行通信的客户端-服务器应用程序。 我想使用 RSA 对通信进行编码(对密钥进行编码)和 AES 对数据报进行编码。

客户端是c++,服务端是c#

我目前正在尝试使用 RSA 将 AES IV 编码为密钥,但在 c# 中解码时出现错误:

异常类型: System.Security.Cryptography.CryptographicException

异常消息: Cryptography_OAEPDecoding

这是我的编码代码(客户端,c++) [编辑] 将 RSAES_PKCS1v15_Encryptor 更改为 RSAES_OAEP_SHA_Encryptor

const CryptoPP::Integer n("107289343054719278577597018805838066296333011963085747309982087864392842699433873606133118875978275304651444098131280023618603357722259282514858925191134541966986361546234507079678544203468616135436686852577772762581654429498496768721214543879181421353486700409082948114039206485653595743465270256058198245113.");
const CryptoPP::Integer e("17.");   

[...]

void Crypto::CryptRSA(const std::string & bufferIn, std::string & bufferOut, const CryptoPP::Integer &n, const CryptoPP::Integer &e)

    CryptoPP::AutoSeededRandomPool rnd;
    CryptoPP::RSA::PublicKey pubKey;
    pubKey.Initialize(n, e);

    CryptoPP::RSAES_OAEP_SHA_Encryptor encryptor(pubKey);

    size_t ecl = encryptor.CiphertextLength(bufferIn.size());
    CryptoPP::SecByteBlock ciphertext(ecl);

    encryptor.Encrypt(rnd, (CryptoPP::byte*)bufferIn.c_str(), bufferIn.size(), ciphertext);

    bufferOut = std::string((char*)ciphertext.data(), ecl);


这是我的解码代码(服务器端。C#)

private static string _keyN = "107289343054719278577597018805838066296333011963085747309982087864392842699433873606133118875978275304651444098131280023618603357722259282514858925191134541966986361546234507079678544203468616135436686852577772762581654429498496768721214543879181421353486700409082948114039206485653595743465270256058198245113";
private static string _keyE = "17";
private static string _keyD = "50489102613985542860045655908629678257097887982628586969403335465596631858557116991121467706342717790424208987355896481702872168339886721183463023619357421741798172532326737925480536247565713413538718832057918801452980775480097195493999319542331774866185094818177243836015292183598722700529776296282728256145";

[...]

public static byte[] DecryptRSA(byte[] encrypted)

    BigInteger n, e, d;
    BigInteger.TryParse(_keyN, out n);
    BigInteger.TryParse(_keyE, out e);
    BigInteger.TryParse(_keyD, out d);

    CspParameters csp = new CspParameters();
    csp.KeyContainerName = "RSA Test (OK to Delete)";
    csp.ProviderType = 1; 
    csp.KeyNumber = 1;    

    var rsa = new RSACryptoServiceProvider(csp);
    rsa.PersistKeyInCsp = false;

    var param = new RSAParameters()
    
        Modulus = n.ToByteArray().Skip(1).ToArray(),
        Exponent = e.ToByteArray().Skip(1).ToArray(),
        D = d.ToByteArray().Skip(1).ToArray(),
    ;            

    rsa.ImportParameters(param);

    return rsa.Decrypt(encrypted.ToArray(), true);

所以,我想知道我在代码中做错了什么。

在 c++ 中我可以编码和解码我的数据报,但是当我尝试用 c# 解码时它不起作用。

谢谢你,对不起我的英语不好。

【问题讨论】:

认为 Microsoft 不支持 RSA 的 OAEP。您也可以尝试使用 PKCS 填充,认为它被认为是 less secure。您可能还对Cryptographic Interoperability: Keys 感兴趣。 @jww 我已经阅读了这篇文章,但没有成功。这可能是因为它不是最新的(11 岁)或者我没有正确理解它。此外,在本文中,他们将密钥放在了一个文件中,但由于某些限制,我现在不能这样做。 基于Cryptography_OAEPDecoding,.Net 似乎正在使用 OAEP 填充。您的 Crypto++ 加密器正在使用 PKSC 填充。也许你应该使用RSAES_OAEP_SHA_Encryptor。还要注意默认的哈希值。 @jww 感谢您尝试帮助我。不幸的是我仍然有同样的问题 【参考方案1】:

BigInteger.ToByteArray 以 little-endian 形式返回值。

虽然RSAParameters 字段确实是大端(正如here 所解释的那样)。

你可以试试这样的:

 Modulus = n.ToByteArray().Reverse().ToArray()

【讨论】:

感谢您的回答。我按照你说的做了,但还是出现同样的错误

以上是关于使用 Crypto++ 进行 RSA 编码并使用 c# RSACryptoServiceProvider 进行解码的主要内容,如果未能解决你的问题,请参考以下文章

Web Crypto API:如何使用导入的 RSA 公钥加密数据并在 Ruby 中解密数据

加密RSA私钥并使用Crypto ++将其写入文件

如何在 Crypto++ 中使用 RSA OAEP SHA-256 加密/解密数据

RSA加密后做Base64编码

Crypto-RSA-1

使用polarssl进行RSA加密解密