簡體   English   中英

C# BouncyCastle - 使用公鑰/私鑰進行 RSA 加密

[英]C# BouncyCastle - RSA Encryption with Public/Private keys

我需要在 C# 中加密數據才能將其傳遞給 Java。 Java 代碼屬於第 3 方,但我已獲得相關來源,因此我決定當 Java 使用 Bouncy Castle 庫時,我將使用 C# 端口。

解密工作正常。 但是,只有當我使用私鑰而不是公鑰使用加密時,解密才有效。 使用公鑰時,解密失敗, unknown block type

顯然RsaEncryptWithPrivate內部的加密在加密時使用了公鑰,所以我不明白為什么這兩種加密方法在功能上不相同:

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.OpenSsl;

public class EncryptionClass
{       
    public string RsaEncryptWithPublic(string clearText
        , string publicKey)
    {
        var bytesToEncrypt = Encoding.UTF8.GetBytes(clearText);

        var encryptEngine = new Pkcs1Encoding(new RsaEngine());

        using (var txtreader = new StringReader(publicKey))
        {
            var keyParameter = (AsymmetricKeyParameter)new PemReader(txtreader).ReadObject();

            encryptEngine.Init(true, keyParameter);
        }

        var encrypted = Convert.ToBase64String(encryptEngine.ProcessBlock(bytesToEncrypt, 0, bytesToEncrypt.Length));
        return encrypted;

    }

    public string RsaEncryptWithPrivate(string clearText
        , string privateKey)
    {
        var bytesToEncrypt = Encoding.UTF8.GetBytes(clearText);

        var encryptEngine = new Pkcs1Encoding(new RsaEngine());

        using (var txtreader = new StringReader(privateKey))
        {
            var keyPair = (AsymmetricCipherKeyPair)new PemReader(txtreader).ReadObject();

            encryptEngine.Init(true, keyPair.Public);
        }

        var encrypted= Convert.ToBase64String(encryptEngine.ProcessBlock(bytesToEncrypt, 0, bytesToEncrypt.Length));
        return encrypted;
    }


    // Decryption:

    public string RsaDecrypt(string base64Input
        , string privateKey)
    {
        var bytesToDecrypt = Convert.FromBase64String(base64Input);

        //get a stream from the string
        AsymmetricCipherKeyPair keyPair;
        var decryptEngine = new Pkcs1Encoding(new RsaEngine());

        using ( var txtreader = new StringReader(privateKey) )
        {
            keyPair = (AsymmetricCipherKeyPair) new PemReader(txtreader).ReadObject();

            decryptEngine.Init(false, keyPair.Private);
        }

        var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(bytesToDecrypt, 0, bytesToDecrypt.Length));
        return decrypted;
    }
}

// In my test project   

    [Test()]
    public void EncryptTest()
    {
        // Set up 
        var input = "Perceived determine departure explained no forfeited";
        var enc = new EncryptionClass();
        var publicKey = "-----BEGIN PUBLIC KEY----- // SNIPPED // -----END PUBLIC KEY-----";
        var privateKey = "-----BEGIN PRIVATE KEY----- // SNIPPED // -----END PRIVATE KEY-----";

        // Encrypt it
        var encryptedWithPublic = enc.RsaEncryptWithPublic(input, publicKey); 

        var encryptedWithPrivate = enc.RsaEncryptWithPrivate(input, privateKey);

        // Decrypt
        var outputWithPublic = payUEnc.RsaDecrypt(encryptedWithPrivate, privateKey); 
        // Throws error: "unknown block type"

        var outputWithPrivate = payUEnc.RsaDecrypt(encryptedWithPrivate, _privateKey); 
        // returns the correct decrypted text, "Perceived determine departure explained no forfeited"

        // Assertion
        Assert.AreEqual(outputWithPrivate, input); // This is true
    }

順便提一下,Java 解密也有同樣的問題——當只用公鑰加密時,它會失敗。

我對密碼學很RsaEncryptWithPublic ,所以我確定我在RsaEncryptWithPublic方法中做了一些非常簡單的錯誤。

編輯:

我還添加了一個單元測試,證明公鑰等於從私鑰中提取的公鑰:

    [Test()]
    public void EncryptCompareTest()
    {
        AsymmetricKeyParameter keyParameterFromPub;
        AsymmetricKeyParameter keyParameterFromPriv;
        AsymmetricCipherKeyPair keyPair;

        using (var txtreader = new StringReader(_publicKey))
        {
            keyParameterFromPub = (AsymmetricKeyParameter)new PemReader(txtreader).ReadObject();
        }

        using (var txtreader = new StringReader(_privateKey))
        {
            keyPair = (AsymmetricCipherKeyPair)new PemReader(txtreader).ReadObject();
            keyParameterFromPriv = keyPair.Public;
        }

        Assert.AreEqual(keyParameterFromPub, keyParameterFromPriv); // returns true;

    } 

OP 的代碼中存在一些錯誤。 我做了一些改變。 這是我運行的內容。

public class TFRSAEncryption
{
    public string RsaEncryptWithPublic(string clearText, string publicKey)
    {
        var bytesToEncrypt = Encoding.UTF8.GetBytes(clearText);

        var encryptEngine = new Pkcs1Encoding(new RsaEngine());

        using (var txtreader = new StringReader(publicKey))
        {
            var keyParameter = (AsymmetricKeyParameter)new PemReader(txtreader).ReadObject();

            encryptEngine.Init(true, keyParameter);
        }

        var encrypted = Convert.ToBase64String(encryptEngine.ProcessBlock(bytesToEncrypt, 0, bytesToEncrypt.Length));
        return encrypted;

    }

    public string RsaEncryptWithPrivate(string clearText, string privateKey)
    {
        var bytesToEncrypt = Encoding.UTF8.GetBytes(clearText);

        var encryptEngine = new Pkcs1Encoding(new RsaEngine());

        using (var txtreader = new StringReader(privateKey))
        {
            var keyPair = (AsymmetricCipherKeyPair)new PemReader(txtreader).ReadObject();

            encryptEngine.Init(true, keyPair.Private);
        }

        var encrypted = Convert.ToBase64String(encryptEngine.ProcessBlock(bytesToEncrypt, 0, bytesToEncrypt.Length));
        return encrypted;
    }


    // Decryption:

    public string RsaDecryptWithPrivate(string base64Input, string privateKey)
    {
        var bytesToDecrypt = Convert.FromBase64String(base64Input);

        AsymmetricCipherKeyPair keyPair;
        var decryptEngine = new Pkcs1Encoding(new RsaEngine());

        using (var txtreader = new StringReader(privateKey))
        {
            keyPair = (AsymmetricCipherKeyPair)new PemReader(txtreader).ReadObject();

            decryptEngine.Init(false, keyPair.Private);
        }

        var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(bytesToDecrypt, 0, bytesToDecrypt.Length));
        return decrypted;
    }

    public string RsaDecryptWithPublic(string base64Input, string publicKey)
    {
        var bytesToDecrypt = Convert.FromBase64String(base64Input);

        var decryptEngine = new Pkcs1Encoding(new RsaEngine());

        using (var txtreader = new StringReader(publicKey))
        {
            var keyParameter = (AsymmetricKeyParameter)new PemReader(txtreader).ReadObject();

            decryptEngine.Init(false, keyParameter);
        }

        var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(bytesToDecrypt, 0, bytesToDecrypt.Length));
        return decrypted;
    }
}

class Program
{

    static void Main(string[] args)
    {
        // Set up 
        var input = "Perceived determine departure explained no forfeited";
        var enc = new TFRSAEncryption();
        var publicKey = "-----BEGIN PUBLIC KEY----- // Base64 string omitted // -----END PUBLIC KEY-----";
        var privateKey = "-----BEGIN PRIVATE KEY----- // Base64 string omitted// -----END PRIVATE KEY-----";

        // Encrypt it
        var encryptedWithPublic = enc.RsaEncryptWithPublic(input, publicKey);

        var encryptedWithPrivate = enc.RsaEncryptWithPrivate(input, privateKey);

        // Decrypt
        var output1 = enc.RsaDecryptWithPrivate(encryptedWithPublic, privateKey);

        var output2 = enc.RsaDecryptWithPublic(encryptedWithPrivate, publicKey);

        Console.WriteLine(output1 == output2 && output2 == input);

        Console.Read();
    }
}

我使用了不正確的公鑰……並且證明私鑰和公鑰匹配的測試使用了正確的公鑰。

上面的代碼可以完美運行,只要你把鑰匙弄對了!

我嘗試了@Morio 的解決方案,但遇到了一些例外情況。 第一個是

-----END PUBLIC KEY not found

我可以通過正確格式化兩個鍵來修復

publicKey = $"-----BEGIN PUBLIC KEY-----\n{publicKey}\n-----END PUBLIC KEY-----\n";

第二個錯誤是在嘗試解密文本時。 Unable to cast object of type 'Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters' to type 'Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair'.
我通過轉換為適當的類型來解決。

var keyPair = (RsaPrivateCrtKeyParameters)new PemReader(txtreader).ReadObject();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM