// $Id: MakeCertChain.cs $ using System; using System.Text; using System.IO; using CryptoSysPKI; // Make a chain of X.509 certificates [Carl] --> [Ian] --> [Enid] then create a PFX file. // Carl is a trusted root CA. Ian and Enid's certs are created from scratch. /******************************* LICENSE *********************************** * Copyright (C) 2019 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> **************************************************************************** */ namespace MakeCertChain { class MakeCertChain { static void Main(string[] args) { //MakeKeys(); // Only call this once. Uncomment to redo. MakeCertForIan(); MakeCertForEnid(); MakeP7(); CheckChain(); MakePFX(); } // Only call this once! static void MakeKeys() { // Create two new sets of 1024-bit RSA keys string prikeyfile, pubkeyfile; int r; prikeyfile = "IanRSA.p8e"; pubkeyfile = "IanRSA.pub"; r = Rsa.MakeKeys(pubkeyfile, prikeyfile, 1024, Rsa.PublicExponent.Exp_EQ_65537, 2000, "password", Rsa.PbeOptions.Pbe_Pbkdf2_aes128_CBC, true); Console.WriteLine("Rsa.MakeKeys returns {0}", r); prikeyfile = "EnidRSA.p8e"; pubkeyfile = "EnidRSA.pub"; r = Rsa.MakeKeys(pubkeyfile, prikeyfile, 1024, Rsa.PublicExponent.Exp_EQ_65537, 2000, "password", Rsa.PbeOptions.Pbe_Pbkdf2_aes128_CBC, true); Console.WriteLine("Rsa.MakeKeys returns {0}", r); } // Make an intermediate cert static void MakeCertForIan() { string pubkeyfile; string issuercert, issuerkey; string certname; int r; X509.KeyUsageOptions kuo = X509.KeyUsageOptions.DigitalSignature | X509.KeyUsageOptions.KeyCertSign | X509.KeyUsageOptions.CrlSign; certname = "IanRSASignedByCarl.cer"; pubkeyfile = "IanRSA.pub"; issuercert = "CarlRSASelf.cer"; issuerkey = "CarlPrivRSASign.p8e"; r = X509.MakeCert(certname, issuercert, pubkeyfile, issuerkey, 0x3002, 20, "O=Administración de certificados;CN=Ian", "notBefore=2019-01-01", kuo, "password", SigAlgorithm.Rsa_Sha256, X509.CertOptions.SetAsCA | X509.CertOptions.UTF8String); Console.WriteLine("X509.MakeCert returns {0} (expected 0)", r); if (r != 0) disp_error(r); ShowFileInfo(certname); } // Make an end-user cert static void MakeCertForEnid() { string pubkeyfile; string issuercert, issuerkey; string certname; int r; X509.KeyUsageOptions kuo = X509.KeyUsageOptions.DigitalSignature; certname = "EnidRSASignedByIan.cer"; pubkeyfile = "EnidRSA.pub"; issuercert = "IanRSASignedByCarl.cer"; issuerkey = "IanRSA.p8e"; r = X509.MakeCert(certname, issuercert, pubkeyfile, issuerkey, 0, 19, "CN=Enid", "notBefore=2019-01-02;rfc822Name=enid@example.org;serialNumber=#x02deadbeef123456", kuo, "password", SigAlgorithm.Rsa_Sha256, X509.CertOptions.UTF8String); Console.WriteLine("X509.MakeCert returns {0} (expected 0)", r); if (r != 0) disp_error(r); ShowFileInfo(certname); } static void MakeP7() { string fname = "enid.p7b"; // List of all the cert files we want to include string certlist = "EnidRSASignedByIan.cer;IanRSASignedByCarl.cer;CarlRSASelf.cer"; int r; // Use the Cms.MakeSigData method with "CertsOnly" option. inputFile and privateKey are ignored. r = Cms.MakeSigData(fname, "", certlist, "", Cms.Options.CertsOnly); Console.WriteLine("Cms.MakeSigData returns {0} (expected 0)", r); if (r != 0) disp_error(r); ShowFileInfo(fname); } static void CheckChain() { string fname = "enid.p7b"; string trustedCert = "CarlRSASelf.cer"; int r; r = X509.ValidatePath(fname, trustedCert, false); Console.WriteLine("X509.ValidatePath(.p7b) returns {0} (expected 0)", r); if (r != 0) disp_error(r); string certlist = "EnidRSASignedByIan.cer;IanRSASignedByCarl.cer;CarlRSASelf.cer"; r = X509.ValidatePath(certlist, trustedCert, false); Console.WriteLine("X509.ValidatePath(list) returns {0} (expected 0)", r); if (r != 0) disp_error(r); } static void MakePFX() { string pfxname = "enid.pfx"; string certlist = "EnidRSASignedByIan.cer;IanRSASignedByCarl.cer;CarlRSASelf.cer"; string prikeyfile = "EnidRSA.p8e"; int r = Pfx.MakeFile(pfxname, certlist, prikeyfile, "password", "Enid", Pfx.Options.Default); Console.WriteLine("Pfx.MakeFile returns {0} (expected 0)", r); if (r != 0) disp_error(r); // NOTE: pfx will be different each time (encryption IVs) ShowFileInfo(pfxname); } static void ShowFileInfo(string fname) { if (File.Exists(fname)) { long flen = new System.IO.FileInfo(fname).Length; Console.WriteLine(" File '{0}': {1} bytes, SHA-1={2}", fname, flen, Hash.HexFromFile(fname, HashAlgorithm.Sha1)); } else { Console.WriteLine(" File '{0}' DOES NOT EXIST!", fname); } } //*********************** // DISPLAY ERROR DETAILS //*********************** /// <summary> /// Display details of last error given error code /// </summary> /// <param name="nErr">Error code returned</param> static void disp_error(int nErr) { string s = General.LastError(); Console.WriteLine("ERROR Returned={0}/{1}: {2}; {3}", nErr, General.ErrorCode(), General.ErrorLookup(nErr), s); } /// <summary> /// Display details of last error (no error code) /// </summary> static void disp_error() { string s = General.LastError(); int nErr = General.ErrorCode(); Console.WriteLine("ERROR {0}: {1}: {2}", nErr, General.ErrorLookup(nErr), s); } } }