Как преобразовать закрытый ключ ECDsa в тип AsymmetricKeyParameter? - PullRequest
0 голосов
/ 10 июля 2020

Я использую приведенный ниже код для преобразования ECDsa в AsymmetricKeyParameter тип закрытого ключа.

X509Certificate2 x509Certificate2 = new X509Certificate2(KeyStore, pin, X509KeyStorageFlags.Exportable);

AsymmetricKeyParameter ecdsaprivKey =  x509Certificate2.GetECDsaPrivateKey(); // Error

Я получил ошибку при преобразовании ecdsa private key, как могу я это преобразовать?

1 Ответ

0 голосов
/ 13 июля 2020

Вам необходимо вручную преобразовать параметры закрытого ключа ECDsa из. NET в BouncyCastle. Я полагаю, что вы используете именованные кривые, маловероятно, что в сертификате есть явные параметры кривой. Если да, то единственное, что вам нужно передать в BouncyCastle, - это параметр D закрытого ключа + OID кривой:

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace EcConverter
{
    class Program
    {
        static void Main(string[] args)
        {
            var dotNetCertificate = new X509Certificate2("mycert.pfx", "mypassword", X509KeyStorageFlags.Exportable);
            var dotNetPrivateKey = (ECDsaCng)dotNetCertificate.GetECDsaPrivateKey();
            var dotNetPrivateKeyExportable = UpdateExportPolicies(dotNetPrivateKey);
            var dotNetECDsaParameters = dotNetPrivateKeyExportable.ExportParameters(true);
            var oid = "1.2.840.10045.3.1.7"; // nistP256Oid
            var bouncyCastleD = new BigInteger(dotNetECDsaParameters.D);
            var bouncyCastlePrivateKey = new ECPrivateKeyParameters("ECDSA", bouncyCastleD, new DerObjectIdentifier(oid));
        }
    }
}

В этом коде есть несколько недостающих частей:

Сначала UpdateExportPolicies(). Я не знаю, есть ли у вас экспортный закрытый ключ или нет, но возможно, что ключ может не иметь правильных политик экспорта, которые позволили бы ему экспортировать параметры закрытого ключа. Если это правда, то следуйте инструкциям из этого вопроса о том, как повторно импортировать закрытый ключ из большого двоичного объекта PKCS8 и исправить политики экспорта (вам необходимо иметь AllowPlaintextExport в dotNetPrivateKey.Key.ExportPolicy). Если он у вас есть, просто пропустите этот шаг.

Второй - OID. Вы можете получить доступ к OID с помощью dotNetECDsaParameters.Curve.Oid, однако он может не иметь фактического кода OID, а иметь понятное имя. Вы можете либо жестко закодировать OID кривой, либо проанализировать понятное имя и преобразовать его в правильный код. Я указал наиболее часто используемую кривую nistP256.

Третий - это формат BER, который Bouncy Castle использует вместо DER для хранения параметра D. В большинстве случаев код будет работать, но могут возникнуть проблемы, если массив байтов закрытого ключа короче, чем ожидалось, и его необходимо усечь. Кодирование BER требует минимального количества используемых байтов и вставки 0 байта впереди. Таким образом, реальный код будет выглядеть примерно так:

var bouncyCastleD = new BigInteger(ConvertToBer(dotNetECDsaParameters.D));
...
private byte[] ConvertToBer(byte[] derByteArray)
{
    // trim all zeroes in the beginning of a given array
    // add one zero in front
    // return the result
}
...