简体   繁体   English

加载 X509Certificate2 以 Windows 服务器 2012 发生内部错误结束

[英]Loading X509Certificate2 ends with An internal error occurred on Windows server 2012

I`m trying to load certificate from path and getting internal server error on windows server.我正在尝试从路径加载证书并在 windows 服务器上出现内部服务器错误。 While I do it on windows 10 everything works fine.当我在 windows 10 上执行此操作时,一切正常。

Not working console application Code控制台应用程序代码不工作

var path = args[0];
var password = args[1];
var certificate2 = new X509Certificate2(path, password);

But getting error但是出现错误

Unhandled exception. Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: An internal error occurred.
   at Internal.Cryptography.Pal.CertificatePal.FilterPFXStore(Byte[] rawData, SafePasswordHandle password, PfxCertStoreFlags pfxCertStoreFlags)
   at Internal.Cryptography.Pal.CertificatePal.FromBlobOrFile(Byte[] rawData, String fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(String fileName, String password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName, String password)
   at CertCoreTest.Program.Main(String[] args) in C:\Users\Admin\Documents\Visual Studio 2019\Projects\CertTest\CertCoreTest\Program.cs:line 12

Hack working code (not sure why it works)破解工作代码(不确定它为什么有效)

var path = args[0];
var password = args[1];

Chilkat.Cert cert = new Chilkat.Cert();
var success = cert.LoadPfxData(File.ReadAllBytes(path), password);
if (success == false)
{
    throw new Exception(cert.LastErrorText);
}

var bytes = cert.ExportToPfxData(password, true);
var ceeert = new X509Certificate2(bytes, password);

How to make it work on windows server without using chilkat library?如何在不使用 chilkat 库的情况下使其在 windows 服务器上运行?

If your code is running in a web application under IIS:如果您的代码在 IIS 下的 Web 应用程序中运行:

  1. Go to IIS Manager进入 IIS 管理器
  2. Go to the application pool instance转到应用程序池实例
  3. Click advanced settings点击高级设置
  4. Under Process model, set Load User Profile to true在流程模型下,将加载用户配置文件设置为 true

Else, try specifying the UserKeySet (it's possible that the PFX contains the "use the machine store" marker internally):否则,尝试指定 UserKeySet(PFX 可能在内部包含“使用机器存储”标记):

var path = args[0]; var path = args[0]; var password = args[1]; var 密码 = args[1]; var certificate2 = new X509Certificate2(path, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.EphemeralKeySet); var certificate2 = new X509Certificate2(path, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.EphemeralKeySet);

Have you tried to pass byte data into X509Certificate2 instead of passing path?您是否尝试将字节数据传递到X509Certificate2而不是传递路径? check below src from the official document .官方文档中查看下面的 src 。

I have faced a similar problem when loading from HTTP call.从 HTTP 调用加载时,我遇到了类似的问题。 I had to pass cert.GetRawCertData() (Not similar to your case, but seems cause is similar)我必须通过cert.GetRawCertData() (与您的情况不相似,但似乎原因相似)

using System;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.IO;
using System.Security.Cryptography.X509Certificates;

class CertInfo
{
    //Reads a file.
    internal static byte[] ReadFile (string fileName)
    {
        FileStream f = new FileStream(fileName, FileMode.Open, FileAccess.Read);
        int size = (int)f.Length;
        byte[] data = new byte[size];
        size = f.Read(data, 0, size);
        f.Close();
        return data;
    }
    //Main method begins here.
    static void Main(string[] args)
    {
        //Test for correct number of arguments.
        if (args.Length < 1)
        {
            Console.WriteLine("Usage: CertInfo <filename>");
            return;
        }
        try
        {
            X509Certificate2 x509 = new X509Certificate2();
            //Create X509Certificate2 object from .cer file.
            byte[] rawData = ReadFile(args[0]);
            x509.Import(rawData);

            //Print to console information contained in the certificate.
            Console.WriteLine("{0}Subject: {1}{0}", Environment.NewLine, x509.Subject);
            Console.WriteLine("{0}Issuer: {1}{0}", Environment.NewLine, x509.Issuer);
            Console.WriteLine("{0}Version: {1}{0}", Environment.NewLine, x509.Version);
            Console.WriteLine("{0}Valid Date: {1}{0}", Environment.NewLine, x509.NotBefore);
            Console.WriteLine("{0}Expiry Date: {1}{0}", Environment.NewLine, x509.NotAfter);
            Console.WriteLine("{0}Thumbprint: {1}{0}", Environment.NewLine, x509.Thumbprint);
            Console.WriteLine("{0}Serial Number: {1}{0}", Environment.NewLine, x509.SerialNumber);
            Console.WriteLine("{0}Friendly Name: {1}{0}", Environment.NewLine, x509.PublicKey.Oid.FriendlyName);
            Console.WriteLine("{0}Public Key Format: {1}{0}", Environment.NewLine, x509.PublicKey.EncodedKeyValue.Format(true));
            Console.WriteLine("{0}Raw Data Length: {1}{0}", Environment.NewLine, x509.RawData.Length);
            Console.WriteLine("{0}Certificate to string: {1}{0}", Environment.NewLine, x509.ToString(true));
            Console.WriteLine("{0}Certificate to XML String: {1}{0}", Environment.NewLine, x509.PublicKey.Key.ToXmlString(false));

            //Add the certificate to a X509Store.
            X509Store store = new X509Store();
            store.Open(OpenFlags.MaxAllowed);
            store.Add(x509);
            store.Close();
        }
        catch (DirectoryNotFoundException)
        {
               Console.WriteLine("Error: The directory specified could not be found.");
        }
        catch (IOException)
        {
            Console.WriteLine("Error: A file in the directory could not be accessed.");
        }
        catch (NullReferenceException)
        {
            Console.WriteLine("File must be a .cer file. Program does not have access to that type of file.");
        }
    }
}

Use local computer store for the private key:使用本地计算机存储作为私钥:

X509Certificate2 cert = new X509Certificate2("yourhost.pfx", "password", X509KeyStorageFlags.MachineKeySet);

MachineKeySet is described as private keys are stored in the local computer store rather than the current user store . MachineKeySet被描述为私钥存储在本地计算机存储中而不是当前用户存储中 The default with no flags is to place in the user store.没有标志的默认设置是放置在用户存储中。

Even though you are reading the certificate from disk and storing it in an object the private keys are still stored in the Microsoft Cryptographic API Cryptographic Service Provider key database.即使您从磁盘读取证书并将其存储在对象中,私钥仍存储在Microsoft Cryptographic API Cryptographic Service Provider 密钥数据库中。 On the hosting server the ASP.NET process does not have permission to access the user store.在托管服务器上, ASP.NET进程无权访问用户存储。

Another approach: (If you change your application console to web)另一种方法:(如果您将应用程序控制台更改为 Web)
Modify the IIS Configuration or App Pool identity-- which do work.修改 IIS 配置或应用程序池标识——这确实有效。 However, this assumes that there is access to these configuration items which may not be the case (eg in shared hosting environment).但是,这假设可以访问这些配置项,但情况可能并非如此(例如,在共享托管环境中)。

You can read more about MSDN.System.Security.Cryptography.X509Certificates 您可以阅读有关 MSDN.System.Security.Cryptography.X509Certificates 的更多信息

Setting the MachineKeySet flag will solve the problem of loading the certificate but you'll end up getting "Access denied" error when trying to use it to sign or decrypt, so you will switch to BoucyCastle.设置 MachineKeySet 标志将解决加载证书的问题,但是当您尝试使用它来签名或解密时,您最终会收到“访问被拒绝”错误,因此您将切换到 BoucyCastle。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM