問題描述
我需要在 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 加密的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!