//**************************************************************** // // SignedXMLCerts // Retrieves X509 certificates embedded in signed XML document // // Copyright (C) 2004. Michel I. Gallant // // //***************************************************************** using System; using System.IO; using System.Xml; using System.Security.Cryptography.X509Certificates; using System.Runtime.InteropServices; //------ For Pinvoke to display certs GUI --------- public class Win32 { [DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern IntPtr CertCreateCertificateContext( uint dwCertEncodingType, byte[] pbCertEncoded, uint cbCertEncoded) ; [DllImport("crypt32.dll", CharSet=CharSet.Auto)] public static extern bool CertFreeCertificateContext( IntPtr pCertContext) ; [DllImport("cryptui.dll", SetLastError=true)] public static extern bool CryptUIDlgViewCertificate( ref PCCRYPTUI_VIEWCERTIFICATE_STRUCT pCertViewInfo, ref bool pfPropertiesChanged) ; } [StructLayout(LayoutKind.Sequential)] public struct PCCRYPTUI_VIEWCERTIFICATE_STRUCT { public uint dwSize; //required public IntPtr hwndParent; public uint dwFlags; public String szTitle; public IntPtr pCertContext; //required public IntPtr rgszPurposes; uint cPurposes; IntPtr hWVTStateData; bool fpCryptProviderDataTrustedUsage; uint idxSigner; uint idxCert; bool fCounterSigner; uint idxCounterSigner; uint cStores; IntPtr rghStores; uint cPropSheetPages; IntPtr rgPropSheetPages; public uint nStartPage; //required } public class SignedXmlCerts { public static void Main(string[] args) { if(args.Length !=1) { Console.WriteLine("Usage: SignedXmlCerts "); return; } String signedxmldoc = args[0] ; if(!File.Exists(args[0])) { Console.WriteLine("File {0} not found", args[0]); return; } //Create the XmlDocument. XmlDocument doc = new XmlDocument(); doc.Load(signedxmldoc); XmlNodeList elemList = doc.GetElementsByTagName("X509Certificate"); byte[] certBytes = null; for (int i=0; i < elemList.Count; i++) { String b64cert = elemList[i].InnerXml ; Console.WriteLine("---- X509 Certificates in xigned XML document '{0}' ----\n", signedxmldoc); try //see if the file is a valid Base64 encoded cert { certBytes = Convert.FromBase64String(b64cert) ; X509Certificate x509cert = new X509Certificate(certBytes); showCertInfo(x509cert); showCertGUI(certBytes) ; //display the native certs GUI via Pinvoke } catch(System.FormatException formexc) { Console.WriteLine(formexc.Message); } catch(System.Security.Cryptography.CryptographicException cryptb64) { Console.WriteLine(cryptb64.Message); } } } private static void showCertInfo(X509Certificate x509cert) { Console.WriteLine("\nName: " + x509cert.GetName()); Console.WriteLine("\nIssuer: " + x509cert.GetIssuerName()); Console.WriteLine("\nSerial Number: " + x509cert.GetSerialNumberString()); Console.WriteLine("\nExpiration Date: " + x509cert.GetExpirationDateString()); //Console.WriteLine("PublicKey: " + x509cert.GetPublicKeyString()); } private static void showCertGUI(byte[] x509cert) { IntPtr hCertCntxt = IntPtr.Zero; const uint X509_ASN_ENCODING = 0x00000001; const uint PKCS_7_ASN_ENCODING = 0x00010000; uint encoding = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ; hCertCntxt = Win32.CertCreateCertificateContext(encoding, x509cert, (uint)x509cert.Length); if(hCertCntxt != IntPtr.Zero){ //show certificate properties panel PCCRYPTUI_VIEWCERTIFICATE_STRUCT vcstruct = new PCCRYPTUI_VIEWCERTIFICATE_STRUCT() ; vcstruct.dwSize = (uint)Marshal.SizeOf(vcstruct); vcstruct.pCertContext = hCertCntxt; vcstruct.szTitle = "KeyPal Certificate Display"; vcstruct.nStartPage = 0; bool propschanged = false; Win32.CryptUIDlgViewCertificate(ref vcstruct, ref propschanged) ; //show the cert } //------- Clean Up ----------- if(hCertCntxt != IntPtr.Zero) Win32.CertFreeCertificateContext(hCertCntxt); } }