C# 如何将ECDsa私钥转换为AsymmetricKeyParameter类型?

C# 如何将ECDsa私钥转换为AsymmetricKeyParameter类型?,c#,.net,bouncycastle,C#,.net,Bouncycastle,我使用下面的代码将ECDsa转换为AsymmetricKeyParameter私钥类型 X509Certificate2 x509Certificate2 = new X509Certificate2(KeyStore, pin, X509KeyStorageFlags.Exportable); AsymmetricKeyParameter ecdsaprivKey = x509Certificate2.GetECDsaPrivateKey(); // Error 转换ecdsa私钥时出错

我使用下面的代码将ECDsa转换为AsymmetricKeyParameter私钥类型

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

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

转换
ecdsa私钥时出错,如何转换?

您需要手动将ecdsa私钥参数从.NET转换为BouncyCastle。我假设您使用命名曲线,那么证书不太可能具有显式曲线参数。如果是,则只需将私钥D参数+曲线的OID带到BouncyCastle:

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));
        }
    }
}
此代码中缺少几个部分:

首先是
updateExportPolicys()
。我不知道您的私钥是否可导出,但该密钥可能没有允许导出私钥参数的正确导出策略。如果为真,请按照问题中关于如何从PKCS8 blob重新导入私钥和修复导出策略的说明进行操作(您需要在
dotNetPrivateKey.key.ExportPolicy
中设置
AllowPlaintextExport
)。如果你有,跳过这一步

其次是老年痴呆症。您可以使用
dotnetecdsapaparameters.Curve.OID
访问OID,但是它可能没有实际的OID代码,而是一个友好的名称。可以硬编码曲线OID,也可以分析友好名称并将其转换为正确的代码。我已经指定了最常用的曲线nistP256

第三种是Bouncy Castle使用的BER格式,而不是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
}

rsa和ecdsa是完全不同的算法。您无法从rsa密钥获取ecdsa密钥,反之亦然。