问题描述
我需要在 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 加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!