Расшифровать пароль защищен PEM, содержащий закрытый ключ
У меня есть следующий метод, который создает зашифрованный закрытый ключ с помощью Bouncy Castle для 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-----
Чего я не знаю, так это как использовать пароль, используемый для шифрования закрытого ключа в моем методе расшифровки. Прямо сейчас, не зная, как "расшифровать" мой закрытый ключ с помощью he password
, я получаю следующее исключение:
Орг.После установки BouncyCastle.В OpenSSL.PemException: проблема создания зашифрованного закрытый ключ: Система.NullReferenceException: ссылка на объект не установлена к экземпляру объекта. около Org.После установки BouncyCastle.В OpenSSL.Пемридер.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;
}
1 ответ:
Мне кажется, что вам нужно расшифровать закрытый ключ, чтобы использовать его. В настоящее время Ваш пароль не используется. К сожалению, не так-то просто выяснить, как это сделать.
Bouncy Castle, как и многие другие Java API, использует обработчик паролей для получения пароля. Причина этого заключается в том, чтобы позволить программе запрашивать пароль у пользователя только тогда, когда это необходимо. Это позволяет программе оставлять пароль в памяти на максимально короткий срок. время.
Итак, чтобы разрешить расшифровку, используйте следующий конструктор:
PemReader(TextReader reader, IPasswordFinder pFinder);
С реализацией
IPasswordFinder
(Bouncy Castle для C# - это в основном 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; }
Требуемый вспомогательный класс:
private class PasswordFinder : IPasswordFinder { private string password; public PasswordFinder(string password) { this.password = password; } public char[] GetPassword() { return password.ToCharArray(); } }
Обратите внимание, что обычно вы должны использовать только
char[]
вместоstring
для паролей, так какchar[]
может быть очищен после использования, в то время какstring
не может.Теперь у вас есть секретный ключ, расшифровка должна быть легкой.