X509Certificate2错误 - 系统找不到指定的文件。

12

相关代码在独立控制台应用程序中运行良好,但在尝试使其在NSB架构中工作时出现错误。我已经尝试在工作器中以及在测试控制台应用程序中单独测试相同的代码。无论哪种情况,在以下行中都会出错- X509Certificate2 certificate = new X509Certificate2(filePath, "***key***UeUHFxS"); 异常信息为 - System.Security.Cryptography.CryptographicException:“系统找不到指定的文件”。 该代码包括上述代码和一个用于激活设备的辅助文件。然而,异常发生在从pfx文件路径和密钥初始化X509Certificate2的部分。

class Program
{
    static void Main(string[] args)
    {
        try
        {
            string filePath = Path.GetDirectoryName(System.AppDomain.CurrentDomain.BaseDirectory);
            filePath = Directory.GetParent(Directory.GetParent(filePath).FullName).FullName;
            filePath = Path.Combine(filePath, @"Cert\TestCompany-qa.partner.client.siriusxm.com.pfx");

            X509Certificate2 certificate = new X509Certificate2(filePath, "****key****");
            SoapMessageHelper soapHelper = new SoapMessageHelper(certificate, @"https://api-ext-test.siriusxm.com/SAT/UpdateDeviceSatRefresh/v_1");
            var test = soapHelper.ActivateDevice(new ActivateDeviceRequest()
            {
                SourceName = "12493",
                ESN = "W26890HW",
                TimeStamp = DateTime.UtcNow,
                TrasanctionId = System.Guid.NewGuid().ToString()
            });

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(test);

            foreach (XmlNode node in doc.DocumentElement.ChildNodes)
            {
                foreach (XmlNode locNode in node)
                {
                    if (locNode.Name == "ns0:responseRefreshDevice")
                    {
                        string resultCode = locNode["ns0:resultCode"].InnerText;
                        string errorCode = locNode["ns0:errorCode"].InnerText;
                        string errorMessage = locNode["ns0:errorMessage"].InnerText;
                        Console.WriteLine(resultCode + errorCode + errorMessage);
                    }
                }
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine(
                String.Format("Exception occurred{0}Message:{1}{2}Inner Exception: {3}", Environment.NewLine, ex.Message, Environment.NewLine, ex.InnerException));
        }

    }

}

@popsiporkkanaa - 是的,我已经尝试过调试并且filePath包含证书PFX文件。此外,附上用于调试的示例代码 - Console.WriteLine(File.Exists(filePath) ? "文件存在。" : "文件不存在。"); - Rakesh Kumar
你能否在这里粘贴完整的 CryptographicException 消息和其堆栈跟踪?堆栈跟踪中可能有一些有用的信息来查找根本原因。 - popsiporkkanaa
"File exists." : "文件不存在。"-- 这是你的问题。异常被抛出,因为代码找不到证书文件。 - Crypt32
System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) 在 System.Security.Cryptography.X509Certificates.X509Utils._QueryCertFileType(String fileName) 中 在 System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromFile(String fileName, Object password, X509KeyStorageFlags keyStorageFlags) 中 在 System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName, String password) 中 在 TestApp.Program.Main:line 34 中 - Rakesh Kumar
1
@RakeshKumar 可能与您当前的用户配置文件加载有关。让我们在这里尝试这个解决方案:https://dev59.com/bWMm5IYBdhLWcg3wIsU2#27242467 - popsiporkkanaa
显示剩余4条评论
4个回答

32

让我们试着修改你的构造函数为:

X509Certificate2 certificate = new X509Certificate2(filePath, key, 
                               X509KeyStorageFlags.MachineKeySet
                             | X509KeyStorageFlags.PersistKeySet
                             | X509KeyStorageFlags.Exportable);

根据MSDN的说法,使用MachineKeySet会将私钥存储在本地计算机存储区而不是当前用户存储区中。


1
相同的异常也会出现在字节数组上。目前的代码如下 -byte [] bytes = System.IO.File.ReadAllBytes(filePath);X509Certificate2 证书 = new X509Certificate2(bytes,“**** key ****”,X509KeyStorageFlags.MachineKeySet      | X509KeyStorageFlags.PersistKeySet      | X509KeyStorageFlags.Exportable); - Rakesh Kumar
3
添加 MachineKeySet 解决了我的问题:X509Certificate2(filePath, key, X509KeyStorageFlags.MachineKeySet)。 - w00ngy
5
感谢 @popsiporkkanaa 添加 X509KeyStorageFlags.MachineKeySet,解决了我在部署到 Azure Web 应用程序时遇到的问题。在本地运行时,不设置该值也可以正常工作。 - Nishank
MachineKey 也解决了我的问题。错误信息非常令人困惑。 - Kishan Vaishnav
我在这个更改后仍然有错误 :( - Neel
显示剩余3条评论

4
请查看此处的更多细节:https://github.com/dotnet/runtime/issues/25143

证书确实存在,并且可以被运行用户读取 - 所以找不到证书不是问题!

实际错误是,我认为它无法将证书放入LocalUser的证书存储中。

以下是对我有用的内容:

var issuerCertificate  = new X509Certificate2(caFileName, caPassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);

3
提供绝对路径而不是相对路径确实有帮助。提供相对路径的目的是将证书作为构件的一部分包含进来,当应用程序部署到服务器时,证书将被写入输出路径并从该位置读取。 然而,在尝试测试工作代码时,我发现只有绝对路径可行,尽管证书属性设置始终复制。现在,可用的代码看起来像这样:
filePath = @"C:\Users\<user name>\Documents\TestCompany-qa.partner.client.siriusxm.com.pfx"; 

X509Certificate2 certificate = new X509Certificate2(filePath, "****key****"); 

因此,现在需要知道应用程序部署在服务器上的路径和证书位置,以便继续进行,作为解决方案的权宜之计。


1

对于所有遇到这个问题的人,不管你是否已经切换了IIS并尝试了所有的keyFlags!

我在我的本地机器上遇到了这个问题。一直找不到解决方法。所以我在X509调用之前插入了Directory.GetFiles(certs folder)来检查文件路径是否正确。然后new X509Certification2()就可以正常工作了。

certs文件夹位于项目范围之外,在我的本地项目中从未访问过。证书存储必须使用一个影子文件夹结构,你必须通过简单地读取文件来注册它。

希望这可以帮助某些人在这个问题上不要浪费半天时间。


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