Создайте X509Certificate2 из сертификата и ключа, не создавая файл PFX - PullRequest
1 голос
/ 01 апреля 2019

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

Я не использую коммерческие сертификаты SSL, и у меня есть корневой центр сертификации, который я использую для выпуска сертификатов сервера.Эти серверные сертификаты требуют дополнительных шагов при размещении TcpListener в C # (я полагаю, потому что CSR не использовался) ... но что, если у меня есть закрытый ключ и сертификат, который OpenSSL генерирует / использует.

sslCertificate = new X509Certificate2("myExportedCert.pfx", "1234");

Так что это здорово, однако мне нужно выполнить команду openssl, чтобы создать файл pfx из сертификата и закрытого ключа, а затем составить пароль.Затем включите этот пароль в мой код.

Мне было интересно, был ли этот шаг совершенно необходимым.Есть ли способ создать сертификат X509 из сертификата Cert, а затем применить закрытый ключ.Аргументы конструктора допускают только часть Cert, но тогда шифрование завершается неудачно, потому что нет закрытого ключа.

Кроме того, я не хочу полагаться на OpenSSL или IIS для экспорта pfx .... кажется неуклюжим.

В идеале я хотел бы:

sslCertificate = new X509Certificate2("myCert.crt");
sslCertificate.ApplyPrivateKey(keyBytes) // <= or "private.key" or whatever

sslStream.AuthenticateAsServer(sslCertificate, false, SslProtocols.Default, false);

Ответы [ 2 ]

1 голос
/ 01 апреля 2019

Есть несколько разных вещей, о которых вы просите, с разными уровнями легкости.

Прикрепление закрытого ключа к сертификату

Начиная с .NET Framework 4.7.2 илиВ .NET Core 2.0 вы можете комбинировать сертификат и ключ.Он не изменяет объект сертификата, а создает новый объект сертификата, который знает о ключе.

using (X509Certificate2 pubOnly = new X509Certificate2("myCert.crt"))
using (X509Certificate2 pubPrivEphemeral = pubOnly.CopyWithPrivateKey(privateKey))
{
    // Export as PFX and re-import if you want "normal PFX private key lifetime"
    // (this step is currently required for SslStream, but not for most other things
    // using certificates)
    return new X509Certificate2(pubPrivEphemeral.Export(X509ContentType.Pfx));
}

в .NET Framework (но не в .NET Core), если ваш закрытый ключ равен RSACryptoServiceProviderили DSACryptoServiceProvider вы можете использовать cert.PrivateKey = key, но это имеет сложные побочные эффекты и не рекомендуется.

Загрузка секретного ключа

Этот сложнее, если вы его уже не решили.

В большинстве случаев ответом на этот вопрос является Цифровая подпись в c # без использования BouncyCastle , но если вы сможете перейти на .NET Core 3.0, все станет намного проще.

PKCS # 8 PrivateKeyInfo

Начиная с .NET Core 3.0 вы можете сделать это относительно просто:

using (RSA rsa = RSA.Create())
{
    rsa.ImportPkcs8PrivateKey(binaryEncoding, out _);
    // do stuff with the key now
}

(конечно, если у вас был PEM, вам нужноPEM ", извлекая содержимое между разделителями BEGIN и END и пропуская его через Convert.FromBase64String, чтобы получить binaryEncoding).

PKCS # 8 EncryptedPrivateKeyInfo

Начиная с .NETCore 3.0 вы можете сделать это относительно просто:

using (RSA rsa = RSA.Create())
{
    rsa.ImportEncryptedPkcs8PrivateKey(password, binaryEncoding, out _);
    // do stuff with the key now
}

(какbove, вам нужно сначала «де-PEM», если это был PEM).

PKCS # 1 RSAPrivateKey

Начиная с .NET Core 3.0 вы можете сделать это относительно просто:

using (RSA rsa = RSA.Create())
{
    rsa.ImportRSAPrivateKey(binaryEncoding, out _);
    // do stuff with the key now
}

(то же самое "de-PEM", если PEM).

0 голосов
/ 02 апреля 2019

В конце концов я сделал это, и все работает отлично:

...
if (!File.Exists(pfx)) {
    // Generate PFX
    string arguments = "openssl pkcs12 -export -in " + certPath + "" + certFile + ".crt -inkey " + certPath + "" + certFile + ".key -out " + certPath + "" + certFile + ".pfx -passout pass:" + pfxPassword;
    ProcessStartInfo opensslPsi = new ProcessStartInfo("sudo", arguments);
    opensslPsi.UseShellExecute = false;
    opensslPsi.RedirectStandardOutput = true;
    using (Process p = Process.Start(opensslPsi)) {
        p.WaitForExit();
    }
    // Set Permission
    ProcessStartInfo chmodPsi = new ProcessStartInfo("sudo", "chmod 644 " + certPath + "" + certFile + ".pfx");
    chmodPsi.UseShellExecute = false;
    chmodPsi.RedirectStandardOutput = true;
    using (Process p = Process.Start(chmodPsi)) {
        p.WaitForExit();
    }
}
sslCertificate = new X509Certificate2(pfx, pfxPassword);
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...