无法在C#中解密由openssl完成的加密字符串.始终获取Org.BouncyCastle.Security.InvalidKeyException [英] Cannot decrypt in C# an encrypted string done by openssl. Always get Org.BouncyCastle.Security.InvalidKeyException

查看:119
本文介绍了无法在C#中解密由openssl完成的加密字符串.始终获取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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆