Игра с сертификатами в .net5

#bouncycastle #x509certificate2

#баунсикасл #x509сертификат2 #bouncycastle

Вопрос:

Я пытаюсь узнать о сертификатах, необходимость в этом возникла из идеи, которая возникла у меня несколько дней назад, чтобы упростить заказ и доставку SSL-сертификатов моим коллегам. Итак, я начинаю исследовать, «насколько это может быть сложно»?

И к большому энтузиазму, весь процесс был «не таким уж сложным», но затем я перешел к «генерации сертификатов pfx» с закрытым ключом…

Код взят из консольного тестового приложения:

Создание ключей и их хранение.

 int keysize = 2048;
CngKeyCreationParameters ckcParams = new CngKeyCreationParameters()
{
   ExportPolicy = CngExportPolicies.AllowPlaintextExport,
   KeyCreationOptions = CngKeyCreationOptions.None,
   KeyUsage = CngKeyUsages.AllUsages,
};

ckcParams.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(KeySize), CngPropertyOptions.None));

CngKey myCngKey = CngKey.Create(CngAlgorithm.Rsa, KeyName, ckcParams);

byte[] privatePlainTextBlob = myCngKey.Export(CngKeyBlobFormat.Pkcs8PrivateBlob);
string privateblob_string = Convert.ToBase64String(privatePlainTextBlob); 
// Now I can save the Pkcs8PrivateBlob "somewhere"
  

Позже я смогу воспользоваться этим, создать запрос на сертификат и отправить его в службу сертификатов с помощью API.

 byte[] cngbytes = Convert.FromBase64String( privateblob_string );
CngKey importedkey = CngKey.Import(cngbytes, CngKeyBlobFormat.Pkcs8PrivateBlob, CngProvider.MicrosoftSoftwareKeyStorageProvider);
RSACng rsa = new RSACng(importedkey);

request = new CertificateRequest(
   new X500DistinguishedName(order.CertName),
   rsa,
   HashAlgorithmName.SHA512,
   RSASignaturePadding.Pkcs1);

etc....
  

Теперь я могу загрузить выданный сертификат в различных форматах из API.
Пока все идет хорошо. Теперь я хочу создать PFX-файл и ключевой файл.

Создание PFX:

 
// My issued certificate from provider
byte[] PublicKeyStr = System.Text.Encoding.ASCII.GetBytes(CER_STRING);

// pfx
var certificate = new X509Certificate2(PublicKeyStr, string.Empty, X509KeyStorageFlags.Exportable);
byte[] certificateData = certificate.Export(X509ContentType.Pfx, "password");
// Now I have the pfx, but no private key

  

Я, очевидно, не способен решить эту проблему. Я был в путешествии в Надувной замок, но безуспешно (кстати: где их документация?).

Я заметил, что в .net5 есть метод, который, как я думал (опять же), может решить эту проблему.
X509Certificate2.CreateFromPem(сертификат ReadOnlySpan, ключевая строка ReadOnlySpan)
Но тогда мне нужно получить keypem «закрытый ключ pem».

Мой вопрос прост: я совершенно неправильно понял или есть какой-либо способ добавить необходимый закрытый ключ в файл pfx с информацией, которую я сохранил из CngKey?

ЛЮБЫЕ предложения, идеи, помощь, советы будут очень приветствоваться. Это просто так неприятно — быть так близко и просто с треском провалиться.

Ответ №1:

Вам необходимо связать открытый сертификат с закрытым ключом, прежде чем экспортировать его в формате PFX.

 // Key
byte[] cngbytes = Convert.FromBase64String( privateblob_string );
CngKey importedkey = CngKey.Import(cngbytes, CngKeyBlobFormat.Pkcs8PrivateBlob, CngProvider.MicrosoftSoftwareKeyStorageProvider);
RSACng rsa = new RSACng(importedkey);

// Cert
byte[] PublicKeyStr = System.Text.Encoding.ASCII.GetBytes(CER_STRING);
var certificate = new X509Certificate2(PublicKeyStr);

// Together:
X509Certificate2 certWithKey = certificate.CopyWithPrivateKey(rsa);

// PFX:
byte[] pfx = certWithKey.Export(X509ContentType.Pfx, pwd);
  

Комментарии:

1. Фантастика. Я посмотрю на CopyWithPrivateKey. Спасибо.

2. Теперь все это вернулось ко мне. «Система. Безопасность. Криптография. Cng»выдает»Операция не поддерживается». Примечание: Текст «Операция не поддерживается» переведен мной, и я использую .net5.

3. Ах да, у вас есть безымянный ключ, поэтому его нужно экспортировать, но он не подлежит экспорту. Попробуйте RSA.Create() и rsa.ImportPkcs8PrivateKey(cngbytes, out _) , которая является экспортируемой версией.

4. Сэр, вы мне очень помогли. Я ознакомился с вашей предыдущей работой и помощью, которую вы оказали сообществу, и я поражен вашими навыками, терпением и навыками преподавания. Еще раз благодарю вас за вашу помощь.