/* $Id: GetCertsFromPfx.cs $ * Last updated: * $Date: 2020-09-27 10:41:00 $ * $Version: 1.0.0 $ */ /******************************* LICENSE *********************************** * Copyright (C) 2019-20 David Ireland, DI Management Services Pty Limited. * All rights reserved. <www.di-mgt.com.au> <www.cryptosys.net> * The code in this module is licensed under the terms of the MIT license. * For a copy, see <http://opensource.org/licenses/MIT> **************************************************************************** */ using System; using System.Text; using System.Text.RegularExpressions; using System.Collections.Generic; using System.Linq; using System.IO; using System.Diagnostics; // Requires `CryptoSys PKI` to be installed on your system: available from <http://cryptosys.net/pki/> // Either add a reference to `diCrSysPKINet.dll` (installed by default in `C:\Program Files (x86)\CryptoSysPKI\DotNet`) // or add the source code module `CryptoSysPKI.cs` to your project. using Pki = CryptoSysPKI; namespace DIManagement.GetCertsFromPfx { class Program { static void Main(string[] args) { GetCertsFromPfx.GetCerts("user.pfx", "password"); } } class GetCertsFromPfx { /// <summary> /// Extract all X.509 certificates in a PFX/P12 file and save as separate CER files. /// </summary> /// <param name="pfxFile">Filename of PFX/P12 file.</param> /// <param name="password">Password for PFX file.</param> /// <remarks>Certificate files will be saved as the subject's common name (CN) or as certN.cer.</remarks> public static void GetCerts(string pfxFile, string password) { string newp7file; string certFile; string subjectName; int r, ncerts, i; Console.WriteLine("PFX FILE: {0}", pfxFile); // Compose output filename newp7file = Path.ChangeExtension(pfxFile, ".p7b"); Console.WriteLine("newp7file=" + newp7file); // Extract P7 chain file from PFX // Note: this .p7b file is not needed afterwards r = Pki.X509.GetP7ChainFromPFX(newp7file, pfxFile, password); Console.WriteLine("GetP7ChainFromPFX returns {0} (expecting >0)", r); Debug.Assert(r > 0, "Failed to extract P7 file from PFX"); // How many certs to extract ncerts = Pki.X509.GetCertCountInP7Chain(newp7file); Console.WriteLine("P7 file has {0} certs", ncerts); char[] invalidchars = new char[] { ' ', '<', '>', '|', ':', '*', '?', '/', '\\' }; Regex reg1 = new Regex(@"CN=([^;]+)(;|$)"); for (i = 1; i <= ncerts; i++) { // Extract X.509certificate certFile = string.Format("cert{0}.cer", i); Console.WriteLine(" Extracting certificate {0}...", certFile); r = Pki.X509.GetCertFromP7Chain(certFile, newp7file, i); Console.WriteLine(" GetCertFromP7Chain returns {0} (expecting >0)", r); Debug.Assert(r > 0, "Failed to extract certificate"); subjectName = Pki.X509.QueryCert(certFile, "subjectName"); Console.WriteLine(" SubjectName='{0}'", subjectName); // Get the Common Name (CN) Match match = reg1.Match(subjectName); if (match.Success) { // Create new cert name from CN string newcertname = match.Groups[1].Value; Console.WriteLine(" {0}", newcertname); // Remove any invalid filename chars newcertname = invalidchars.Aggregate(newcertname, (c1, c2) => c1.Replace(c2, '_')); newcertname = newcertname.Replace(".", ""); newcertname += ".cer"; // Change name of certFile if (File.Exists(newcertname)) { File.Delete(newcertname); } System.IO.File.Move(certFile, newcertname); Console.WriteLine(" File renamed as '{0}'", newcertname); } } } } }