/* $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);
}
}
}
}
}