gpt4 book ai didi

c# - 使用 RSA 公钥解密使用 RSA 私钥加密的字符串

转载 作者:行者123 更新时间:2023-11-30 18:33:45 29 4
gpt4 key购买 nike

这是此处未回答问题的副本:Using an RSA Public Key to decrypt a string that was encrypted using RSA Private Key

您可以看到作者使用此处的一些代码找到了解决方案: http://www.codeproject.com/KB/security/PrivateEncryption.aspx

使用该链接中的代码看起来很有前途。唯一缺少的是填充物。我通常使用 PKCS1.5 填充,这是 OpenSSL RSA 的默认设置。

我知道这个问题的答案非常接近。我知道唯一阻碍解密的是加密的 openssl 密文上的 pkcs1.5 填充。

我很惊讶地发现关于这个主题的信息很少,因为在很多情况下,您需要服务器来加密、签名等,并让客户端应用程序向公众验证、解密等键。

我还广泛尝试使用 RSACryptoServiceProvider 来验证使用 OpenSSL 加密产生的哈希值。例如,我会使用明文的 SHA256 哈希进行私钥加密,然后尝试对该签名进行 RSACryptoServiceProvider 验证,但它不起作用。我认为 MS 执行此操作的方式是非标准的,并且可能有特殊的自定义操作。

因此,替代方案是这道题,它只是简单地使用私钥加密密文并使用C#对其进行解密,从而验证其真实性。可以合并哈希,为服务器签名并在客户端验证的数据对象创建一个简单的签名验证系统。

我查看了 PKCS1 RFC、OpenSSL rsa 源代码和其他项目,但在进行 RSA 解密时,我无法得到关于如何考虑 PKCS1 填充的可靠答案。我无法在 OpenSSL 源代码中找到他们处理 PKCS1 填充的位置,否则,我现在可能已经有了答案。

此外,这是我的第一个问题,我知道这是一个未回答问题的重复,那么,该怎么办?我也用谷歌搜索了一下,但一无所获。

我不明白的另一件事是为什么我的解密方法不起作用。由于解密后填充被删除,我的解密数据应该类似于明文,而且还差得远。所以,我几乎可以肯定 pkcs1 填充意味着其他事情正在发生,特别是密文,这意味着密文必须在解密之前进行预处理以删除填充元素。

也许简单地过滤密文以删除填充元素是这里最简单的解决方案......

这是我的解密方法:

    public static byte[] PublicDecryption(this RSACryptoServiceProvider rsa, byte[] cipherData)
{
if (cipherData == null)
throw new ArgumentNullException("cipherData");

BigInteger numEncData = new BigInteger(cipherData);

RSAParameters rsaParams = rsa.ExportParameters(false);
BigInteger Exponent = GetBig(rsaParams.Exponent);
BigInteger Modulus = GetBig(rsaParams.Modulus);

BigInteger decData = BigInteger.ModPow(numEncData, Exponent, Modulus);

byte[] data = decData.ToByteArray();
byte[] result = new byte[data.Length - 1];
Array.Copy(data, result, result.Length);
result = RemovePadding(result);
Array.Reverse(result);
return result;
}

private static byte[] RemovePadding(byte[] data)
{
byte[] results = new byte[data.Length - 4];
Array.Copy(data, results, results.Length);
return results;
}

最佳答案

问题不在于填充。事实上,从解密后的密文中去除填充值其实非常简单。问题出在这个位置的软件上:您可以看到作者使用此处的一些代码找到了解决方案:http://www.codeproject.com/KB/security/PrivateEncryption.aspx

并且随着 Microsoft 的 System.Numeric 实现,它根本无法处理更大的整数...

为了解决这个问题,我在 codeproject 网站上查看了以前版本的代码,最后找到了这个 PublicDecrypt 方法。

    public static byte[] PublicDecryption(this RSACryptoServiceProvider rsa, byte[] cipherData)
{
if (cipherData == null)
throw new ArgumentNullException("cipherData");

BigInteger numEncData = new BigInteger(cipherData);
RSAParameters rsaParams = rsa.ExportParameters(false);
BigInteger Exponent = new BigInteger(rsaParams.Exponent);
BigInteger Modulus = new BigInteger(rsaParams.Modulus);

BigInteger decData2 = numEncData.modPow(Exponent, Modulus);
byte[] data = decData2.getBytes();
bool first = false;
List<byte> bl = new List<byte>();
for (int i = 0; i < data.Length; ++i)
{
if (!first && data[i] == 0x00)
{
first = true;
}
else if (first)
{
if (data[i] == 0x00)
{
return bl.ToArray();
}
bl.Add(data[i]);
}
}
if (bl.Count > 0)
return bl.ToArray();
return new byte[0];
}

这将使用 rsautl 实用程序或 Perl Crypt::OpenSSL::RSA private_encrypt 方法完美解密由 openssl 创建的密文。

另一个重大变化是删除了根本不起作用的 Microsoft BitInteger 库。我最终使用了代码项目文章中提到的那个,并在此处找到: http://www.codeproject.com/Articles/2728/C-BigInteger-Class

此处的关键是根据您使用的 key 大小将库中的 maxintsize 设置为更大的值。对于 4096 位,500 的值工作正常(大约模数的长度)。

调用方法如下:

            var encmsg3 = "JIA7qtOrbBthptILxnurAeiQM3JzSoi5WiPCpZrIIqURKfVQMN1BrondF9kyNzbjTs1DaEKEuMBVwKExZe22yCvXXpm8pwcEGc9EHcVK2MPqNo89tIF8LJcaDqBMwLvxdaa/QgebtpmOVN/TIWfuiV8KR+Wn07KwsgV+3SALbNgbOIR3RtCx3IiQ3tZzybJb08+ZKwJEOT011uwvvGmtJskQgq9PC8kr1RPXMgaP6xMX7PHFJ8ORhkuWOFfCh+R4NhY1cItVhnRewKpIC2qVlpzUYRAgKIKdCXuZDqUQdIponR29eTovvLb0DvKQCLTf9WI1SzUm6pKRn0vLsQL7L3UYHWl43ISrTpDdp+3oclhgRF3uITR4WCvoljephbGc6Gelk5z3Vi6lN0oQaazJ7zIen+a/Ts7ZX3KKlwPl4/lAFRjdjoqu7u4IAK7O7u1Jf2xDiGw18C/eGt8UHl09zU4qQf9/u+7gtJ+10z2NERlLSaCDjVqslwmmxu81pG2gCv8LfpR4JlPaFfBZMGfGBihyGryWhJwizUXXo8wgdoYbHRXe8/gL19qro0ea5pA9aAhDjTpX1Zzbwu2rUU7j6wtwQtUDJOGXXCw1VOHsx6WXeW196RkqG72ucVIaSAlx5TFJv8cnj6werEx1Ung5456gth3gj19zHc8E/Mwcpsk=";
byte[] enc = Convert.FromBase64String(encmsg3);
var dec = rsa2.PublicDecryption(enc);
Debug.Print("PLAINTEXT: " + Encoding.UTF8.GetString(dec));

有人需要完全复制它的唯一最后一件事是将私钥转换为 openssl 格式,以便他们可以在 openssl 和 C# 之间来回传递私钥和公钥。

我使用了 openssl.net,并创建了一个 RSA 实例,并使用 bignumbers 设置了所有变量。这是相关代码:

        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(Properties.Resources.RSAParameters);

RSAParameters par = rsa.ExportParameters(true); // export the private key


using (OpenSSL.Crypto.RSA rsaos = new OpenSSL.Crypto.RSA())
using (BigNumber bnmod = BigNumber.FromArray(par.Modulus))
using (BigNumber bnexp = BigNumber.FromArray(par.Exponent))
using (BigNumber bnD = BigNumber.FromArray(par.D))
using (BigNumber bnP = BigNumber.FromArray(par.P))
using (BigNumber bnQ = BigNumber.FromArray(par.Q))
using (BigNumber bnDmodP = BigNumber.FromArray(par.DP))
using (BigNumber bnDmodQ = BigNumber.FromArray(par.DQ))
using (BigNumber bnInverse = BigNumber.FromArray(par.InverseQ))
{
rsaos.PublicExponent = bnexp;
rsaos.PublicModulus = bnmod;

rsaos.IQmodP = bnInverse;
rsaos.DmodP1 = bnDmodP;
rsaos.DmodQ1 = bnDmodQ;
rsaos.SecretPrimeFactorP = bnP;
rsaos.SecretPrimeFactorQ = bnQ;
rsaos.PrivateExponent = bnD;
string privatekey = rsaos.PrivateKeyAsPEM;
string publickey = rsaos.PublicKeyAsPEM
}

有了它,您可以轻松创建一个 RSA key ,将所有内容导出到 OpenSSL,并在合理范围内加密/解密您想要的任何内容。处理私钥加密和公钥解密就足够了。

很酷。

关于c# - 使用 RSA 公钥解密使用 RSA 私钥加密的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17069827/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com