Создание сертификата ECDSA, подписанного другим сертификатом ECDSA - PullRequest
0 голосов
/ 02 июня 2018

Мне необходимо создать сертификат ECDSA «Клиент», подписанный сертификатом «Root» (самоподписанный, ECDSA).«Корневой» сертификат был создан, как описано в Преобразование параметров эллиптической кривой (от BC к MS) .

Для создания «Клиентского» сертификата (подписанного «Root») можно использовать слегка измененный алгоритм.,Разница заключается в том, что закрытый ключ (используемый для подписи открытого ключа из пары ключей, сгенерированный для сертификата «Клиент») должен предоставляться «извне» - это закрытый ключ сертификата «Корень».Но это проблема.Я не могу найти способ, как получить и перевести закрытый ключ к типу Org.BouncyCastle.Crypto.Parameters.ECPrivateKeyParameters, который можно было бы передать фабрике подписи.

// 1. get private-key of "Root" certificate from existing certificate:
byte[] msRootCertData = File.ReadAllBytes(@"c:\root_ecdsa_cert.pfx");
X509Certificate2 msRootCert = new X509Certificate2(msRootCertData);
ECDsaCng msRootPrivateKey = msRootCert.GetECDsaPrivateKey() as ECDsaCng;
ECParameters msRootPrivateKeyParameters = msRootPrivateKey.ExportParameters(true);

// here comes the issue:
ECPrivateKeyParameters bcRootPrivateKeysParameters = TranslateMSKeysToBouncy(msRootPrivateKeyParameters);

// 2. generate "Client" key-pair:
AsymmetricCipherKeyPair bcClientKeyPair = bcKeyGen.GenerateKeyPair();
ECPrivateKeyParameters bcClientPrivKey = (ECPrivateKeyParameters)bcClientKeyPair.Private;
ECPrivateKeyParameters bcClientPublKey = (ECPublicKeyParameters)bcClientKeyPair.Public;

// 3. create X509 certificate:
X509V3CertificateGenerator bcCertGen = new X509V3CertificateGenerator();
bcCertGen.SetPublicKey(bcClientPublKey);
// .. set subject, validity period etc
ISignatureFactory sigFac = new Asn1SignatureFactory("Sha256WithECDSA", bcRootPrivateKeysParameters);
Org.BouncyCastle.X509.X509Certificate bcClientX509Cert = bcCertGen.Generate(sigFac);
byte[] x509CertEncoded = bcClientX509Cert.GetEncoded();

// остальное такое же, как в упомянутом примере.

Есть намеки?Или есть другой способ?(например: передача экземпляра X509Certificate2 непосредственно в библиотеку BouncyCastle (не переводить закрытые ключи в Cng) или создание сертификата «Клиент» без BouncyCastle) Спасибо.

1 Ответ

0 голосов
/ 02 июня 2018

Если вы можете получить зависимость от .NET Framework 4.7.2 (или .NET Core 2.0), вы можете сделать это без BouncyCastle, через новый CertificateRequest класс:

X509Certificate2 publicPrivate;

using (ECDsa clientPrivateKey = ECDsa.Create())
{
    var request = new CertificateRequest(
        "CN=Et. Cetera",
        clientPrivateKey,
        HashAlgorithmName.SHA256);

    // Assuming this isn't another CA cert:
    request.CertificateExtensions.Add(
        new X509BasicConstraintsExtension(false, false, 0, false));

    // other CertificateExtensions as you desire.

    // Assign, or derive, a serial number.
    // RFC 3280 recommends that it have no more than 20 bytes encoded.
    // 12 random bytes seems long enough.
    byte[] serial = new byte[12];

    using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
    {
        rng.GetBytes(serial);
    }

    DateTimeOffset notBefore = DateTimeOffset.UtcNow;
    DateTimeOffset notAfter = notBefore.AddMonths(15);

    using (X509Certificate2 publicOnly = request.Create(
        msRootCert,
        notBefore,
        notAfter,
        serial))
    {
        publicPrivate = publicOnly.CopyWithPrivateKey(clientPrivateKey);
    }
}

// The original key object was disposed,
// but publicPrivate.GetECDsaPrivateKey() still works.

Если вы хотите добавить publicPrivate в X509Store, вам нужно либо 1) экспортировать его в PFX и повторно импортировать его, либо 2) изменить создание ключа на использование именованного ключа.В противном случае будет сохранена только общедоступная часть (в Windows).

...