.NET Standard - программно объединить сертификат и закрытый ключ в файл.pfx
Есть ли способ объединить сертификат и ключ (оба получены отдельно как строки Base64 от службы) в файл.pfx, используя C#/.NET Standard программно? Использование инструмента не вариант, так как мне нужно его автоматизировать.
Контекст: мне нужно загрузить сертификат и закрытый ключ (отдельные строки Base64 без верхних и нижних колонтитулов) в X509Certificate2
объект для передачи его в приложение из библиотеки.NET Standard 1.6. Проблема в том, что нет PrivateKey
недвижимость в X509Certificate2
класс в.NET Standard! Таким образом, единственный способ для меня на самом деле загрузить закрытый ключ в X509Certificate2
Цель состоит в том, чтобы объединить его с самим сертификатом в файле.pfx и загрузить его в конструктор.
2 ответа
Нет способа сделать это с типами фреймворка. Это может быть возможно с BouncyCastle или другими библиотеками.
В.NET Core 2.0 добавлена возможность объединения сертификата и объекта ключа вместе (в новый объект X509Certificate2) с помощью методов расширения:
X509Certificate2 mergedCert = cert.CopyWithPrivateKey(rsaPrivateKey);
X509Certificate2 mergedCert = cert.CopyWithPrivateKey(dsaPrivateKey);
X509Certificate2 mergedCert = cert.CopyWithPrivateKey(ecdsaPrivateKey);
Но это требует компиляции специально для netcoreapp20 (не netstandard20).
Типы каркаса также не имеют возможности загрузки ключевых объектов из двоичных представлений (за исключением CngKey.Import
, но это работает только в Windows), только из предварительно проанализированных структур (RSAParameters
, DSAParameters
, ECParameters
).
Самый простой способ достичь этой цели в Linux (если BouncyCastle не может вам помочь) - это использовать System.Process
создать вызов, похожий на openssl pkcs12 -export -out tmp.pfx -in tmp.cer -inkey tmp.key -password pass:""
,
В Windows вы можете использовать CngKey.Import и P / Invoke CertSetCertificateContextProperty (для CERT_NCRYPT_KEY_HANDLE_PROP_ID (78)), чтобы затем вызвать cert.Export
на мутантном сертификате.
Для .NET Core 3.1 (отсутствуют методы PEM) я использовал эту логику:
var privateKeyLines = File.ReadAllText(keyPath)
.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)
.Where(x => !(x.StartsWith("--") && x.EndsWith("--")));
var privateKey = string.Join("", privateKeyLines);
var privateKeyBytes = Convert.FromBase64String(privateKey);
using (var rsa = RSA.Create())
{
rsa.ImportRSAPrivateKey(privateKeyBytes, out _);
using (X509Certificate2 publicCertificate = new X509Certificate2(certPath))
using (X509Certificate2 publicAndPrivateCombinedCertificate = publicCertificate.CopyWithPrivateKey(rsa))
{
return publicAndPrivateCombinedCertificate.Export(X509ContentType.Pfx);
}
}
Он возвращает byte[], который вы можете использовать в конструкторе X509Certificate2.