Thursday, May 28, 2009

Open Certificate Stores

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

/// True if a certificate is selected and false if no certificate is selected

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

2 comments:

  1. Hi Meetu,
    Isn't life simple with the System.Security.Cryptography.X509Certificates namespace??

    ReplyDelete
  2. There Are always more then one method to solve a problem. I shared One of them

    ReplyDelete

Subscribe via email

Enter your email address:

Delivered by FeedBurner

MSDotnetMentor

MSDotnetMentor My Website http://msdotnetmentor.com