加载 X509Certificate2 以 Windows 服务器 2012 上发生内部错误结束
Loading X509Certificate2 ends with An internal error occurred on Windows server 2012
我正在尝试从路径加载证书并在 windows 服务器上收到内部服务器错误。当我在 windows 10 上执行时,一切正常。
控制台应用程序代码不工作
var path = args[0];
var password = args[1];
var certificate2 = new X509Certificate2(path, password);
但是出现错误
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
破解工作代码(不确定为什么有效)
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);
如何在不使用 chilkat 库的情况下使其在 windows 服务器上运行?
如果您的代码是 运行 在 IIS 下的 Web 应用程序中:
- 转到 IIS 管理器
- 转到应用程序池实例
- 点击高级设置
- 在流程模型下,将加载用户配置文件设置为真
否则,请尝试指定 UserKeySet(PFX 可能在内部包含“使用机器存储”标记):
var path = args[0]; var password = args[1]; var certificate2 = new X509Certificate2(path, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.EphemeralKeySet);
否则,在本地机器上安装证书并尝试通过指纹从商店加载:
在本地机器上安装:https://blog.powerbiz.net.au/server-2012/importing-a-pfx-certificate-into-windows-server-2012/
-
使用配置的指纹从证书存储加载证书
string certificateThumbprint = "<...thumbprint...>"; X509Certificate2 certificate = null; using X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, false); if (certificates.Count > 0) certificate = certificates[0];
如果上述操作失败,则可能无法使用内置的 Windows 2012 工具将 .p12 文件导入 Windows 2012。要检查:
“对于您的每个 PKCS #12 文件,您可以尝试以下操作:发出命令 certutil -asn | findstr /i "pb aes des sha"(将“”替换为 PKCS #12 文件的名称)。
如果输出像这样开始:
| | | | | ; 1.2.840.113549.1.12.1.3 szOID_PKCS_12_pbeWithSHA1And3KeyTripleDES
那么应该可以将 PKCS #12 文件导入 Windows 2016。
如果输出像这样开始:
| | | | | ; 1.2.840.113549.1.5.13 szOID_PKCS_5_PBES2
| | | | | | ; 1.2.840.113549.1.5.12 szOID_PKCS_5_PBKDF2
| | | | | ; 2.16.840.1.101.3.4.1.42 aes256
或类似的,那么 PKCS #12 文件可能无法使用内置的 Windows 2016 工具导入到 Windows 2016。您将必须使用 TripleDES 和 SHA1 重新创建 PKCS #12 文件。”- 参见主题:https://docs.microsoft.com/en-us/answers/questions/518605/importing-a-pkcs12-to-windows-server-2016.html
您是否尝试过将字节数据传递到 X509Certificate2
而不是传递路径?从 official document.
检查下面的 src
我在从 HTTP 调用加载时遇到了类似的问题。我必须通过 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.");
}
}
}
为私钥使用本地计算机存储:
X509Certificate2 cert = new X509Certificate2("yourhost.pfx", "password", X509KeyStorageFlags.MachineKeySet);
MachineKeySet 被描述为 私钥存储在本地计算机存储而不是当前用户存储。没有标志的默认设置是放在用户存储中。
即使您从磁盘读取证书并将其存储在对象中,私钥仍存储在 Microsoft Cryptographic API 加密服务提供商密钥数据库中。 在托管服务器上,ASP.NET
进程没有访问用户存储的权限。
另一种方法:(如果您将应用程序控制台更改为 Web)
修改 IIS 配置或应用程序池标识——这确实有效。但是,这假设可以访问这些配置项,而实际情况可能并非如此(例如在共享主机环境中)。
You can read more about MSDN.System.Security.Cryptography.X509Certificates
设置 MachineKeySet 标志将解决加载证书的问题,但是当您尝试使用它来签名或解密时最终会出现“访问被拒绝”错误,因此您将切换到 BoucyCastle。
我正在尝试从路径加载证书并在 windows 服务器上收到内部服务器错误。当我在 windows 10 上执行时,一切正常。
控制台应用程序代码不工作
var path = args[0];
var password = args[1];
var certificate2 = new X509Certificate2(path, password);
但是出现错误
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
破解工作代码(不确定为什么有效)
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);
如何在不使用 chilkat 库的情况下使其在 windows 服务器上运行?
如果您的代码是 运行 在 IIS 下的 Web 应用程序中:
- 转到 IIS 管理器
- 转到应用程序池实例
- 点击高级设置
- 在流程模型下,将加载用户配置文件设置为真
否则,请尝试指定 UserKeySet(PFX 可能在内部包含“使用机器存储”标记):
var path = args[0]; var password = args[1]; var certificate2 = new X509Certificate2(path, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.EphemeralKeySet);
否则,在本地机器上安装证书并尝试通过指纹从商店加载:
在本地机器上安装:https://blog.powerbiz.net.au/server-2012/importing-a-pfx-certificate-into-windows-server-2012/
使用配置的指纹从证书存储加载证书
string certificateThumbprint = "<...thumbprint...>"; X509Certificate2 certificate = null; using X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, false); if (certificates.Count > 0) certificate = certificates[0];
如果上述操作失败,则可能无法使用内置的 Windows 2012 工具将 .p12 文件导入 Windows 2012。要检查: “对于您的每个 PKCS #12 文件,您可以尝试以下操作:发出命令 certutil -asn | findstr /i "pb aes des sha"(将“”替换为 PKCS #12 文件的名称)。
如果输出像这样开始:
| | | | | ; 1.2.840.113549.1.12.1.3 szOID_PKCS_12_pbeWithSHA1And3KeyTripleDES
那么应该可以将 PKCS #12 文件导入 Windows 2016。
如果输出像这样开始:
| | | | | ; 1.2.840.113549.1.5.13 szOID_PKCS_5_PBES2 | | | | | | ; 1.2.840.113549.1.5.12 szOID_PKCS_5_PBKDF2 | | | | | ; 2.16.840.1.101.3.4.1.42 aes256
或类似的,那么 PKCS #12 文件可能无法使用内置的 Windows 2016 工具导入到 Windows 2016。您将必须使用 TripleDES 和 SHA1 重新创建 PKCS #12 文件。”- 参见主题:https://docs.microsoft.com/en-us/answers/questions/518605/importing-a-pkcs12-to-windows-server-2016.html
您是否尝试过将字节数据传递到 X509Certificate2
而不是传递路径?从 official document.
我在从 HTTP 调用加载时遇到了类似的问题。我必须通过 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.");
}
}
}
为私钥使用本地计算机存储:
X509Certificate2 cert = new X509Certificate2("yourhost.pfx", "password", X509KeyStorageFlags.MachineKeySet);
MachineKeySet 被描述为 私钥存储在本地计算机存储而不是当前用户存储。没有标志的默认设置是放在用户存储中。
即使您从磁盘读取证书并将其存储在对象中,私钥仍存储在 Microsoft Cryptographic API 加密服务提供商密钥数据库中。 在托管服务器上,ASP.NET
进程没有访问用户存储的权限。
另一种方法:(如果您将应用程序控制台更改为 Web)
修改 IIS 配置或应用程序池标识——这确实有效。但是,这假设可以访问这些配置项,而实际情况可能并非如此(例如在共享主机环境中)。
You can read more about MSDN.System.Security.Cryptography.X509Certificates
设置 MachineKeySet 标志将解决加载证书的问题,但是当您尝试使用它来签名或解密时最终会出现“访问被拒绝”错误,因此您将切换到 BoucyCastle。