我想使用CryptoAPI P / Invoke从商店获取证书。但是我遇到了一些问题。我可以开商店,但是找不到证书。我不明白为什么。相同的代码适用于C ++。我想使用CryptoAPI,因为.NET仅允许使用带有密钥可导出标记为“是”的证书密钥。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; namespace capp { public class Crypto { #region CONSTS // #define CERT_COMPARE_SHIFT 16 public const Int32 CERT_COMPARE_SHIFT = 16; // #define CERT_STORE_PROV_SYSTEM_W ((LPCSTR) 10) public const Int32 CERT_STORE_PROV_SYSTEM_W = 10; // #define CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W public const Int32 CERT_STORE_PROV_SYSTEM = CERT_STORE_PROV_SYSTEM_W; // #define CERT_SYSTEM_STORE_CURRENT_USER_ID 1 public const Int32 CERT_SYSTEM_STORE_CURRENT_USER_ID = 1; // #define CERT_SYSTEM_STORE_LOCATION_SHIFT 16 public const Int32 CERT_SYSTEM_STORE_LOCATION_SHIFT = 16; // #define CERT_SYSTEM_STORE_CURRENT_USER \ // (CERT_SYSTEM_STORE_CURRENT_USER_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT) public const Int32 CERT_SYSTEM_STORE_CURRENT_USER = CERT_SYSTEM_STORE_CURRENT_USER_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT; // #define CERT_COMPARE_SHA1_HASH 1 public const Int32 CERT_COMPARE_SHA1_HASH = 1; // #define CERT_FIND_SHA1_HASH (CERT_COMPARE_SHA1_HASH << CERT_COMPARE_SHIFT) public const Int32 CERT_FIND_SHA1_HASH = (CERT_COMPARE_SHA1_HASH << CERT_COMPARE_SHIFT); // #define X509_ASN_ENCODING 0x00000001 public const Int32 X509_ASN_ENCODING = 0x00000001; // #define PKCS_7_ASN_ENCODING 0x00010000 public const Int32 PKCS_7_ASN_ENCODING = 0x00010000; // #define MY_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) public const Int32 MY_ENCODING_TYPE = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING; #endregion #region STRUCTS // typedef struct _CRYPTOAPI_BLOB // { // DWORD cbData; // BYTE *pbData; // } CRYPT_HASH_BLOB, CRYPT_INTEGER_BLOB, // CRYPT_OBJID_BLOB, CERT_NAME_BLOB; [StructLayout(LayoutKind.Sequential)] public struct CRYPTOAPI_BLOB { public Int32 cbData; public Byte[] pbData; } #endregion #region FUNCTIONS (IMPORTS) // HCERTSTORE WINAPI CertOpenStore( // LPCSTR lpszStoreProvider, // DWORD dwMsgAndCertEncodingType, // HCRYPTPROV hCryptProv, // DWORD dwFlags, // const void* pvPara // ); [DllImport("Crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr CertOpenStore( Int32 lpszStoreProvider, Int32 dwMsgAndCertEncodingType, IntPtr hCryptProv, Int32 dwFlags, String pvPara ); // BOOL WINAPI CertCloseStore( // HCERTSTORE hCertStore, // DWORD dwFlags // ); [DllImport("Crypt32.dll", SetLastError = true)] public static extern Boolean CertCloseStore( IntPtr hCertStore, Int32 dwFlags ); // PCCERT_CONTEXT WINAPI CertFindCertificateInStore( // HCERTSTORE hCertStore, // DWORD dwCertEncodingType, // DWORD dwFindFlags, // DWORD dwFindType, // const void* pvFindPara, // PCCERT_CONTEXT pPrevCertContext // ); [DllImport("Crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr CertFindCertificateInStore( IntPtr hCertStore, Int32 dwCertEncodingType, Int32 dwFindFlags, Int32 dwFindType, //String pvFindPara, ref CRYPTOAPI_BLOB pvFindPara, IntPtr pPrevCertContext ); // BOOL WINAPI CertFreeCertificateContext( // PCCERT_CONTEXT pCertContext // ); [DllImport("Crypt32.dll", SetLastError = true)] public static extern Boolean CertFreeCertificateContext( IntPtr pCertContext ); #endregion } class Program { const string MY = "MY"; static void Main(string[] args) { IntPtr hCertCntxt = IntPtr.Zero; IntPtr hStore = IntPtr.Zero; hStore = Crypto.CertOpenStore(Crypto.CERT_STORE_PROV_SYSTEM, Crypto.MY_ENCODING_TYPE, IntPtr.Zero, Crypto.CERT_SYSTEM_STORE_CURRENT_USER, MY); Console.WriteLine("Store Handle:\t0x{0:X}", hStore.ToInt32()); String sha1Hex = "7a0b021806bffdb826205dac094030f8045d4daa"; // Convert to bin int tam = sha1Hex.Length / 2; byte[] sha1Bin = new byte[tam]; int aux = 0; for (int i = 0; i < tam; ++i) { String str = sha1Hex.Substring(aux, 2); sha1Bin[i] = (byte)Convert.ToInt32(str, 16); aux = aux + 2; } Crypto.CRYPTOAPI_BLOB cryptBlob; cryptBlob.cbData = sha1Bin.Length; cryptBlob.pbData = sha1Bin; if (hStore != IntPtr.Zero) { Console.WriteLine("Inside Store"); hCertCntxt = Crypto.CertFindCertificateInStore( hStore, Crypto.MY_ENCODING_TYPE, 0, Crypto.CERT_FIND_SHA1_HASH, ref cryptBlob, IntPtr.Zero); if (hCertCntxt != IntPtr.Zero) Console.WriteLine("Certificate found!"); else Console.WriteLine("Could not find "); } if (hCertCntxt != IntPtr.Zero) Crypto.CertFreeCertificateContext(hCertCntxt); if (hStore != IntPtr.Zero) Crypto.CertCloseStore(hStore, 0); } } }
将CrytpoAPI映射到C#http://blogs.msdn.com/b/alejacma/archive/2007/11/23/p-invoking-cryptoapi-in-net-c-version.aspx的参考链接
我想使用CryptoAPI P / Invoke从商店获取证书。但是我遇到了一些问题。我可以开商店,但是找不到证书。我不明白为什么。相同的代码适用于C ++。 ...
您不能只是重新定义CertFindCertificateInStore
以取ref CRYPTOAPI_BLOB
。
如果使用的是.Net,为什么不使用“ System.Security.Cryptography”来执行此操作?