Open Certificate Stores
I am working on Digital Signatures with ASP.Net. Once in a life time for a programmer we get a chance to work for security or with security and even myself is not an exception . I have to work with digital signatures to achieve security and I searched a lot in internet to achieve what i need and I am still in the process to learn more but in this journey I have found many things but most of them were related to java and applets as I was form .net domain I had to work on it. So here I am Starting the discussion with the first obstacle I met, it is to open a certificate store as of Internet Explorer... I am calling it first as I need not to generate the digital signature as I have them which were already issued by the authorized CA. still if you want to have a look then you can go through the link where i have explained how to create a certificate.. or the mirror link...
Proceeding further... I have encountered two ways to open a certificate store discussing them here..
Method One:
Certfun is a class which i found on the Internet which i don't remember where exactly but i have modified that class as i found that code in vb and i need that in C# so i will paste the code at the end
Limitation:-- This will not open the certificate in the token.
[code]
///
/// Opens the Certificate Store of IE Excluding the Certificates in Token
///
/// The variable passed to store the reason if function returns false
///
public Boolean OpenStoreIE(ref string popupScript)
{
x509_2 = null;
//declare a pointer and initilize it with Zero This pointer will hold the value returened by opening the Store
IntPtr hCertStore = IntPtr.Zero;
//declare a pointer and initilize it with Zero This pointer will hold the value returened by selecting the certificate from the store
IntPtr pCertContext = IntPtr.Zero;
//Declare a string and Intilaize it with the store name to open by default it is 'My' Stroe from where we store or install the certificates
string kk = "MY";
//Declaring a StringBuilder Object to hold the NameString of the certificate
StringBuilder NS = new StringBuilder(128);
//To hold the size
int provinfosize = 0;
//Opens the Store and returns a pointer handler of the Store.
hCertStore = CertFun.CertOpenSystemStore(IntPtr.Zero, kk);
//Will returns the pointer handler of the selected certificate
pCertContext = CertFun.CryptUIDlgSelectCertificateFromStore(hCertStore, IntPtr.Zero, "Personal Store", "Please select a PKC12 (.pfx) Certificate and press ok", cf.CRYPTUI_SELECT_LOCATION_COLUMN, 0, IntPtr.Zero);
//Testing if the pointer handler is equal to zero then informing the user that no certificate is selected and exiting the function
if (pCertContext.Equals(IntPtr.Zero))
{
popupScript = "You didn't select a certificate!!!";
//ScriptManager.RegisterClientScriptBlock(Page, this.GetType(), "nocert", popupScript, false);
return false;
}
//check certificate is PKCS12
if (!CertFun.CertGetCertificateContextProperty(pCertContext, cf.CERT_KEY_PROV_INFO_PROP_ID, IntPtr.Zero, ref provinfosize))
{
//Check the pointer handler if it is not eqal to zero then
if (!(pCertContext.Equals(IntPtr.Zero)))
{
//free the pointer handler as the certificate is not PKCS12
CertFun.CertFreeCertificateContext(pCertContext);
}
//Display a message and exit from the function
popupScript = "Selected certificate is not PKCS12. Please select a PKCS12 certificate!!!";
//ScriptManager.RegisterClientScriptBlock(Page, this.GetType(), "invalidcert", popupScript, false);
return false;
}
else
{
// yes pkcs12
//need not to do anything here
}
//Get Name String for the Certificate into your stringbuilder created above
if ((CertFun.CertGetNameString(pCertContext, cf.CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, IntPtr.Zero, NS, 128)))
{
}
else
{
// Can Display the message here that certificate name failed
//in my case no requirement to display this message
}
//Now store the user selected certificate into the global static variable for later use
x509_2 = new X509Certificate2(pCertContext);
return true;
}
[/code]
CertFun
[code]
using
System;
using
System.Runtime.InteropServices;
using
System.Security.Cryptography;
using
System.Text;
namespace
Secure_Login
{
///
/// Summary description for CertFun
/// class which will handle and implemet the delegates
///
public class CertFun
{
[StructLayout(LayoutKind.Sequential)]
public struct CRYPTUI_CERT_MGR_STRUCT
{
public int dwSize;
public IntPtr hwndParent;
public int dwFlags;
public string pwszTitle;
public IntPtr pszInitUsageOID;
}
[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_KEY_PROV_INFO
{
[MarshalAs(UnmanagedType.LPWStr)]
public string ContainerName;
[MarshalAs(UnmanagedType.LPWStr)]
public string ProvName;
public int ProvType;
public int Flags;
public int ProvParam;
public IntPtr rgProvParam;
public int KeySpec;
}
[DllImport("cryptui.dll", SetLastError = true)]
public static extern IntPtr CryptUIDlgSelectCertificateFromStore(IntPtr hCertStore, IntPtr hwnd, [MarshalAs(UnmanagedType.LPWStr)]
string
pwszTitle, [MarshalAs(UnmanagedType.LPWStr)]
string
pwszDisplayString, int dwDontUseColumn, int dwFlags, IntPtr pvReserved);
[DllImport("crypt32.dll", SetLastError = true)]
public static extern IntPtr CertEnumCertificatesInStore(IntPtr hCertStore, IntPtr pPrevCertContext);
[DllImport("crypt32.dll", SetLastError = true)]
public static extern bool CertGetNameString(IntPtr pCertContext, int dwType, int dwFlags, IntPtr pvTypePara, StringBuilder pszNameString, Int32 cchNameString);
[DllImport("crypt32.dll", SetLastError = true)]
public static extern bool CertGetCertificateContextProperty(IntPtr pCertContext, int dwPropId, IntPtr pvData, ref int pcbData);
[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 CertFreeCertificateContext(IntPtr hCertStore);
[DllImport("crypt32.dll", SetLastError = true)]
public static extern bool CertCloseStore(IntPtr hCertStore, int dwFlags);
[DllImport("cryptui.dll", SetLastError = true)]
public static extern bool CryptUIDlgCertMgr(ref CRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr);
[DllImport("crypt32.dll")]
public static extern bool CryptDecodeObject(int CertEncodingType, int lpszStructType, byte[] pbEncoded, int cbEncoded, int flags, [In(), Out()]
byte
[] pvStructInfo, ref int cbStructInfo);
[DllImport("crypt32.dll", SetLastError = true)]
public static extern IntPtr CertFindCertificateInStore(IntPtr hCertStore, int dwCertEncodingType, int dwFindFlags, int dwFindType, [In(), MarshalAs(UnmanagedType.LPWStr)]
string
pszFindString, IntPtr pPrevCertContext);
[StructLayout(LayoutKind.Sequential)]
public struct PUBKEYBLOBHEADERS
{
////BLOBHEADER
public byte bType;
// //BLOBHEADER
public byte bVersion;
////BLOBHEADER
public short reserved;
////BLOBHEADER
public Int32 aiKeyAlg;
// //RSAPUBKEY
public int magic;
//; '//RSAPUBKEY
public int bitlen;
//; //RSAPUBKEY
public int pubexp;
}
public int CERT_NAME_SIMPLE_DISPLAY_TYPE = 0x4;
public int CRYPTUI_SELECT_LOCATION_COLUMN = 0x10;
public int CERT_KEY_PROV_INFO_PROP_ID = 0x2;
static public int X509_ASN_ENCODING = 0x1;
static public int PKCS_7_ASN_ENCODING = 0x10000;
public int RSA_CSP_PUBLICKEYBLOB = 19;
static public int ENCODING_TYPE = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
public int CERT_FIND_SUBJECT_STR = 0x80007;
public byte[] pubblob;
public string PKC12CertSelectedName = "";
public byte[] EncKey;
public byte[] EncIv;
public byte[] EncData;
//creates new instance of Rinjndael
public RijndaelManaged Rin = new RijndaelManaged();
public byte[] SignedData;
public string CertForEnc = "";
public string CertForSig = "";
}
}
[/code]
I will Cover the next method in my next resource which will overcome the limitation of the method one
Thanks and Regards
Meetu Choudhary