´╗┐using System;
using System.Text;
using System.IO;
using System.Diagnostics;
using CryptoSysPKI;

// Create keys and X.509 certificates for Alice, Bob and Carl using RSA-PSS and ECDSA signature algorithms
// similar to those given in RFC4134 " Examples of S/MIME Messages"

namespace SetupAliceBobCarl_PSS_ECDSA
{
    class SetupAliceBobCarl
    {
        static void Main(string[] args)
        {
            /* 
             // MakeTheKeys();
              - only do this once 
            */
            //GetUnencryptedPrivateKeys();
            MakeCarlRSASelfSigned();
            MakeAliceRSA();
            MakeBobRSA();
            MakeCarlECDSASelfSigned();
            MakeAliceECDSA();
        }

        static void MakeCarlRSASelfSigned()
        {
            int r;
            string certfile = "CarlRSAPssSelf.cer";
            string dn = "CN=CarlRSA;O=PSS;";
            string pubkeyfile = "CarlRSAPSS.pub";
            string prikeyfile = "CarlRSAPSS.p8e";
            // Compute SubjectKeyIdentifier from public key (see RFC5280 s4.2.1.2)
            string ski = Hash.HexFromFile(pubkeyfile, HashAlgorithm.Sha1);
            string extns = 
                "rfc822name=CarlRSA@example.com;" +
                "serialNumber=47346bc7800056bc11d36e2e9ff25020;" +
	            "subjectKeyIdentifier=" + ski + ";" +
	            "notBefore=2018-04-01;" + 
	            "notAfter=2039-12-31;";
            X509.KeyUsageOptions ku = X509.KeyUsageOptions.DigitalSignature | X509.KeyUsageOptions.KeyCertSign | X509.KeyUsageOptions.CrlSign;
            // Make new cert using RSA-PSS but using Pss_SaltLenZero so we get the same result each time
            r = X509.MakeCertSelf(certfile, prikeyfile, 0, 0, dn, extns, ku, "password", 
                SigAlgorithm.Rsa_Pss_Sha256, X509.CertOptions.Pss_SaltLenZero);
            if (0 == r)
                Console.WriteLine("Saved certificate as {0}", certfile);
            else
                Console.WriteLine("ERROR {0}: {1}: {2}", r, General.ErrorLookup(r), General.LastError());
            Debug.Assert(0 == r);

            Console.WriteLine("SHA-1 Thumb '{0}'={1}", certfile, X509.CertThumb(certfile, HashAlgorithm.Sha1));
        }

        static void MakeAliceRSA()
        {
            int r;
            string certfile = "AliceRSAPssSignByCarl.cer";
            string issuercert = "CarlRSAPssSelf.cer";
            string issuerkey = "CarlRSAPSS.p8e";
            string subjectpubkey = "AliceRSAPSS.pub";
            string dn = "CN=AliceRSA;O=PSS;";
            // Compute SubjectKeyIdentifier from public key (see RFC5280 s4.2.1.2)
            string ski = Hash.HexFromFile(subjectpubkey, HashAlgorithm.Sha1);
            string extns =
                "rfc822name=AliceRSA@example.com;" +
                "serialNumber=47346BC7800056BC11D36E2EC410B3B0;" +
                "subjectKeyIdentifier=" + ski + ";" +
                "notBefore=2018-04-01;" +
                "notAfter=2039-12-31;";
            X509.KeyUsageOptions ku = X509.KeyUsageOptions.DigitalSignature | X509.KeyUsageOptions.NonRepudiation;

            // Make new cert using RSA-PSS but using Pss_SaltLenZero so we get the same result each time
            r = X509.MakeCert(certfile, issuercert, subjectpubkey, issuerkey, 0, 0, dn, extns, ku, "password", 
                SigAlgorithm.Rsa_Pss_Sha256, X509.CertOptions.Pss_SaltLenZero | X509.CertOptions.AuthKeyId);
            if (0 == r)
                Console.WriteLine("Saved certificate as {0}", certfile);
            else
                Console.WriteLine("ERROR {0}: {1}: {2}", r, General.ErrorLookup(r), General.LastError());
            Debug.Assert(0 == r);

            Console.WriteLine("SHA-1 Thumb '{0}'={1}", certfile, X509.CertThumb(certfile, HashAlgorithm.Sha1));
            Console.WriteLine(X509.TextDumpToString(certfile, 0));
        }

        static void MakeBobRSA()
        {
            int r;
            string certfile = "BobRSAPssSignByCarl.cer";
            string issuercert = "CarlRSAPssSelf.cer";
            string issuerkey = "CarlRSAPSS.p8e";
            string subjectpubkey = "BobRSAPSS.pub";
            string dn = "CN=BobRSA-PSS;";
            // Compute SubjectKeyIdentifier from public key (see RFC5280 s4.2.1.2)
            string ski = Hash.HexFromFile(subjectpubkey, HashAlgorithm.Sha1);
            string extns =
                "rfc822name=BobRSA@example.com;" +
                "serialNumber=48346bc7800056bc11d36e2ecd5d71d0;" +
                "subjectKeyIdentifier=" + ski + ";" +
                "notBefore=2018-04-01;" +
                "notAfter=2039-12-31;";
            X509.KeyUsageOptions ku = X509.KeyUsageOptions.KeyEncipherment;

            // Make new cert using RSA-PSS but using Pss_SaltLenZero so we get the same result each time
            r = X509.MakeCert(certfile, issuercert, subjectpubkey, issuerkey, 0, 0, dn, extns, ku, "password",
                SigAlgorithm.Rsa_Pss_Sha256, X509.CertOptions.Pss_SaltLenZero | X509.CertOptions.AuthKeyId);
            if (0 == r)
                Console.WriteLine("Saved certificate as {0}", certfile);
            else
                Console.WriteLine("ERROR {0}: {1}: {2}", r, General.ErrorLookup(r), General.LastError());
            Debug.Assert(0 == r);

            Console.WriteLine("SHA-1 Thumb '{0}'={1}", certfile, X509.CertThumb(certfile, HashAlgorithm.Sha1));
        }

        static void MakeCarlECDSASelfSigned()
        {
            int r;
            string certfile = "CarlEcdsaSelf.cer";
            string dn = "CN=CarlECDSA;O=ECC;";
            string pubkeyfile = "CarlECCP256.pub";
            string prikeyfile = "CarlECCP256.p8e";
            // Compute SubjectKeyIdentifier from public key (see RFC5280 s4.2.1.2)
            string ski = Hash.HexFromFile(pubkeyfile, HashAlgorithm.Sha1);
            string extns =
                "rfc822name=CarlECDSA@example.com;" +
                "serialNumber=a8427780659491799706b6fe62f42d55;" +
                "subjectKeyIdentifier=" + ski + ";" +
                "notBefore=2018-04-01;" +
                "notAfter=2039-12-31;";
            X509.KeyUsageOptions ku = X509.KeyUsageOptions.DigitalSignature | X509.KeyUsageOptions.KeyCertSign | X509.KeyUsageOptions.CrlSign;
            // Make new cert using ECDSA but using Ecdsa_Deterministic so we get the same result each time
            r = X509.MakeCertSelf(certfile, prikeyfile, 0, 0, dn, extns, ku, "password",
                SigAlgorithm.Ecdsa_Sha256, X509.CertOptions.Ecdsa_Deterministic);
            if (0 == r)
                Console.WriteLine("Saved certificate as {0}", certfile);
            else
                Console.WriteLine("ERROR {0}: {1}: {2}", r, General.ErrorLookup(r), General.LastError());
            Debug.Assert(0 == r);

            Console.WriteLine("SHA-1 Thumb '{0}'={1}", certfile, X509.CertThumb(certfile, HashAlgorithm.Sha1));
        }

        static void MakeAliceECDSA()
        {
            int r;
            string certfile = "AliceEcdsaSignByCarl.cer";
            string issuercert = "CarlEcdsaSelf.cer";
            string issuerkey = "CarlECCP256.p8e";
            string subjectpubkey = "AliceECCP256.pub";
            string dn = "CN=AliceECDSA;O=ECC;";
            // Compute SubjectKeyIdentifier from public key (see RFC5280 s4.2.1.2)
            string ski = Hash.HexFromFile(subjectpubkey, HashAlgorithm.Sha1);
            string extns =
                "rfc822name=AliceECDSA@example.com;" +
                "serialNumber=08a6263fc85bdeae69d9311a9445c41f;" +
                "subjectKeyIdentifier=" + ski + ";" +
                "notBefore=2018-04-01;" +
                "notAfter=2039-12-31;";
            X509.KeyUsageOptions ku = X509.KeyUsageOptions.DigitalSignature | X509.KeyUsageOptions.NonRepudiation;

            // Make new cert using ECDSA but using Ecdsa_Deterministic so we get the same result each time
            r = X509.MakeCert(certfile, issuercert, subjectpubkey, issuerkey, 0, 0, dn, extns, ku, "password",
                SigAlgorithm.Ecdsa_Sha256, X509.CertOptions.Ecdsa_Deterministic | X509.CertOptions.AuthKeyId);
            if (0 == r)
                Console.WriteLine("Saved certificate as {0}", certfile);
            else
                Console.WriteLine("ERROR {0}: {1}: {2}", r, General.ErrorLookup(r), General.LastError());
            Debug.Assert(0 == r);

            Console.WriteLine("SHA-1 Thumb '{0}'={1}", certfile, X509.CertThumb(certfile, HashAlgorithm.Sha1));
            Console.WriteLine(X509.TextDumpToString(certfile, 0));
        }

        static void GetUnencryptedPrivateKeys()
        {
            string keystr, newname;
            int r;
            // For each .p8e key file, save again as an unencrypted .p8 key
            string[] rsaKeyFiles = { "AliceRSAPSS.p8e", "BobRSAPSS.p8e", "CarlRSAPSS.p8e" };
            foreach (string fname in rsaKeyFiles) {
                newname = Path.ChangeExtension(fname, ".p8");
                Console.WriteLine("{0} --> {1}", fname, newname);
                keystr = Rsa.ReadPrivateKey(fname, "password").ToString();
                Debug.Assert(keystr.Length > 0);
                r = Rsa.SavePrivateKeyInfo(newname, keystr, 0);
                if (0 == r)
                    Console.WriteLine("Saved key as {0}", newname);
                else
                    Console.WriteLine("ERROR {0}: {1}: {2}", r, General.ErrorLookup(r), General.LastError());
            }
            string[] eccKeyFiles = { "AliceECCP256.p8e", "BobECCP256.p8e", "CarlECCP256.p8e" };
            foreach (string fname in eccKeyFiles) {
                newname = Path.ChangeExtension(fname, ".p8");
                Console.WriteLine("{0} --> {1}", fname, newname);
                keystr = Ecc.ReadPrivateKey(fname, "password").ToString();
                Debug.Assert(keystr.Length > 0);
                r = Ecc.SaveKey(newname, keystr, 0, 0);
                if (0 == r)
                    Console.WriteLine("Saved key as {0}", newname);
                else
                    Console.WriteLine("ERROR {0}: {1}: {2}", r, General.ErrorLookup(r), General.LastError());
            }

        }
        static void MakeTheKeys()
        {   // DO ONCE
            int r;
            Console.WriteLine("Generating three 2048-bit RSA keys...");
            r = Rsa.MakeKeys("AliceRSAPSS.pub", "AliceRSAPSS.p8e", 2048, Rsa.PublicExponent.Exp_EQ_65537, 80, "password", Rsa.PbeOptions.Pbe_Pbkdf2_aes256_CBC, false);
            r = Rsa.MakeKeys("BobRSAPSS.pub", "BobRSAPSS.p8e", 2048, Rsa.PublicExponent.Exp_EQ_65537, 80, "password", Rsa.PbeOptions.Pbe_Pbkdf2_aes256_CBC, false);
            r = Rsa.MakeKeys("CarlRSAPSS.pub", "CarlRSAPSS.p8e", 2048, Rsa.PublicExponent.Exp_EQ_65537, 80, "password", Rsa.PbeOptions.Pbe_Pbkdf2_aes256_CBC, false);

            Console.WriteLine("Generating three ECC keys using P-256...");
            r = Ecc.MakeKeys("AliceECCP256.pub", "AliceECCP256.p8e", Ecc.CurveName.P_256, "password", Ecc.PbeScheme.Pbe_Pbkdf2_aes256_CBC, "", 0);
            r = Ecc.MakeKeys("BobECCP256.pub", "BobECCP256.p8e", Ecc.CurveName.P_256, "password", Ecc.PbeScheme.Pbe_Pbkdf2_aes256_CBC, "", 0);
            r = Ecc.MakeKeys("CarlECCP256.pub", "CarlECCP256.p8e", Ecc.CurveName.P_256, "password", Ecc.PbeScheme.Pbe_Pbkdf2_aes256_CBC, "", 0);
        }
    }
}