解密包含私钥的受密码保护的 PEM
Decrypt passphrase protected PEM containing private key
我有以下使用 Bouncy Castle for C# 创建加密私钥的方法:
public string GetPrivateKey(AsymmetricCipherKeyPair keyPair, string password)
{
var generator = new Pkcs8Generator(keyPair.Private, Pkcs8Generator.PbeSha1_3DES);
generator.IterationCount = 4;
generator.Password = password.ToCharArray();
var pem = generator.Generate();
TextWriter textWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(textWriter);
pemWriter.WriteObject(pem);
pemWriter.Writer.Flush();
string privateKey = textWriter.ToString();
return privateKey;
}
看起来像这样:
-----BEGIN ENCRYPTED PRIVATE KEY-----
...
-----END ENCRYPTED PRIVATE KEY-----
我不知道的是如何在我的 Decrypt 方法中使用用于加密私钥的密码。现在,不知道如何使用他 password
"decrypt" 我的私钥,我得到以下异常:
Org.BouncyCastle.OpenSsl.PemException : problem creating ENCRYPTED
private key: System.NullReferenceException: Object reference not set
to an instance of an object. at
Org.BouncyCastle.OpenSsl.PemReader.ReadPrivateKey(PemObject pemObject)
解密方法的代码如下:
public string Decrypt(string base64Input, string privateKey, string password)
{
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))
{
var obj = new PemReader(txtreader).ReadObject();
keyPair = (AsymmetricCipherKeyPair) obj;
decryptEngine.Init(false, keyPair.Private);
}
var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(bytesToDecrypt, 0, bytesToDecrypt.Length));
return decrypted;
}
在我看来,您需要解密私钥才能使用它。当前未使用您的密码参数。不幸的是,要找出如何做到这一点似乎并不那么容易。
Bouncy Castle 与许多其他 Java API 一样,使用密码处理程序来检索密码。这样做的原因是允许程序仅在需要时才询问用户密码。这允许程序在内存中保留密码的时间最短。
因此要允许解密,请使用以下构造函数:
PemReader(TextReader reader, IPasswordFinder pFinder);
实现 IPasswordFinder
(C# 的 Bouncy Castle 主要是一个 Java 端口,否则可能会使用委托)。
为方便起见,代码。此代码还重建了整个密钥对,而不仅仅是私钥。
导入语句:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using System.IO;
解码器:
private static AsymmetricCipherKeyPair DecodePrivateKey(string encryptedPrivateKey, string password)
{
TextReader textReader = new StringReader(encryptedPrivateKey);
PemReader pemReader = new PemReader(textReader, new PasswordFinder(password));
object privateKeyObject = pemReader.ReadObject();
RsaPrivateCrtKeyParameters rsaPrivatekey = (RsaPrivateCrtKeyParameters)privateKeyObject;
RsaKeyParameters rsaPublicKey = new RsaKeyParameters(false, rsaPrivatekey.Modulus, rsaPrivatekey.PublicExponent);
AsymmetricCipherKeyPair kp = new AsymmetricCipherKeyPair(rsaPublicKey, rsaPrivatekey);
return kp;
}
需要帮手 class:
private class PasswordFinder : IPasswordFinder
{
private string password;
public PasswordFinder(string password)
{
this.password = password;
}
public char[] GetPassword()
{
return password.ToCharArray();
}
}
请注意,通常您只应使用char[]
而不是string
作为密码,因为char[]
可以在使用后清除,而string
不能。
现在有了私钥解密应该很容易了
我有以下使用 Bouncy Castle for C# 创建加密私钥的方法:
public string GetPrivateKey(AsymmetricCipherKeyPair keyPair, string password)
{
var generator = new Pkcs8Generator(keyPair.Private, Pkcs8Generator.PbeSha1_3DES);
generator.IterationCount = 4;
generator.Password = password.ToCharArray();
var pem = generator.Generate();
TextWriter textWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(textWriter);
pemWriter.WriteObject(pem);
pemWriter.Writer.Flush();
string privateKey = textWriter.ToString();
return privateKey;
}
看起来像这样:
-----BEGIN ENCRYPTED PRIVATE KEY-----
...
-----END ENCRYPTED PRIVATE KEY-----
我不知道的是如何在我的 Decrypt 方法中使用用于加密私钥的密码。现在,不知道如何使用他 password
"decrypt" 我的私钥,我得到以下异常:
Org.BouncyCastle.OpenSsl.PemException : problem creating ENCRYPTED private key: System.NullReferenceException: Object reference not set to an instance of an object. at Org.BouncyCastle.OpenSsl.PemReader.ReadPrivateKey(PemObject pemObject)
解密方法的代码如下:
public string Decrypt(string base64Input, string privateKey, string password)
{
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))
{
var obj = new PemReader(txtreader).ReadObject();
keyPair = (AsymmetricCipherKeyPair) obj;
decryptEngine.Init(false, keyPair.Private);
}
var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(bytesToDecrypt, 0, bytesToDecrypt.Length));
return decrypted;
}
在我看来,您需要解密私钥才能使用它。当前未使用您的密码参数。不幸的是,要找出如何做到这一点似乎并不那么容易。
Bouncy Castle 与许多其他 Java API 一样,使用密码处理程序来检索密码。这样做的原因是允许程序仅在需要时才询问用户密码。这允许程序在内存中保留密码的时间最短。
因此要允许解密,请使用以下构造函数:
PemReader(TextReader reader, IPasswordFinder pFinder);
实现 IPasswordFinder
(C# 的 Bouncy Castle 主要是一个 Java 端口,否则可能会使用委托)。
为方便起见,代码。此代码还重建了整个密钥对,而不仅仅是私钥。
导入语句:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using System.IO;
解码器:
private static AsymmetricCipherKeyPair DecodePrivateKey(string encryptedPrivateKey, string password)
{
TextReader textReader = new StringReader(encryptedPrivateKey);
PemReader pemReader = new PemReader(textReader, new PasswordFinder(password));
object privateKeyObject = pemReader.ReadObject();
RsaPrivateCrtKeyParameters rsaPrivatekey = (RsaPrivateCrtKeyParameters)privateKeyObject;
RsaKeyParameters rsaPublicKey = new RsaKeyParameters(false, rsaPrivatekey.Modulus, rsaPrivatekey.PublicExponent);
AsymmetricCipherKeyPair kp = new AsymmetricCipherKeyPair(rsaPublicKey, rsaPrivatekey);
return kp;
}
需要帮手 class:
private class PasswordFinder : IPasswordFinder
{
private string password;
public PasswordFinder(string password)
{
this.password = password;
}
public char[] GetPassword()
{
return password.ToCharArray();
}
}
请注意,通常您只应使用char[]
而不是string
作为密码,因为char[]
可以在使用后清除,而string
不能。
现在有了私钥解密应该很容易了