无法在C#中解密由openssl完成的加密字符串.始终获取Org.BouncyCastle.Security.InvalidKeyException [英] Cannot decrypt in C# an encrypted string done by openssl. Always get Org.BouncyCastle.Security.InvalidKeyException
问题描述
我试图在C#中解密一个由openssl通过命令行加密的字符串,但它不断抛出以下异常:
I trying to decrypt a string in C# that was encrypted by openssl via command line but it keep thrown the exception below:
Exception thrown: 'Org.BouncyCastle.Security.InvalidKeyException' in BouncyCastle.Crypto.dll
An unhandled exception of type 'Org.BouncyCastle.Security.InvalidKeyException' occurred in
BouncyCastle.Crypto.dll
Not an RSA key
我正在使用RSA加密,这些是我用来生成.pem文件的命令(来自git bash),用于对测试字符串进行加密/解密:
I am using RSA encryption and these are the commands (from git bash) that I use to generate the .pem file sand encrypt/decrypt a test string:
// Create private key
// openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 -out privkey.pem
// Create public key
// openssl pkey -pubout -in privkey.pem -out pubkey.pem
// "helloworld" as test text
// echo helloworld > clear_text.txt
// Encrypt using public key
// openssl rsautl -encrypt -inkey pubkey.pem -pubin -in clear_text.txt -out crypt.bin
// Decrypt using private key
// openssl rsautl -decrypt -inkey privkey.pem -in crypt.bin -out decrypt.txt
在C#中需要做的只是上面序列的最后一行,而在C#中.这是我用来加载.pem文件(由openssl生成)并解密字符串的C#代码.
What need to do in C# is just the last line of the sequence above but in C#. Here is the C# code that I use to load the .pem files (generated by openssl) and decrypt the string.
static private PemReader publicKeyPemFile;
static private PemReader privateKeyPemFile;
static private string filesRootPath = System.IO.Directory.GetCurrentDirectory() + "/../../../";
static public void LoadKeys()
{
publicKeyPemFile = new PemReader(
(StreamReader)File.OpenText(filesRootPath + "pubkey.pem")
);
privateKeyPemFile = new PemReader(
(StreamReader)File.OpenText(filesRootPath + "privkey.pem")
);
}
static public string RSADecrypt(byte[] cipherTextBytes)
{
RsaKeyParameters keys = (RsaKeyParameters)privateKeyPemFile.ReadObject();
OaepEncoding eng = new OaepEncoding(new RsaEngine());
eng.Init(false, keys);
int length = cipherTextBytes.Length;
int blockSize = eng.GetInputBlockSize();
List<byte> plainTextBytes = new List<byte>();
for (int chunkPosition = 0;
chunkPosition < length;
chunkPosition += blockSize)
{
int chunkSize = Math.Min(blockSize, length - chunkPosition);
plainTextBytes.AddRange(eng.ProcessBlock(
cipherTextBytes, chunkPosition, chunkSize
));
}
string outString = Encoding.UTF8.GetString(plainTextBytes.ToArray());
return outString;
}
但是尝试解密时失败,如下所示.
but when trying to decrypt it fails as below with the exception.
真正困扰我的是,如果我仅使用下面的加密方法使用C#进行加密和解密,那么它可以工作.这是使用由openssl生成的.pem文件的C#加密代码.
What really bugs me is that if I encrypt and decrypt using C# only using the encryption below, it works. Here is a C# encryption code that uses the .pem files generated by openssl.
static public string RSAEncrypt(string clearText)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(clearText);
RsaKeyParameters keys = (RsaKeyParameters)publicKeyPemFile.ReadObject();
OaepEncoding eng = new OaepEncoding(new RsaEngine());
eng.Init(true, keys);
int length = plainTextBytes.Length;
int blockSize = eng.GetInputBlockSize();
List<byte> cipherTextBytes = new List<byte>();
for (int chunkPosition = 0;
chunkPosition < length;
chunkPosition += blockSize)
{
int chunkSize = Math.Min(blockSize, length - chunkPosition);
cipherTextBytes.AddRange(eng.ProcessBlock(
plainTextBytes, chunkPosition, chunkSize
));
}
return result;Convert.ToBase64String(cipherTextBytes.ToArray());
}
但是如果使用openssl加密并尝试使用C#解密总是会崩溃.
but if encrypt with openssl and try to decrypt with C# is always crashes.
最终测试程序
static void Main(string[] args)
{
RSAEncryption.LoadKeys();
RSAEncryption.TestRSAFromOpenSSL();
}
static public void TestRSAFromOpenSSL()
{
byte[] bytes = File.ReadAllBytes(filesRootPath + "crypt.bin");
string outString = RSADecrypt(bytes);
Debug.WriteLine("clear text = " + bytes.Length);
}
有任何线索吗?
谢谢.
推荐答案
我尝试用更简单的代码来复制您的问题,但我做不到.但是尝试解密文本时出现错误.事实证明,我的 openssl
使用pkcs1作为默认编码,而不是oaep.当我更改它时,我就可以使用它.
I tried replicating your problem with a simpler piece of code and I can't. But I got an error when trying to decrypt the text. It turns out that my openssl
uses pkcs1 as it's default encoding rather than oaep. When I changed that, I got it to work.
这是我的代码
byte[] cipherText = Convert.FromBase64String(File.ReadAllText("./crypt.bin"));
PemReader pr = new PemReader((StreamReader)File.OpenText("./privkey.pem"));
var keys = (RsaKeyParameters)pr.ReadObject();
var eng = new Pkcs1Encoding(new RsaEngine());
eng.Init(false, keys);
var length = cipherText.Length;
var blockSize = eng.GetInputBlockSize();
var plainTextBytes = new List<byte>();
for (int chunkPosition = 0; chunkPosition < length; chunkPosition += blockSize)
{
var chunkSize = Math.Min(blockSize, length - chunkPosition);
plainTextBytes.AddRange(eng.ProcessBlock(cipherText, chunkPosition, chunkSize));
}
Console.WriteLine(Encoding.UTF8.GetString(plainTextBytes.ToArray()));
我在Linux机器上通过base64编码运行了加密的文本,以减少传输时出现任何错误的风险.我的代码使用.NET Core 3.1和Bouncy Castle Core 1.86.
I ran the encrypted text through a base64 encoding on my Linux box to lessen the risk of any errors when transfering. My code uses .NET core 3.1 and Bouncy Castle Core 1.86.
令您震惊的一件事是LoadKeys方法.它实际上并没有加载密钥.它设置了一个可以加载密钥的读取器.我的直觉是,如果您两次要求输入相同的密钥,它将不起作用.你这样做吗?
One thing that struck me in your code is the LoadKeys method. It doesn't really load the keys. It sets up a reader that can load the keys. My hunch is that it won't work if you ask for the same key twice. Do you do that?
这篇关于无法在C#中解密由openssl完成的加密字符串.始终获取Org.BouncyCastle.Security.InvalidKeyException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!