'X509Certificate2' 不包含 'CopyWithPrivateKey' 的定义

'X509Certificate2' does not contain a definition for 'CopyWithPrivateKey'

正在尝试使用 RSA C# 库,但出现奇怪的错误。我相信所有需要的进口都在那里......

using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;

////

X509Certificate2 keyPair = publicX509.CopyWithPrivateKey(rsa);
    return keyPair;

返回以下错误:

'X509Certificate2' 不包含 'CopyWithPrivateKey' 的定义,并且找不到接受类型 'X509Certificate2' 的第一个参数的可访问扩展方法 'CopyWithPrivateKey'。

我不明白为什么会这样,因为据我所知我有所有必要的导入。另外,当我在一个单独的项目文件中打开它时,它编译得很好,这让我相信我需要它的项目配置有问题。有什么建议吗?

CopyWithPrivateKey(RSA)(扩展)方法最初是在 .NET Core 2.0 中添加的,并在 .NET Framework 4.7.2 中添加,根据 https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.rsacertificateextensions.copywithprivatekey?view=net-5.0#applies-to

不幸的是,.NET Standard 2.0 本质上是 .NET Core 2.1 和 .NET Framework 4.6.1 的交集(根据 https://docs.microsoft.com/en-us/dotnet/standard/net-standard),这意味着 RSACertificateExtensions class如果您的目标是 .NET Standard 2.0,则没有该方法。

有几种不同的解决方法:

  • 如果您不需要 .NET Framework 和 .NET (nee Core),请从 .NET Standard 2.0 切换到特定于框架的目标。

这个不言自明。

  • 如果您要制作 NuGet 包,请针对 .NET Standard 2.0、.NET Framework (4.7.2+) 和 .NET Core 3.1 / .NET 5.0+ 这三个目标

在这种情况下,我会做类似

的事情
internal static X509Certificate2 CopyWithPrivateKey(X509Certificate2 cert, RSA key)
{
#if NETFRAMEWORK || NET_5_0_OR_GREATER
    return cert.CopyWithPrivateKey(key);
#else
    throw new PlatformNotSupportedException("This build does not know how to find CopyWithPrivateKey.");
#endif
}

这是可行的,因为 NuGet 包将继续提供 .NET Standard 2.0 作为库项目的有效目标,但应用程序项目(实际运行的项目)将更喜欢依赖于框架的适当构建而不是 .NET Standard一。所以你的包裹有点大,但一切正常。 (除非有人针对 .NET Framework 4.7.2 之前的版本构建他们的 exe。)

  • 使用反射

当然,这可能会失败,但失败的可能性很小(因为我相信 .NET Framework 4.7.2 或 4.8 通常是通过 Windows 更新推出的)。基本上,支付一次性成本来找出 CopyWithPrivateKey 所在的位置,然后将其作为委托调用:

private static Func<X509Certificate2, RSA, X509Certificate2> s_copyWithRsa = FindCopyWithRsa();

private static Func<X509Certificate2, RSA, X509Certificate2> FindCopyWithRsa()
{
    MethodInfo info = typeof(RSACertificateExtensions).GetMethod("CopyWithPrivateKey");

    if (info == null)
    {
        return (x, k) =>
            throw new PlatformNotSupportedException("The CopyWithPrivateKey method was not found");
    }

    return (Func<X509Certificate2, RSA, X509Certificate2>)info.CreateDelegate(
        typeof(Func<X509Certificate2, RSA, X509Certificate2>));
}        

internal static X509Certificate2 CopyWithPrivateKey(X509Certificate2 cert, RSA key)
{
    return s_copyWithRsa(cert, key);
}

这种方法的主要缺点是它在使用 .NET 5+ 进行提前 (AoT) 编译时会遇到问题,因为它不会看到对 RSACertificateExtensions.CopyWithPrivateKey 的任何调用它'我会删除它。

  • 混搭

如果您希望 AoT 工作,并希望支持针对较旧 .NET Framework 的调用方(但 运行 针对较新的 Framework),则使用 netstandard2.0 和 net5.0 目标进行编译,在netstandard2.0变种和net5.0变种直接编译