C# .NET Framework与.NET Core-将证书添加到RESTful API调用在一种情况下有效,而不是在另一种情况下有效

C# .NET Framework与.NET Core-将证书添加到RESTful API调用在一种情况下有效,而不是在另一种情况下有效,c#,.net,asp.net-core,ssl,client-certificates,C#,.net,Asp.net Core,Ssl,Client Certificates,我有一个通用的RESTful API端点,两个应用程序都在使用它——一个在.NET Core 3.1中,另一个在.NET Framework 4.7.2中。两者都使用类似的代码检索证书(PFX文件),将证书附加到HTTP处理程序,然后使用该处理程序创建HTTP客户端,如图所示: var currentDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); X509Certificate2 cert = nu

我有一个通用的RESTful API端点,两个应用程序都在使用它——一个在.NET Core 3.1中,另一个在.NET Framework 4.7.2中。两者都使用类似的代码检索证书(PFX文件),将证书附加到HTTP处理程序,然后使用该处理程序创建HTTP客户端,如图所示:

var currentDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
X509Certificate2 cert = null;
var password = new AzureKeyVault(_configuration).GetPassword(_secretUri).Result;
try 
{
    cert = new X509Certificate2(currentDirectory + _certName, password);
}
catch (Exception ex)
{
    throw new Exception("Error trying to retrieve certificate named " + currentDirectory + _certName + " - exception was " + ex.Message);
}
      
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(cert);
var client = new HttpClient(handler);
                
var response = await client.SendAsync(request);
     
if (response.IsSuccessStatusCode)
{
    var responseContent = await response.Content.ReadAsStringAsync();                    
    return responseContent;
}
        
throw new ApplicationException($"Status code: {response.StatusCode}, Error: {response.ReasonPhrase}");
NET核心代码工作正常;NET Framework代码不支持。NET Framework遇到一个异常,即无法建立SSL/TLS连接。使用Wireshark,我发现我确实在使用端点所需的TLS1.2。但是,.NET核心调用具有证书,而.NET Framework调用不具有证书

在.NET Framework方面进一步研究这一点,我发现证书上没有私钥。在.NET核心代码中,它是可用的(见下文)

.NET核心(正确)

.NET Framework(不正确)

正在检索的证书来自完全相同的目录,并且两者都在完全相同的计算机上运行。 我还应该提到.NET核心代码本身就是一个RESTful API;NET Framework代码是一个简单的控制台应用程序(因此消除了IIS的所有权限问题)。如果我在调试器的即时窗口“cert.GetRSAPrivateKey()”中调用,我确实会得到一个RSA密钥…因此,上面的屏幕截图可能只是调试器的一个症状

我猜问题在于.NETFramework端缺少私钥。或者这可能与此无关-但最终,证书位于.NET Core的数据包上,而不是来自.NET Framework的数据包上,使用的代码基本上完全相同。我们中的一些人对此感到困惑,因此,如果您对这个问题有任何想法,我们将不胜感激。提前谢谢

编辑#1: 下面是调试器跟踪输出,显示了我认为是.NET Framework得出的结论,即请求中没有可供选择的证书:

System.Net Information: 0 : [14200] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 12ed470:6ee7d30, targetName = xxxx.xxx.com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [14200] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=CredentialsNeeded).
System.Net Information: 0 : [14200] SecureChannel#7894961 - We have user-provided certificates. The server has specified 1 issuer(s). Looking for certificates that match any of the issuers.
System.Net Information: 0 : [14200] SecureChannel#7894961 - Left with 0 client certificates to choose from.
此外,以下是Wireshark条目,显示.NET核心调用上的证书,但不显示.NET Framework调用上的证书:

.NET核心(正确):


证书存储在用户IE设置中。那么,这两个应用程序是否使用相同的用户帐户运行?如果您正在运行服务器,则它的启动是一个没有环境的系统帐户。您可能希望以安装了证书的管理员帐户启动服务。@jdweng-两者都在Visual Studio(标准Visual Studio for.NET Framework;Visual Studio代码for.NET Core)中运行(正在调试)-因此都将在我的用户帐户下运行。我试着以管理员的身份运行VS,但没有任何区别。如果你使用的是同一个用户帐户,为什么一个应用程序能够获得证书存储,而另一个应用程序无法获得存储?在以下位置搜索证书:@motor75,谢谢。Net框架和.Net核心的实现绝对不同步。在我们的例子中,我们通过导出公钥(.cer)的方式找到了解决方案。问题在于服务器提供的将接受客户端身份验证的发行者列表中。最初,当在windows上使用默认的证书管理器导出公钥时(虽然有base64编码的信息),它缺少一些元数据。当与我们的合作伙伴共享这些证书并将其导入apache/spring系统时,服务器不会发送客户端身份验证证书的颁发者。1/2显然。net core忽略了颁发者,但.net framework不这样做-因此它在.net core中工作-即,它将证书附加到请求中,如wireshark中所示,但.net framework并没有做到这一点——它尊重服务器提供的发行人。在调查该问题时,我们意外地使用openssl将.pfx导出/创建到.cer。此.cer文件包含base64编码的信息以及一些元数据。当我们的合作伙伴将它们导入apache/java系统时,服务器开始呈现发行者,然后.net framework很好地处理了这些发行者。那是一次非常糟糕的旅行。2/2
Transport Layer Security
    TLSv1.2 Record Layer: Handshake Protocol: Multiple Handshake Messages
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 4262
        Handshake Protocol: Certificate
            Handshake Type: Certificate (11)
            Length: 3924
            Certificates Length: 3921
            Certificates (3921 bytes)
                Certificate Length: 1957
                Certificate: ... <removed rest for brevity>
Transport Layer Security
    TLSv1.2 Record Layer: Handshake Protocol: Multiple Handshake Messages
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 77
        Handshake Protocol: Certificate
            Handshake Type: Certificate (11)
            Length: 3
            Certificates Length: 0