метод вместо просто

аюсь создать самозаверяющий сертификат ECDSA, как описано вгенерировать сертификат с использованием ECDSA, Собираем все кусочки из ответа bartonjs вместе и используемNet.Framework 4.7 (или жеNet.Core 2.0) следующий код, кажется, работает, хотя есть некоторые неясности (по крайней мере, одна) осталось:

Я не уверен, как правильно преобразовать закрытый ключ (параметр 'D') изBC-BigInteger вMS-byte[], С помощьюBigInteger.ToByteArray() выдает исключение:

CryptographicException: Указанные ключевые параметры недействительны. Q.X и Q.Y - обязательные поля. Q.X, Q.Y должны быть одинаковой длины. Если указан D, он должен иметь ту же длину, что и Q.X и Q.Y для именованных кривых, или ту же длину, что и Order для явных кривых.

при проверке ECParameters (методECParameters.Validate()). С помощьюBigInteger.ToByteArrayUnsigned() обеспечивает намного лучшие результаты (один сбой на нескольких сотнях сгенерированных пар ключей), но все же ...

Когда используешьToByteArray() преобразованный «D» обычно на один байт длиннее («D» имеет 33 байта против D.X и D.Y имеет 32 байта). С помощьюToByteArrayUnsigned() буква D иногда на один байт короче.

Так что мой вопрос в том, можно ли использоватьToByteArrayUnsigned().

private const string NCryptExportPolicyProperty = "Export Policy";
private const string SignatureAlgorithm = "Sha256WithECDSA";
private static readonly ECCurve MsCurve = ECCurve.NamedCurves.nistP256;
private static readonly DerObjectIdentifier BcCurve = SecObjectIdentifiers.SecP256r1; // must correspond with MsCurve

public static X509Certificate2 Create()
{    
    // 1. generate keys:
    IAsymmetricCipherKeyPairGenerator bcKeyGen = GeneratorUtilities.GetKeyPairGenerator("ECDSA");
    bcKeyGen.Init(new ECKeyGenerationParameters(BcCurve, new SecureRandom()));

    ECPrivateKeyParameters bcPrivKey;
    ECPublicKeyParameters bcPublKey;

    bool validated;
    ECParameters msEcp;
    do
    {
        AsymmetricCipherKeyPair bcKeyPair = bcKeyGen.GenerateKeyPair();
        bcPrivKey = (ECPrivateKeyParameters)bcKeyPair.Private;
        bcPublKey = (ECPublicKeyParameters)bcKeyPair.Public;

        // 2. ensure generated bc-keys can be translated to cng (see exception below)
        msEcp = new ECParameters();
        msEcp.Curve = MsCurve;
        msEcp.D = bcPrivKey.D.ToByteArrayUnsigned(); // or bcPrivKey.D.ToByteArray() ??
        msEcp.Q.X = bcPublKey.Q.XCoord.GetEncoded();
        msEcp.Q.Y = bcPublKey.Q.YCoord.GetEncoded();

        try
        {
            msEcp.Validate();
            validated = true;
        }
        catch (Exception e)
        {
            // Validate() occasionally throws CryptographicException: 
            // The specified key parameters are not valid. Q.X and Q.Y are required fields. Q.X, Q.Y must be the same length. If D is specified it must be the same length as Q.X and Q.Y for named curves or the same length as Order for explicit curves.
            // e.g.: D = 31, Q.X = 32, Q.Y = 32.
            validated = false;
            Console.WriteLine("D = {0}, Q.X = {1}, Q.Y = {2}. {3}: {4}", msEcp.D.Length, msEcp.Q.X.Length, msEcp.Q.Y.Length, e.GetType().Name, e.Message);
        }
    } while (!validated);

    // 3. create x509 certificate:
    X509V3CertificateGenerator bcCertGen = new X509V3CertificateGenerator();
    bcCertGen.SetPublicKey(bcPublKey);
    // .. set subject, validity period etc
    ISignatureFactory sigFac = new Asn1SignatureFactory(SignatureAlgorithm, bcPrivKey);
    Org.BouncyCastle.X509.X509Certificate bcX509Cert = bcCertGen.Generate(sigFac);
    byte[] x509CertEncoded = bcX509Cert.GetEncoded();

    X509Certificate2 msNewCert;

    // 4. use translated (and validated) parameters:
    using (ECDsaCng msEcdsa = new ECDsaCng())
    {
        msEcdsa.ImportParameters(msEcp);

        CngKey msPrivateKey = msEcdsa.Key;

        // 5. make private key exportable:
        byte[] bytes = BitConverter.GetBytes((int)(CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport));
        CngProperty pty = new CngProperty(NCryptExportPolicyProperty, bytes, CngPropertyOptions.Persist);
        msPrivateKey.SetProperty(pty);

        // 6. tie keys together:
        using (X509Certificate2 msPubCertOnly = new X509Certificate2(x509CertEncoded))
        {
            msNewCert = MateECDsaPrivateKey(msPubCertOnly, msPrivateKey); // method from bartonjs's answer
        }
    }

    return msNewCert;
}

заранее спасибо

Ответы на вопрос(1)

Ваш ответ на вопрос