在 C# 和 Bouncy Castle 中读取 RSA PrivateKey

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15629551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 17:24:23  来源:igfitidea点击:

Read RSA PrivateKey in C# and Bouncy Castle

c#encryptionrsabouncycastle

提问by C0D3

I have successfully written to public and private key files with OpenSSL format.

我已成功写入 OpenSSL 格式的公钥和私钥文件。

Files:

文件:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpHCHYgawzNlxVebSKXL7vfc/i
hP+dQgMxlaPEi7/vpQtV2szHjIP34MnUKelXFuIETJjOgjWAjTTJoj38MQUWc3u7
SRXaGVggqQEKH+cRi5+UcEObIfpi+cIyAm9MJqKabfJK2e5X/OS7FgAwPjgtDbZO
ZxamOrWWL8KGB+lH+QIDAQAB
-----END PUBLIC KEY-----

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCpHCHYgawzNlxVebSKXL7vfc/ihP+dQgMxlaPEi7/vpQtV2szH
jIP34MnUKelXFuIETJjOgjWAjTTJoj38MQUWc3u7SRXaGVggqQEKH+cRi5+UcEOb
Ifpi+cIyAm9MJqKabfJK2e5X/OS7FgAwPjgtDbZOZxamOrWWL8KGB+lH+QIDAQAB
AoGBAIXtL6jFWVjdjlZrIl4JgXUtkDt21PD33IuiVKZNft4NOWLu+wp17/WZYn3S
C2fbSXfaKZIycKi0K8Ab6zcUo0+QZKMoaG5GivnqqTPVAuZchkuMUSVgjGvKAC/D
12/b+w+Shs9pvqED1CxfvtePXNwL6ZNuaREFC5hF/YpMVyg5AkEA3BUCZYJ+Ec96
2cwsdY6HocW8Kn+RIqMjkNtyLA19cQV5mpIP7kAiW6drBDlraVANi+5AgK2zQ+ZT
hYzs/JfRKwJBAMS1g5/B7XXnfC6VTRs8AMveZudi5wS/aGpaApybsfx1NTLLsm3l
GmGTkbCr+EPzvJ5zRSIAHAA6N6NdORwzEWsCQHTli+JTD5dyNvScaDkAvbYFi06f
d32IXYnBpcEUYT65A8BAOMn5ssYwBL23qf/ED431vLkcig1Ut6RGGFKKaQUCQEfa
UdkSWm39/5N4f/DZyySs+YO90csfK8HlXRzdlnc0TRlf5K5VyHwqDkatmoMfzh9G
1dLknVXL7jTjQZA2az8CQG0jRSQ599zllylMPPVibW98701Mdhb1u20p1fAOkIrz
+BNEdOPqPVIyqIP830nnFsJJgTG2eKB59ym+ypffRmA=
-----END RSA PRIVATE KEY-----

And public key contains just the public key portion of course.

公钥当然只包含公钥部分。

After encrypting my message using the public key. I want to read the private key file and decrypt it but it's not working. I'm getting exceptions trying to read the private key saying can't cast object to asymmetriccipherkey.

使用公钥加密我的消息后。我想读取私钥文件并解密它,但它不起作用。我在尝试读取私钥时遇到异常,说无法将对象强制转换为非对称密码。

Here is my code:

这是我的代码:

public static AsymmetricKeyParameter ReadAsymmetricKeyParameter(string pemFilename)
{
    var fileStream = System.IO.File.OpenText(pemFilename);
    var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(fileStream);
    var KeyParameter = (Org.BouncyCastle.Crypto.AsymmetricKeyParameter)pemReader.ReadObject();
    return KeyParameter;
}

static void Encrypt2(string publicKeyFileName, string inputMessage, string encryptedFileName)
    {   
        UTF8Encoding utf8enc = new UTF8Encoding();
        FileStream encryptedFile = null;

        try
        {
            // Converting the string message to byte array
            byte[] inputBytes = utf8enc.GetBytes(inputMessage);

            // RSAKeyPairGenerator generates the RSA Key pair based on the random number and strength of key required
            /*RsaKeyPairGenerator rsaKeyPairGnr = new RsaKeyPairGenerator();
            rsaKeyPairGnr.Init(new Org.BouncyCastle.Crypto.KeyGenerationParameters(new SecureRandom(), 512));
            Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keyPair = rsaKeyPairGnr.GenerateKeyPair();
            */

            AsymmetricKeyParameter publicKey = ReadAsymmetricKeyParameter(publicKeyFileName);

            // Creating the RSA algorithm object
            IAsymmetricBlockCipher cipher = new RsaEngine();

            // Initializing the RSA object for Encryption with RSA public key. Remember, for encryption, public key is needed
            cipher.Init(true, publicKey);

            //Encrypting the input bytes
            byte[] cipheredBytes = cipher.ProcessBlock(inputBytes, 0, inputMessage.Length);

            //Write the encrypted message to file
            // Write encrypted text to file
            encryptedFile = File.Create(encryptedFileName);
            encryptedFile.Write(cipheredBytes, 0, cipheredBytes.Length);
        }
        catch (Exception ex)
        {
            // Any errors? Show them
            Console.WriteLine("Exception encrypting file! More info:");
            Console.WriteLine(ex.Message);
        }
        finally
        {
            // Do some clean up if needed
            if (encryptedFile != null)
            {
                encryptedFile.Close();
            }
        }

    }

Here is the decrypt function. 2nd one is without using Bouncy Castle, however, I'd rather use Bouncy Castle since later I'll be also encrypting and decrypting in Java.

这是解密函数。第二个是不使用 Bouncy Castle,但是,我宁愿使用 Bouncy Castle,因为稍后我还将使用 Java 进行加密和解密。

static void Decrypt2(string privateKeyFileName, string encryptedFileName, string plainTextFileName)
    {
        UTF8Encoding utf8enc = new UTF8Encoding();
        FileStream encryptedFile = null;
        StreamWriter plainFile = null;
        byte[] encryptedBytes = null;
        string plainText = "";

        try
        {
            // Converting the string message to byte array
            //byte[] inputBytes = utf8enc.GetBytes(inputMessage);

            // RSAKeyPairGenerator generates the RSA Key pair based on the random number and strength of key required
            /*RsaKeyPairGenerator rsaKeyPairGnr = new RsaKeyPairGenerator();
            rsaKeyPairGnr.Init(new Org.BouncyCastle.Crypto.KeyGenerationParameters(new SecureRandom(), 512));
            Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keyPair = rsaKeyPairGnr.GenerateKeyPair();
            */


            StreamReader sr = File.OpenText(privateKeyFileName);
            PemReader pr = new PemReader(sr);

            PemReader pemReader = new PemReader(new StringReader(privateKeyFileName));
            AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
            Console.WriteLine(keyPair.ToString());
            AsymmetricKeyParameter privatekey = keyPair.Private;


            Console.WriteLine(pr.ReadPemObject());
            AsymmetricCipherKeyPair KeyPair = (AsymmetricCipherKeyPair)pr.ReadObject();

            AsymmetricKeyParameter privateKey = ReadAsymmetricKeyParameter(privateKeyFileName);

            // Creating the RSA algorithm object
            IAsymmetricBlockCipher cipher = new RsaEngine();
            Console.WriteLine("privateKey: " + privateKey.ToString());

            // Initializing the RSA object for Decryption with RSA private key. Remember, for decryption, private key is needed
            //cipher.Init(false, KeyPair.Private);
            //cipher.Init(false, KeyPair.Private);
            cipher.Init(false, keyPair.Private);    

            // Read encrypted text from file
            encryptedFile = File.OpenRead(encryptedFileName);
            encryptedBytes = new byte[encryptedFile.Length];
            encryptedFile.Read(encryptedBytes, 0, (int)encryptedFile.Length);

            //Encrypting the input bytes
            //byte[] cipheredBytes = cipher.ProcessBlock(inputBytes, 0, inputMessage.Length);
            byte[] cipheredBytes = cipher.ProcessBlock(encryptedBytes, 0, encryptedBytes.Length);

            //Write the encrypted message to file
            // Write encrypted text to file
            plainFile = File.CreateText(plainTextFileName);
            plainText = Encoding.Unicode.GetString(cipheredBytes);
            plainFile.Write(plainText);
        }
        catch (Exception ex)
        {
            // Any errors? Show them
            Console.WriteLine("Exception encrypting file! More info:");
            Console.WriteLine(ex.Message);
        }
        finally
        {
            // Do some clean up if needed
            if (plainFile != null)
            {
                plainFile.Close();
            }
            if (encryptedFile != null)
            {
                encryptedFile.Close();
            }
        }
    }


    // Decrypt a file
    static void Decrypt(string privateKeyFileName, string encryptedFileName, string plainFileName)
    {
        // Variables
        CspParameters cspParams = null;
        RSACryptoServiceProvider rsaProvider = null;
        StreamReader privateKeyFile = null;
        FileStream encryptedFile = null;
        StreamWriter plainFile = null;
        string privateKeyText = "";
        string plainText = "";
        byte[] encryptedBytes = null;
        byte[] plainBytes = null;

        try
        {
            // Select target CSP
            cspParams = new CspParameters();
            cspParams.ProviderType = 1; // PROV_RSA_FULL 
            //cspParams.ProviderName; // CSP name
            rsaProvider = new RSACryptoServiceProvider(cspParams);

            // Read private/public key pair from file
            privateKeyFile = File.OpenText(privateKeyFileName);
            privateKeyText = privateKeyFile.ReadToEnd();

            // Import private/public key pair
            rsaProvider.FromXmlString(privateKeyText);

            // Read encrypted text from file
            encryptedFile = File.OpenRead(encryptedFileName);
            encryptedBytes = new byte[encryptedFile.Length];
            encryptedFile.Read(encryptedBytes, 0, (int)encryptedFile.Length);

            // Decrypt text
            plainBytes = rsaProvider.Decrypt(encryptedBytes, false);

            // Write decrypted text to file
            plainFile = File.CreateText(plainFileName);
            plainText = Encoding.Unicode.GetString(plainBytes);
            plainFile.Write(plainText);
        }
        catch (Exception ex)
        {
            // Any errors? Show them
            Console.WriteLine("Exception decrypting file! More info:");
            Console.WriteLine(ex.Message);
        }
        finally
        {
            // Do some clean up if needed
            if (privateKeyFile != null)
            {
                privateKeyFile.Close();
            }
            if (encryptedFile != null)
            {
                encryptedFile.Close();
            }
            if (plainFile != null)
            {
                plainFile.Close();
            }
        }

    } // Decrypt

Any help would be greatly appreciated!

任何帮助将不胜感激!

采纳答案by C0D3

I figured this out. Basically to read a private openssl key using BouncyCastle and C# is like this:

我想通了。基本上使用 BouncyCastle 和 C# 读取私有的 openssl 密钥是这样的:

static AsymmetricKeyParameter readPrivateKey(string privateKeyFileName)
{
    AsymmetricCipherKeyPair keyPair;

    using (var reader = File.OpenText(privateKeyFileName))
        keyPair = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject();

    return keyPair.Private;
}

Then this key can be used to decrypt data such as below:

然后此密钥可用于解密数据,如下所示:

AsymmetricKeyParameter key = readPrivateKey(pemFilename);       
RsaEngine e = new RsaEngine();      
e.Init(false, key);

byte[] decipheredBytes = e.ProcessBlock(cipheredData, 0, cipheredData.Length);