这是一个未回答的问题的副本: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#对其进行解密,从而验证它的真实性 . 可以合并散列,为服务器签名并在客户端验证的数据对象 Build 简单的签名验证系统 .
我查看了PKCS1 RFC,OpenSSL rsa源代码和其他项目,我无法得到关于如何在进行RSA Decrypt时考虑PKCS1填充的可靠答案 . 我无法找到他们处理PKCS1填充的OpenSSL源代码中的哪个位置,否则,我现在可能会得到一个答案 .
另外,这是我的第一个问题,我知道这是一个未答复的问题的副本,那么,该怎么办?我也用谷歌搜索,一无所获 .
另一件我不明白的是为什么我的解密方法不起作用 . 由于填充在解密后被删除,我的解密数据应该类似于明文,并且它甚至都不接近 . 因此,我几乎可以肯定pkcs1填充意味着其他事情正在发生,特别是密文,这意味着密文必须在解密之前进行预处理以删除填充元素 .
也许简单地过滤密文来删除填充元素是最简单的解决方案......
这是我的Decrypt方法:
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;
}
2 回答
问题不在于填充 . 实际上,从解密的密文中删除填充值实际上非常简单 . 问题在于此位置的软件:您可以看到作者使用此处的一些代码找到了解决方案:http://www.codeproject.com/KB/security/PrivateEncryption.aspx
并且使用Microsoft的System.Numeric实现,它根本无法处理更大的整数...
为了解决这个问题,我查看了codeproject站点上以前的代码版本,最后得到了这个PublicDecrypt方法 .
这将使用rsautl实用程序或Perl Crypt :: OpenSSL :: RSA private_encrypt方法完美地解密openssl创建的密文 .
另一个重大变化是放弃了微软的BitInteger库,它根本无效 . 我最终使用了代码项目文章中提到的那个,并在此处找到:http://www.codeproject.com/Articles/2728/C-BigInteger-Class
这里的关键是将库中的maxintsize设置为一个值,该值根据您使用的密钥大小有多大 . 对于4096位,值500工作正常(大约模数的长度) .
这是调用方法:
有人需要完全复制它的唯一最后一件事就是将私钥变为openssl格式,以便它们可以在openssl和C#之间来回传递私钥和公钥 .
我使用openssl.net,创建了一个RSA实例,并使用bignumbers设置所有变量 . 这是代码:
有了它,您可以轻松创建RSA密钥,将所有内容导出到OpenSSL,并在合理范围内加密/解密您想要的任何内容 . 处理私钥加密,然后进行公钥解密就足够了 .
凉 .
PublicDecryption函数中的行存在问题:BigInteger numEncData = new BigInteger(cipherData);
它应该是:BigInteger numEncData = GetBig(cipherData);
该行也将被删除:Array.Reverse(result);
您可能会遇到一些填充问题,但如果您能够正确获取数据,则应该很容易纠正 .