//*************************************************************** // // CertCSP // CryptoAPI P/Invoke to find a certificate CU MY store // Determines if cert has private key using CryptAcquireCertificatePrivateKey() // Lists some CSP properties using CryptGetProvParam() // // Copyright (C) 2003. Michel I. Gallant //*************************************************************** using System; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using System.ComponentModel; using System.Text; public class WinCapi { /* HCERTSTORE WINAPI CertOpenSystemStore(HCRYPTPROV hprov, LPTCSTR szSubsystemProtocol); BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags); PCCERT_CONTEXT WINAPI CertFindCertificateInStore( HCERTSTORE hCertStore, DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType, const void* pvFindPara, PCCERT_CONTEXT pPrevCertContext); BOOL WINAPI CryptAcquireCertificatePrivateKey( PCCERT_CONTEXT pCert, DWORD dwFlags, void* pvReserved, HCRYPTPROV* phCryptProv, DWORD* pdwKeySpec, BOOL* pfCallerFreeProv ); BOOL WINAPI CertFreeCertificateContext( PCCERT_CONTEXT pCertContext ); */ [DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern IntPtr CertOpenSystemStore( IntPtr hCryptProv, string storename) ; [DllImport("crypt32.dll", SetLastError=true)] public static extern bool CertCloseStore( IntPtr hCertStore, uint dwFlags) ; [DllImport("crypt32.dll", SetLastError=true)] public static extern IntPtr CertFindCertificateInStore( IntPtr hCertStore, uint dwCertEncodingType, uint dwFindFlags, uint dwFindType, [In, MarshalAs(UnmanagedType.LPWStr)]String pszFindString, IntPtr pPrevCertCntxt) ; [DllImport("crypt32.dll", SetLastError=true)] public static extern bool CertFreeCertificateContext( IntPtr hCertStore) ; [DllImport("crypt32.dll", SetLastError=true)] public static extern bool CryptAcquireCertificatePrivateKey( IntPtr pCert, uint dwFlags, IntPtr pReserved, ref IntPtr hProv, ref uint dwKeySpec, ref bool pfCallerFreeProv) ; [DllImport("advapi32.dll")] public static extern bool CryptReleaseContext( IntPtr hProv, uint dwFlags) ; [DllImport("advapi32.dll", SetLastError=true)] public static extern bool CryptGetProvParam( IntPtr hProv, uint dwParam, [MarshalAs(UnmanagedType.LPStr)] StringBuilder pbData, ref uint dwDataLen, uint dwFlags) ; [DllImport("advapi32.dll", SetLastError=true)] public static extern bool CryptGetProvParam( IntPtr hProv, uint dwParam, ref uint pbData, ref uint dwDataLen, uint dwFlags) ; } public class CertCSP { const string MY = "MY"; const string OTHERS = "AddressBook"; const uint PKCS_7_ASN_ENCODING = 0x00010000; const uint X509_ASN_ENCODING = 0x00000001; const uint CERT_FIND_SUBJECT_STR = 0x00080007; static uint MY_ENCODING_TYPE = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING ; const uint PP_NAME = 04; const uint PP_CONTAINER = 06; const uint PP_PROVTPE = 16; const uint PP_UNIQUE_CONTAINER = 36; static String[] CSPTypes = { null, "PROV_RSA_FULL", //1 "PROV_RSA_SIG", //2 "PROV_DSS", "PROV_FORTEZZA", "PROV_MS_EXCHANGE", "PROV_SSL", null, null, null, null, null, "PROV_RSA_SCHANNEL", //12 "PROV_DSS_DH", "PROV_EC_ECDSA_SIG", "PROV_EC_ECNRA_SIG", "PROV_EC_ECDSA_FULL", "PROV_EC_ECNRA_FULL", "PROV_DH_SCHANNEL", null, "PROV_SPYRUS_LYNKS", //20 "PROV_RNG", "PROV_INTEL_SEC", "PROV_REPLACE_OWF", "PROV_RSA_AES" // 24 }; static string[] keyspecs = {null, "AT_KEYEXCHANGE", "AT_SIGNATURE"}; static string lpszCertSubject = "" ; public static void Main(string[] args){ IntPtr hSysStore = IntPtr.Zero; IntPtr hCertCntxt = IntPtr.Zero; IntPtr hCryptProv = IntPtr.Zero; uint keyspec = 0; bool freecsp = false; const int BUFFSIZE = 512; uint pcbData = BUFFSIZE; uint dwFlags = 0; uint csptype = 0; uint pcbType = 4; if(args.Length<1) { Console.WriteLine("Usage: CertCSP "); return; } lpszCertSubject = args[0] ; hSysStore = WinCapi.CertOpenSystemStore(IntPtr.Zero, MY) ; //Console.WriteLine("Store Handle:\t{0}", hSysStore); if(hSysStore != IntPtr.Zero) { hCertCntxt=WinCapi.CertFindCertificateInStore( hSysStore, MY_ENCODING_TYPE, 0, CERT_FIND_SUBJECT_STR, lpszCertSubject , IntPtr.Zero) ; if(hCertCntxt != IntPtr.Zero){ //use certcontext from managed code //Console.WriteLine("CertContext:\t{0}", hCertCntxt) ; X509Certificate foundcert = new X509Certificate(hCertCntxt); Console.WriteLine("\nFound certificate with SubjectName string \"{0}\"",lpszCertSubject); Console.WriteLine("SubjectName:\t{0}", foundcert.GetName()); Console.WriteLine("Serial No:\t{0}", foundcert.GetSerialNumberString()); Console.WriteLine("HashString:\t{0}" , foundcert.GetCertHashString()); if(WinCapi.CryptAcquireCertificatePrivateKey(hCertCntxt, 0, IntPtr.Zero, ref hCryptProv, ref keyspec, ref freecsp)) { Console.WriteLine("Got cert PVK with keyspec {0}", keyspecs[keyspec]); StringBuilder sb = new StringBuilder(BUFFSIZE); Console.WriteLine("\n------------ CSP Properties -------------"); pcbData = BUFFSIZE; //set buffer size if(WinCapi.CryptGetProvParam(hCryptProv, PP_NAME, sb, ref pcbData, dwFlags)) Console.WriteLine("CSP Name: {0}", sb.ToString()); if(WinCapi.CryptGetProvParam(hCryptProv, PP_PROVTPE, ref csptype, ref pcbType, dwFlags)) Console.WriteLine("CSP Type: {0} {1}", csptype, CSPTypes[csptype]) ; pcbData = BUFFSIZE; //reset buffer size if(WinCapi.CryptGetProvParam(hCryptProv, PP_CONTAINER, sb, ref pcbData, dwFlags)) Console.WriteLine("KEY CONTAINER: {0}", sb.ToString()); pcbData = BUFFSIZE; //reset buffer size if(WinCapi.CryptGetProvParam(hCryptProv, PP_UNIQUE_CONTAINER, sb, ref pcbData, dwFlags)) Console.WriteLine("UNIQUE CONTAINER: {0}", sb.ToString()); WinCapi.CryptReleaseContext(hCryptProv, 0) ; Console.WriteLine("\n---------------------------------------"); } } else Console.WriteLine("Could not find SubjectName containing string \"{0}\"", lpszCertSubject); } //------- Clean Up ----------- if(hCertCntxt != IntPtr.Zero) WinCapi.CertFreeCertificateContext(hCertCntxt); if(hSysStore != IntPtr.Zero) WinCapi.CertCloseStore(hSysStore, 0) ; } private static void showWin32Error(int errorcode) { Win32Exception myEx=new Win32Exception(errorcode); Console.WriteLine("Error code:\t 0x{0:X}", myEx.ErrorCode); Console.WriteLine("Error message:\t " + myEx.Message); } }