我在C#中使用crypt api创建SSL证书时遇到问题,CertCreateSelfSignCertificate返回null,错误代码为87(参数不正确)。 不知道错过了什么。
Win32Native.CRYPTOAPI_BLOB SubjectIssuerBlob = new Win32Native.CRYPTOAPI_BLOB();
GCHandle asnNameHandle = GCHandle.Alloc(pbEncoded, GCHandleType.Pinned);
// SubjectIssuerBlob.pbData = Marshal.AllocHGlobal(pbEncoded.Length);
//Marshal.Copy(pbEncoded, 0, SubjectIssuerBlob.pbData, pbEncoded.Length);
SubjectIssuerBlob.pbData = asnNameHandle.AddrOfPinnedObject();
SubjectIssuerBlob.cbData = cbEncoded;
Win32Native.CRYPT_KEY_PROV_INFO providerInfo = new Win32Native.CRYPT_KEY_PROV_INFO();
providerInfo.pwszContainerName = hostname;
providerInfo.pwszProvName = null;
providerInfo.dwProvType = PROV_RSA_FULL;
providerInfo.dwFlags = CRYPT_MACHINE_KEYSET;
providerInfo.cProvParam = 0;
providerInfo.rgProvParam = IntPtr.Zero;
providerInfo.dwKeySpec = AT_SIGNATURE;
Win32Native.CRYPT_ALGORITHM_IDENTIFIER algorithmID = new Win32Native.CRYPT_ALGORITHM_IDENTIFIER();
algorithmID.pszObjId = "1.2.840.113549.1.1.5"; //szOID_RSA_SHA1RSA
pContext = Win32Native.CertCreateSelfSignCertificate(IntPtr.Zero, ref SubjectIssuerBlob, 0, ref providerInfo, ref algorithmID, null, endtime, IntPtr.Zero);
win32api呼叫
[DllImport("Crypt32.dll", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static extern IntPtr CertCreateSelfSignCertificate(
IntPtr providerHandle,
ref CRYPTOAPI_BLOB subjectIssuerBlob,
uint flags,
ref CRYPT_KEY_PROV_INFO pKeyProvInfo,
ref CRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
SystemTime startTime,
SystemTime endTime,
IntPtr extensions);
答案 0 :(得分:0)
在Windows 10 VS 2015上使用 CertCreateSelfSignCertificate 进行的测试=>
对话框(法语):
//Guid guidContainerName = Guid.NewGuid();
Guid guidContainerName = Guid.Empty;
int nRet = UuidCreate(out guidContainerName);
if (nRet == 0)
{
IntPtr pContainerName = new IntPtr();
nRet = UuidToString(ref guidContainerName, ref pContainerName);
string sContainerName;
sContainerName = Marshal.PtrToStringUni(pContainerName);
string sProviderName = MS_DEF_PROV;
IntPtr hProv = IntPtr.Zero;
bool bRet = CryptAcquireContext(ref hProv, sContainerName, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET);
IntPtr hKey = IntPtr.Zero;
bRet = CryptGenKey(hProv, AT_KEYEXCHANGE, RSA1024BIT_KEY | CRYPT_EXPORTABLE, ref hKey);
string sSubject = "CN=TEST,OU=TESTOU";
byte[] encodedSubjectName = null;
uint nNameLenght = 0;
if (CertStrToName(X509_ASN_ENCODING, sSubject, CERT_X500_NAME_STR, IntPtr.Zero, null, ref nNameLenght, IntPtr.Zero))
{
encodedSubjectName = new byte[nNameLenght];
CertStrToName(X509_ASN_ENCODING, sSubject, CERT_X500_NAME_STR, IntPtr.Zero, encodedSubjectName, ref nNameLenght, IntPtr.Zero);
}
CERT_NAME_BLOB subjectblob = new CERT_NAME_BLOB();
subjectblob.pbData = Marshal.AllocHGlobal(encodedSubjectName.Length);
Marshal.Copy(encodedSubjectName, 0, subjectblob.pbData, encodedSubjectName.Length);
subjectblob.cbData = encodedSubjectName.Length;
CRYPT_KEY_PROV_INFO pKeyProvInfo = new CRYPT_KEY_PROV_INFO();
pKeyProvInfo.pwszContainerName = sContainerName;
pKeyProvInfo.pwszProvName = sProviderName;
pKeyProvInfo.dwProvType = PROV_RSA_FULL;
pKeyProvInfo.rgProvParam = IntPtr.Zero;
pKeyProvInfo.dwKeySpec = AT_KEYEXCHANGE;
IntPtr pcCertContext = CertCreateSelfSignCertificate(hProv, ref subjectblob, 0, ref pKeyProvInfo, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
if (pcCertContext != IntPtr.Zero)
{
X509Certificate cert = new X509Certificate(pcCertContext);
// Add reference to System.Security
X509Certificate2UI.DisplayCertificate(new X509Certificate2(cert));
CertFreeCertificateContext(pcCertContext);
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
Marshal.FreeHGlobal(subjectblob.pbData);
CryptDestroyKey(hKey);
CryptReleaseContext(hProv, 0);
RpcStringFree(ref pContainerName);
}
带有声明=>
[DllImport("Crypt32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr CertCreateSelfSignCertificate(IntPtr hCryptProvOrNCryptKey, ref CERT_NAME_BLOB pSubjectIssuerBlob, int dwFlags, ref CRYPT_KEY_PROV_INFO pKeyProvInfo,
IntPtr pSignatureAlgorithm, IntPtr pStartTime, IntPtr pEndTime, IntPtr pExtensions);
[DllImport("Crypt32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CertFreeCertificateContext(IntPtr pCertContext);
[StructLayout(LayoutKind.Sequential)]
public struct CERT_NAME_BLOB
{
public int cbData;
public IntPtr pbData;
}
[DllImport("Rpcrt4.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int UuidCreate(out Guid Uuid);
[DllImport("rpcrt4.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int UuidToString(ref Guid uuid, ref IntPtr str);
[DllImport("rpcrt4.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int RpcStringFree(ref IntPtr str);
[DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CryptAcquireContext(ref IntPtr phProv, string szContainer, string szProvider, int dwProvType, uint dwFlags);
[DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlags);
[DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CryptGenKey(IntPtr hProv, uint Algid, int dwFlags, ref IntPtr phKey);
[DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CryptDestroyKey(IntPtr hKey);
public const int RSA1024BIT_KEY = 0x04000000;
public const int CRYPT_EXPORTABLE = 0x00000001;
[DllImport("Crypt32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CertStrToName(uint dwCertEncodingType, string pszX500, uint dwStrType, IntPtr pvReserved,
[In, Out] byte[] pbEncoded, ref uint pcbEncoded, IntPtr ppszError);
public const int CRYPT_ASN_ENCODING = 0x00000001;
public const int CRYPT_NDR_ENCODING = 0x00000002;
public const int X509_ASN_ENCODING = 0x00000001;
public const int X509_NDR_ENCODING = 0x00000002;
public const int PKCS_7_ASN_ENCODING = 0x00010000;
public const int PKCS_7_NDR_ENCODING = 0x00020000;
public const string MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0";
public const int PROV_RSA_FULL = 1;
public const uint CRYPT_VERIFYCONTEXT = 0xF0000000;
public const uint CRYPT_NEWKEYSET = 0x00000008;
public const uint CRYPT_DELETEKEYSET = 0x00000010;
public const uint CRYPT_MACHINE_KEYSET = 0x00000020;
public const uint CRYPT_SILENT = 0x00000040;
public const int CERT_SIMPLE_NAME_STR = 1;
public const int CERT_OID_NAME_STR = 2;
public const int CERT_X500_NAME_STR = 3;
public const int CERT_XML_NAME_STR = 4;
public const int CERT_NAME_STR_SEMICOLON_FLAG = 0x40000000;
public const int CERT_NAME_STR_NO_PLUS_FLAG = 0x20000000;
public const int CERT_NAME_STR_NO_QUOTING_FLAG = 0x10000000;
public const int CERT_NAME_STR_CRLF_FLAG = 0x08000000;
public const int CERT_NAME_STR_COMMA_FLAG = 0x04000000;
public const int CERT_NAME_STR_REVERSE_FLAG = 0x02000000;
public const int CERT_NAME_STR_FORWARD_FLAG = 0x01000000;
public const int CERT_NAME_STR_DISABLE_IE4_UTF8_FLAG = 0x00010000;
public const int CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG = 0x00020000;
public const int CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG = 0x00040000;
public const int CERT_NAME_STR_FORCE_UTF8_DIR_STR_FLAG = 0x00080000;
public const int CERT_NAME_STR_DISABLE_UTF8_DIR_STR_FLAG = 0x00100000;
public const int CERT_NAME_STR_ENABLE_PUNYCODE_FLAG = 0x00200000;
[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_KEY_PROV_INFO
{
[MarshalAs(UnmanagedType.LPWStr)] public string pwszContainerName;
[MarshalAs(UnmanagedType.LPWStr)] public string pwszProvName;
public int dwProvType;
public int dwFlags;
public int cProvParam;
public IntPtr rgProvParam;
public int dwKeySpec;
}
public const int AT_KEYEXCHANGE = 1;
public const int AT_SIGNATURE = 2;