第一个参数中文件的格式(.pfx,.cer或其他什么)应该是什么?
public X509Certificate2(
string fileName,
SecureString password,
X509KeyStorageFlags keyStorageFlags
)
更多背景信息:
我在尝试使用以下函数获取证书时遇到以下错误 -
功能:
public static X509Certificate2 AuthenticationCertificate(string AuthenticationCertificateAsBase64String, string AuthenticationCertificatePassword)
{
if (!string.IsNullOrEmpty(AuthenticationCertificateAsBase64String) &&
AuthenticationCertificatePassword != null)
{
Console.WriteLine("AuthenticationCertificateAsBase64String: " + AuthenticationCertificateAsBase64String);
Console.WriteLine("AuthenticationCertificatePassword: " + AuthenticationCertificatePassword);
return new X509Certificate2(Convert.FromBase64String(AuthenticationCertificateAsBase64String),
AuthenticationCertificatePassword);
}
return null;
}
错误:
{System.Security.Cryptography.CryptographicException: The specified network password is not correct.
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromBlob(Byte[] rawData, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx)
at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(Byte[] rawData, Object password, X509KeyStorageFlags keyStorageFlags)
at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData, String password)
at CryptoPlay.Program.AuthenticationCertificate(String AuthenticationCertificateAsBase64String, String AuthenticationCertificatePassword) in d:\personal\CryptoPlay\CryptoPlay\Program.cs:line 154
at CryptoPlay.Program.Main(String[] args) in d:\personal\CryptoPlay\CryptoPlay\Program.cs:line 59
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()}
错误表示密码不正确但不是这样。如果有人感兴趣,这里是完整的参考代码(将文件名和密码替换为通用名称作为示例)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Pkcs;
namespace CryptoPlay
{
class Program
{
static void Main(string[] args)
{
X509Certificate2 spCert = GetCertificateForUse();
X509Certificate2 encryptCert = GetCertificateUsedForEncryption();
string AuthenticationCertificatePasswordBase64String = EncryptAsBase64String(encryptCert, "Password1!");
Console.WriteLine("AuthenticationCertificatePasswordBase64String:");
Console.WriteLine(AuthenticationCertificatePasswordBase64String);
string AuthenticationCertificatePassword = DecryptFromBase64String(AuthenticationCertificatePasswordBase64String);
Console.WriteLine("AuthenticationCertificatePassword:");
Console.WriteLine(AuthenticationCertificatePassword);
string CertificateAsBase64String = EncryptAsBase64String(encryptCert, spCert);
Console.WriteLine("CertificateAsBase64String");
Console.WriteLine(CertificateAsBase64String);
byte[] rawdata = DecryptBytesFromBase64String(CertificateAsBase64String);
Console.WriteLine("Raw data: " + PrintBytes(rawdata));
string AuthenticationCertificateAsBase64String = Convert.ToBase64String(DecryptBytesFromBase64String(CertificateAsBase64String));
Console.WriteLine("AuthenticationCertificateAsBase64String:");
Console.WriteLine(AuthenticationCertificateAsBase64String);
byte[] rawdata2 = Convert.FromBase64String(AuthenticationCertificateAsBase64String);
Console.WriteLine("Raw data: " + PrintBytes(rawdata2));
if (ByteArrayCompare(rawdata, rawdata2))
Console.WriteLine("Raw data are same");
X509Certificate2 certFromConfig = AuthenticationCertificate(AuthenticationCertificateAsBase64String, AuthenticationCertificatePassword);
Console.WriteLine("Press enter to close...");
Console.ReadLine();
}
public static byte[] DecryptBytesFromBase64String(string payloadBase64String, X509Certificate2 decryptingCert = null)
{
try
{
var env = new EnvelopedCms();
env.Decode(Convert.FromBase64String(payloadBase64String));
if (decryptingCert != null)
{
env.Decrypt(new X509Certificate2Collection(decryptingCert));
}
else
{
env.Decrypt();
}
return env.ContentInfo.Content;
}
catch (Exception e)
{
throw new CryptographicException("Failed to decrypt: " + payloadBase64String, e);
}
}
public static string DecryptFromBase64String(string payloadBase64String, X509Certificate2 decryptingCert = null)
{
return Encoding.UTF8.GetString(DecryptBytesFromBase64String(payloadBase64String, decryptingCert));
}
public static string EncryptAsBase64String(X509Certificate2 cert, string payload)
{
return EncryptAsBase64String(cert, Encoding.UTF8.GetBytes(payload));
}
public static string EncryptAsBase64String(X509Certificate2 cert, byte[] payload)
{
var ci = new ContentInfo(payload);
var env = new EnvelopedCms(ci);
env.Encrypt(new CmsRecipient(cert));
return Convert.ToBase64String(env.Encode());
}
public static string EncryptAsBase64String(X509Certificate2 encryptingCert, X509Certificate2 payload)
{
byte[] bytes = payload.Export(X509ContentType.Pfx);
return EncryptAsBase64String(encryptingCert, bytes);
}
private static X509Certificate2 GetCertificateUsedForEncryption()
{
string certPath = "D:\\encryptcert.pfx";
string certPassword = "P@ssword123";
var cert = new X509Certificate2(certPath, certPassword, X509KeyStorageFlags.Exportable);
return cert;
}
private static X509Certificate2 GetCertificateForUse()
{
string certPath = "D:\\securecert.pfx";
string certPassword = "Password1!";
var cert = new X509Certificate2(certPath, certPassword, X509KeyStorageFlags.Exportable);
return cert;
}
public static X509Certificate2 AuthenticationCertificate(string AuthenticationCertificateAsBase64String, string AuthenticationCertificatePassword)
{
if (!string.IsNullOrEmpty(AuthenticationCertificateAsBase64String) &&
AuthenticationCertificatePassword != null)
{
Console.WriteLine("AuthenticationCertificateAsBase64String: " + AuthenticationCertificateAsBase64String);
Console.WriteLine("AuthenticationCertificatePassword: " + AuthenticationCertificatePassword);
return new X509Certificate2(Convert.FromBase64String(AuthenticationCertificateAsBase64String),
AuthenticationCertificatePassword);
}
return null;
}
public static string PrintBytes(byte[] byteArray)
{
var sb = new StringBuilder("new byte[] { ");
for (var i = 0; i < byteArray.Length; i++)
{
var b = byteArray[i];
sb.Append(b);
if (i < byteArray.Length - 1)
{
sb.Append(", ");
}
}
sb.Append(" }");
return sb.ToString();
}
static bool ByteArrayCompare(byte[] a1, byte[] a2)
{
if (a1.Length != a2.Length)
return false;
for (int i = 0; i < a1.Length; i++)
if (a1[i] != a2[i])
return false;
return true;
}
}
}
答案 0 :(得分:1)
您最初的问题是关于以string
作为第一个参数的重载,但您的代码使用的是使用byte[]
的重载。
简单的答案是,字符串1只是一个文件名,作为字节数组加载,然后调用另一个(它比那更细致,例如文件一个不像符号链路)。
以下类型(由我)知道:
-----BEGIN CERTIFICATE-----\n[etc]\n-----END CERTIFICATE-----
)-----BEGIN PKCS7-----\n...
)(使用第一个签名者识别的嵌入式证书)您是否传入密码与blob被识别为的文件格式无关。除非您的个人资料或临时目录位于SMB / CIFS共享上,否则Windows报告ERROR_BAD_PASSWORD
表示它认为您的字节代表PFX,但无法使用输入密码作为密钥验证PFX MAC。我建议您检查密码变量是否包含嵌入式换行符或换行符(或空值);或领先或尾随空格。