How to view a certificate programatically (C#)
Hi all,
The following C# sample shows a dialog to view a certificate and its properties. This is the same dialog that appears when we double-click on the cert file in Explorer. I'll use CryptUIDlgViewCertificate API and its CRYPTUI_VIEWCERTIFICATE_STRUCT structure to achieve this:
...
using System.Security.Cryptography.X509Certificates;
using System.Runtime.InteropServices;
namespace MyNamespace
{
public partial class MyClass
{
...
public const int CRYPTUI_DISABLE_ADDTOSTORE = 0x00000010;
[DllImport("CryptUI.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean CryptUIDlgViewCertificate(
ref CRYPTUI_VIEWCERTIFICATE_STRUCT pCertViewInfo,
ref bool pfPropertiesChanged
);
public struct CRYPTUI_VIEWCERTIFICATE_STRUCT
{
public int dwSize;
public IntPtr hwndParent;
public int dwFlags;
[MarshalAs(UnmanagedType.LPWStr)]
public String szTitle;
public IntPtr pCertContext;
public IntPtr rgszPurposes;
public int cPurposes;
public IntPtr pCryptProviderData; // or hWVTStateData
public Boolean fpCryptProviderDataTrustedUsage;
public int idxSigner;
public int idxCert;
public Boolean fCounterSigner;
public int idxCounterSigner;
public int cStores;
public IntPtr rghStores;
public int cPropSheetPages;
public IntPtr rgPropSheetPages;
public int nStartPage;
}
private void MySampleFunction()
{
// Get the cert
X509Certificate2 cert = new X509Certificate2(@"C:\temp\mycert.cer");
// Show the cert
CRYPTUI_VIEWCERTIFICATE_STRUCT certViewInfo = new CRYPTUI_VIEWCERTIFICATE_STRUCT();
certViewInfo.dwSize = Marshal.SizeOf(certViewInfo);
certViewInfo.pCertContext = cert.Handle;
certViewInfo.szTitle = "Certificate Info";
certViewInfo.dwFlags = CRYPTUI_DISABLE_ADDTOSTORE;
certViewInfo.nStartPage = 0;
bool fPropertiesChanged = false;
if (!CryptUIDlgViewCertificate(ref certViewInfo, ref fPropertiesChanged))
{
int error = Marshal.GetLastWin32Error();
MessageBox.Show(error.ToString());
}
}
}
}
I hope this helps.
Regards,
Alex (Alejandro Campos Magencio)
Comments
- Anonymous
February 19, 2009
Hi,Very interesting code you have. I am wanting to one, detect the card, two, have a user enter a pin, and lastly, I want to read the card user information, which I will validate via other methods.Will your sample, with some tweaking, allow me to do this?Thanks in advance for your input!Dave - Anonymous
February 19, 2009
I need to access a CTL on an IIS server using C#. I have been looking at your P/Invoke examples and I can probably do it using that. However, our customer has some concerns with using unmanaged code. I have been unable to get to the CTL using the X509 objects that I am aware of. Is there a way to access the CTL (assuming I know which store it is in and I know the CTL identifier from the SSLCtlIdentifier and SSLCtlStore values from AD/WMI). I just need to verify that the CTL contains certain roots and I can't seem to find a way to access it using C#. The tool ssldiag.exe from MS shows the contents of the CTL, but I am not sure how it is implemented. I would like to do it in C# without having to use P/Invoke if at all possible.Thanks in advance for any help you can provide. - Anonymous
February 22, 2010
I can't get this code working in VB.NET environment. I wrote such a code in VB.NET, but when I call CryptUIDlgViewCertificate() application throws an exception. I would be very thankful if you could try to do this in VB.NET and post here if it works. I could send you my code to review, but don't know your e-mail. - Anonymous
March 07, 2010
Certificate2 cert = new X509Certificate2(@"C:tempmycert.cer");X509Certificate2UI.DisplayCertificate(cert); - Anonymous
April 18, 2010
Yes, thanks. This one works well. Just need to mention, that reference to "system.security.dll" should be added in VB.NET. - Anonymous
December 05, 2010
We are trying to automate importing of contacts to Outlook (both 2003 and 2007).Basically we read the contact details from a DB or csv file and create the contact items using C# code.In a folder we also have contact's certificate files that we would like to attach to the above created contacts in code.We have a code for Outlook 2007 that uses propertyaccessor and which does the import with no reported errors. However when we open Outlook contacts manually, there are no certificates attached!Tot troubleshoot, we compared, byte by byte, the certificate that we import via code and the same certificate that is manually attached to a contact.They differ for few bytes both at the begining and at the end!It seems that Outlook adds some header and footer bytes to the attached certificate when we import it manually.If we artificially add those header and footer bytes to our certificate in code, it will be imported and shown later in Outlook just fine!However these header/footer bytes seem to be certificate related and are not the same for every certificate. Just their total number is the same.The question now is, how can we determine the process of adding these extra bytes before and after the certificate so it is always recognized by Outlook?We searched on the internet a lot in regards to this problem but so far no solution was found.I hope you can give us a clue on this? - Anonymous
December 05, 2010
Sorry, I don't know what outlook does, as I don't the product to that extent... - Anonymous
June 09, 2011
How do you display the dialog as a Modal Dialog as you can return to the main application and just keep clicking button to view certificates, not a good idea? - Anonymous
June 09, 2011
Hi Spitz,Never tried it, but does it help if you pass a valid window handle in hwndParent param of the CRYPTUI_VIEWCERTIFICATE_STRUCT struct? - Anonymous
June 09, 2011
Yes, it does!Though I worked this one out myself and only came here to update my findings lolcertViewInfo.hwndParent = this.Handle;