.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.

Другие вопросы по тегам