在C#中,从ECC X509Certificate创建X509Certificate2会抛出'System.NotSupportedException'异常。

5

我需要在C#中将ECC证书导入到Windows密钥库中。作为第一步,我使用BouncyCastle生成一个EC密钥对,使用公钥创建一个X509证书,并使用ECDSA和私钥对其进行签名,即:

            var ecKeyPairGenerator = new ECKeyPairGenerator("ECDSA");
            ECKeyGenerationParameters ecKeyGenParams =
                new ECKeyGenerationParameters(SecObjectIdentifiers.SecP384r1, new SecureRandom());
            ecKeyPairGenerator.Init(ecKeyGenParams);
            AsymmetricCipherKeyPair pair = ecKeyPairGenerator.GenerateKeyPair();
            PrivateKeyInfo privKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(pair.Private);
            SubjectPublicKeyInfo pubKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pair.Public);

            X509V3CertificateGenerator bcX509Gen = new X509V3CertificateGenerator();
// set cert fields
...
            bcX509Gen.SetPublicKey(pair.Public);
            Asn1SignatureFactory bcSigFactory =
                    new Asn1SignatureFactory(X9ObjectIdentifiers.ECDsaWithSha384.Id, pair.Private);
            X509Certificate bcCert = bcX509Gen.Generate(bcSigFactory);

然后,我使用上面创建的证书创建了一个X509Certificate2,即:

    SystemX509.X509Certificate2 msCert2 = 
        new SystemX509.X509Certificate2(bcCert.GetEncoded(), (string)null);

然而,在创建X509Certificate2时会引发异常:

'msCert2.PublicKey.Key' threw an exception of type 'System.NotSupportedException'
"The certificate key algorithm is not supported."

使用BC的DotNetUtilities.ToX509Certificate()会导致相同的异常。

我知道Windows / .NET上对ECC证书的支持可能不完整,但我在网上搜索似乎表明这应该是可能的?你有什么想法我做错了什么吗?

顺便说一下,我正在使用VS Community 2017,我的项目目标是.NET Framework 4.6.2。

谢谢!

1个回答

6

PublicKey.Key非官方弃用(以及PrivateKey)。它不支持ECC,并且不能生成支持OAEP-SHA-2加密的RSA密钥或支持FIPS 186-3 DSA的DSA密钥。

相反,您应该使用不需要转换的扩展方法:

// GetECDsaPublicKey returns a unique object every call,
// so you're responsible for Disposing it (lest it end up on the Finalizer queue)
using (ECDsa ecdsa = msCert2.GetECDsaPublicKey())
{
    // do stuff with the public key object
}

最终,我想创建PKCS12并将其导入密钥库,类似于https://dev59.com/5Jbfa4cB1Zd3GeqPoRJb中的目标,您在那里也提供了非常有用的答案。目前,我发现'GetECDsaPublicKey()扩展方法在'msCert2'上不可用,尽管我导入了`System.Security.Cryptography.X509Certificates`命名空间,即: using SystemX509 = System.Security.Cryptography.X509Certificates; 作为VS/.Net新手,我一定做错了什么?谢谢! - hyongsop
@hyongsop 扩展方法是在4.6.1中添加的。如果您在编译时出现错误,请检查您是否实际引用了4.6.2,而不仅仅是安装了它(VS似乎喜欢针对旧的框架版本)。 - bartonjs
该项目的目标框架为“.NET Framework 4.6.2”,并引用了位于C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.6.2\System.Security.dll的System.Security.dll。我是否遗漏了VS全局配置? - hyongsop
问题出在using指令中使用了别名,即using SystemX509 = System.Security.Cryptography.X509Certificates。如果不使用别名,VS就能找到该方法。回到最初的目标,根据您对上述问题的回答,P/Invoking是否仍然是将私钥与msCert2关联的唯一方法?谢谢。 - hyongsop
由于我的身份,我无法在那里添加评论。谢谢你的帮助! - hyongsop
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接