C# BouncyCastle - 使用公钥/私钥的 RSA 加密

C# BouncyCastle - RSA Encryption with Public/Private keys(C# BouncyCastle - 使用公钥/私钥的 RSA 加密)
本文介绍了C# BouncyCastle - 使用公钥/私钥的 RSA 加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我需要在 C# 中加密数据才能将其传递给 Java.Java 代码属于第 3 方,但我已获得相关来源,因此我决定由于 Java 使用 Bouncy Castle 库,我将使用 C# 端口.

I need to encrypt data in C# in order to pass it to Java. The Java code belongs to a 3rd party but I have been given the relevant source, so I decided that as the Java uses the Bouncy Castle libs, I will use the C# port.

解密工作正常.但是,只有当我使用私钥而不是公钥进行加密时,解密才有效.使用公钥时,解密失败,unknown block type.

Decryption works fine. However, decryption works only when I use the encrypt using the private key, and not with the public key. When using the public key, decryption fails with unknown block type.

显然 RsaEncryptWithPrivate 内部的加密在加密时使用公钥,所以我不明白为什么两种加密方法在功能上不一样:

Obviously the encryption inside the RsaEncryptWithPrivate uses the public key when encrypting, so I do not get why the two encryption methods are not functionally identical:

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 解密也出现了同样的问题 - 仅使用公钥加密时,它会失败.

Incidentally the Java decryption exhibits the same issue - when encrypted with the public key only, it fails.

我对密码学很陌生,所以我确定我在 RsaEncryptWithPublic 方法中做了一些非常简单的错误.

I'm very new to cryptography, so I'm sure I'm doing something very simple wrong in the RsaEncryptWithPublic method.

我还添加了一个单元测试,证明公钥等于从私钥中提取的公钥:

I've also added a unit test which proves that the public key is equal to the public key that is extracted from the private key:

    [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;

    } 

推荐答案

我使用了不正确的公钥.. 并且证明私钥和公钥匹配的测试使用了正确的公钥.

I was using an incorrect Public Key.. and the test that proved the Private and Public keys matched was using the correct Public Key.

只要你把钥匙弄对了,上面的代码就可以完美地工作!

The above code works perfectly as is, as long as you get the keys right!

这篇关于C# BouncyCastle - 使用公钥/私钥的 RSA 加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

Custom Error Queue Name when using EasyNetQ for RabbitMQ?(使用 EasyNetQ for RabbitMQ 时自定义错误队列名称?)
How to generate password_hash for RabbitMQ Management HTTP API(如何为 RabbitMQ 管理 HTTP API 生成密码哈希)
Rabbitmq Ack or Nack, leaving messages on the queue(Rabbitmq Ack 或 Nack,将消息留在队列中)
Setup RabbitMQ consumer in ASP.NET Core application(在 ASP.NET Core 应用程序中设置 RabbitMQ 消费者)
Specify Publish timeouts in mass transit(指定公共交通中的发布超时)
RabbitMQ asynchronous support(RabbitMQ 异步支持)