Exemple #1
0
 /// <summary>
 /// Extracts the public Key of an RSA key or Certificate
 /// </summary>
 /// <param name="Content">RSA or Certificate content</param>
 /// <param name="IsCert">True for Certificate, false for RSA private key</param>
 /// <returns>Public key</returns>
 public static string GetPubKey(string Content, bool IsCert)
 {
     Logger.Debug("Extracting Public key. IsCert={0}", IsCert);
     using (var IN = new KillHandle())
     {
         IN.WriteAllText(Content);
         if (IsCert)
         {
             return(Run("x509", "-in", IN.FileName, "-pubkey", "-noout"));
         }
         else
         {
             return(Run("rsa", "-in", IN.FileName, "-pubout"));
         }
     }
 }
Exemple #2
0
 /// <summary>
 /// Creates a PFX file
 /// </summary>
 /// <param name="Certificate">Main Certificate</param>
 /// <param name="PrivateKey">Private Key of Certificate</param>
 /// <param name="Parents">Parent certificates</param>
 /// <param name="Password">Password</param>
 /// <returns>PFX binary</returns>
 public static byte[] CreatePfx(string Certificate, string PrivateKey, string[] Parents, string Password)
 {
     Logger.Log("Creating PFX file.");
     using (var PfxFile = new KillHandle())
     {
         using (var CertFile = new KillHandle())
         {
             if (Parents == null)
             {
                 CertFile.WriteAllText(Certificate);
             }
             else
             {
                 CertFile.WriteAllLines(Parents.Concat(new string[] { Certificate }).ToArray());
             }
             using (var KeyFile = new KillHandle())
             {
                 KeyFile.WriteAllText(PrivateKey);
                 var args = new string[] {
                     "pkcs12",
                     "-export",
                     "-in",
                     CertFile.FileName,
                     "-inkey",
                     KeyFile.FileName,
                     "-out",
                     PfxFile.FileName,
                     "-passout",
                     $"pass:{Password}"
                 };
                 if (Parents != null && Parents.Length > 0)
                 {
                     using (var ParentFile = new KillHandle())
                     {
                         ParentFile.WriteAllLines(Parents);
                         Run(args);
                     }
                 }
                 else
                 {
                     Run(args);
                 }
             }
         }
         return(PfxFile.ReadAllBytes());
     }
 }
Exemple #3
0
        /// <summary>
        /// Generates a new Certificate
        /// </summary>
        /// <param name="RootKey">Root CA RSA Key</param>
        /// <param name="CaCert">Root CA Content</param>
        /// <param name="PrivateKey">Private RSA Key</param>
        /// <param name="HostName">HostName (often known as Common Name)</param>
        /// <param name="SAN">Alternative Host names</param>
        /// <param name="ExpirationDays">Expiration in days</param>
        /// <param name="UseSha256">Use SHA256 instead of SHA1</param>
        /// <param name="CountryCode">Two-letter ISO Country code</param>
        /// <param name="State">State</param>
        /// <param name="Town">Town</param>
        /// <param name="Organization">Company Name</param>
        /// <param name="OrganizationUnit">Department</param>
        /// <param name="EmailAddress">E-Mail address for Certificate</param>
        /// <returns>Certificate</returns>
        public static string GenerateCertificate(string RootKey, string CaCert, string PrivateKey, string HostName, string[] SAN = null, int ExpirationDays = 3650, bool UseSha256 = true, string CountryCode = "XX", string State = "Local", string Town = "Local", string Organization = "ACME", string OrganizationUnit = "ACME", string EmailAddress = "*****@*****.**")
        {
            Logger.Log("Generating Certificate");
            if (string.IsNullOrEmpty(HostName))
            {
                Logger.Error("HostName not specified");
                throw new ArgumentNullException(nameof(HostName));
            }
            if (string.IsNullOrEmpty(RootKey))
            {
                Logger.Error("RootKey not specified");
                throw new ArgumentNullException(nameof(RootKey));
            }
            if (string.IsNullOrEmpty(PrivateKey))
            {
                Logger.Error("PrivateKey not specified");
                throw new ArgumentNullException(nameof(PrivateKey));
            }
            if (ExpirationDays < 1)
            {
                Logger.Error("ExpirationDays too small");
                throw new ArgumentOutOfRangeException("ExpirationDays");
            }
            if (!Tools.IsValidIp(HostName) && !Tools.IsValidDomainName(HostName))
            {
                Logger.Error("HostName is invalid domain name or IP");
                throw new FormatException("HostName is invalid domain name or IP");
            }

            if (SAN != null && !SAN.All(m => Tools.IsValidDomainName(m) || Tools.IsValidIp(m)))
            {
                throw new FormatException("SAN contains invalid domain name or IP");
            }
            if (SAN == null || SAN.Length == 0)
            {
                SAN = new string[] { HostName };
            }

            var Params = new Dictionary <string, string>();

            Params[nameof(CountryCode)]      = CountryCode;
            Params[nameof(State)]            = State;
            Params[nameof(Town)]             = Town;
            Params[nameof(Organization)]     = Organization;
            Params[nameof(OrganizationUnit)] = OrganizationUnit;
            Params[nameof(HostName)]         = HostName;
            Params[nameof(EmailAddress)]     = EmailAddress;
            foreach (var Entry in Params)
            {
                if (string.IsNullOrEmpty(Entry.Value))
                {
                    Logger.Error("{0} not specified", Entry.Key);
                    throw new ArgumentNullException(Entry.Key);
                }
                if (Entry.Value.Contains("/") || Entry.Value.Contains("\""))
                {
                    Logger.Error("{0} has invalid characters", Entry.Key);
                    throw new FormatException($"{Entry.Key} can't have slash or quote in it.");
                }
            }
            if (CountryCode.Length != 2)
            {
                Logger.Error("CountryCode not two chars in length");
                throw new FormatException("Country code must be 2 letter code");
            }
            Logger.Debug("Arguments OK");
            string Subject = $"/C={CountryCode}/ST={State}/L={Town}/O={Organization}/OU={OrganizationUnit}/CN={HostName}/emailAddress={EmailAddress}";

            using (var KeyPropsFile = new KillHandle())
            {
                Logger.Debug("Writing Props to {0}", KeyPropsFile.FileName);
                KeyPropsFile.WriteAllLines(new string[] {
                    "[req]",
                    "req_extensions = v3_req",
                    "[v3_req]",
                    SAN != null && SAN.Length > 0 ? "subjectAltName=" + SanLine(SAN) : ""
                });
                using (var PrivateKeyFile = new KillHandle())
                {
                    Logger.Debug("Using {0} as Private Key File", PrivateKeyFile.FileName);
                    PrivateKeyFile.WriteAllText(PrivateKey);
                    using (var CaKeyFile = new KillHandle())
                    {
                        Logger.Debug("Using {0} as CA Key File", CaKeyFile.FileName);
                        CaKeyFile.WriteAllText(RootKey);
                        using (var CaCertFile = new KillHandle())
                        {
                            Logger.Debug("Using {0} as CA Cert File", CaCertFile.FileName);
                            CaCertFile.WriteAllText(CaCert);

                            //Make a proper Certificate Request
                            Logger.Debug("Making Cert Request");
                            var ExeParams = new string[]
                            {
                                "req",
                                "-new",
                                "-key",
                                PrivateKeyFile.FileName,
                                UseSha256 ? "-sha256" : "-sha1",
                                //"-nodes",
                                "-extensions",
                                "v3_req",
                                "-subj",
                                Subject
                            };
                            using (var ReqFile = new KillHandle())
                            {
                                var Req = Run(ExeParams);
                                Logger.Debug("Request:\n{0}", Req);
                                ReqFile.WriteAllText(Req);

                                //Sign the Request with the CA key
                                ExeParams = new string[]
                                {
                                    "x509",
                                    "-req",
                                    UseSha256 ? "-sha256" : "-sha1",
                                    "-extensions",
                                    "v3_req",
                                    "-extfile",
                                    KeyPropsFile.FileName,
                                    "-days",
                                    ExpirationDays.ToString(),
                                    "-in",
                                    ReqFile.FileName,
                                    "-CA",
                                    CaCertFile.FileName,
                                    "-CAkey",
                                    CaKeyFile.FileName,
                                    "-CAcreateserial"
                                };
                                var Cert = Run(ExeParams);
                                Logger.Debug("Certificate:\n{0}", Cert);
                                return(Cert);
                            }
                        }
                    }
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Generates a new Root Certificate
        /// </summary>
        /// <param name="PrivateKey">Private key content</param>
        /// <param name="ExpirationDays">Expiration in days</param>
        /// <param name="UseSha256">Use SHA256 instead of SHA1</param>
        /// <param name="CountryCode">Two-letter ISO Country code</param>
        /// <param name="State">State</param>
        /// <param name="Town">Town</param>
        /// <param name="Organization">Company Name</param>
        /// <param name="OrganizationUnit">Department</param>
        /// <param name="CommonName">Display Name for Certificate</param>
        /// <param name="EmailAddress">E-Mail address for Certificate</param>
        /// <returns>Certificate</returns>
        public static string GenerateRootCert(string PrivateKey, int ExpirationDays = 3650, bool UseSha256 = true, string CountryCode = "XX", string State = "Local", string Town = "Local", string Organization = "ACME", string OrganizationUnit = "ACME", string CommonName = "ACME Root CA", string EmailAddress = "*****@*****.**")
        {
            Logger.Log("Generating Root CA");
            if (string.IsNullOrEmpty(PrivateKey))
            {
                Logger.Error("PrivateKey not specified");
                throw new ArgumentNullException(nameof(PrivateKey));
            }
            if (ExpirationDays < 1)
            {
                Logger.Error("ExpirationDays too small");
                throw new ArgumentOutOfRangeException("ExpirationDays");
            }

            var Params = new Dictionary <string, string>();

            Params[nameof(CountryCode)]      = CountryCode;
            Params[nameof(State)]            = State;
            Params[nameof(Town)]             = Town;
            Params[nameof(Organization)]     = Organization;
            Params[nameof(OrganizationUnit)] = OrganizationUnit;
            Params[nameof(CommonName)]       = CommonName;
            Params[nameof(EmailAddress)]     = EmailAddress;
            foreach (var Entry in Params)
            {
                if (string.IsNullOrEmpty(Entry.Value))
                {
                    Logger.Error("{0} not specified", Entry.Key);
                    throw new ArgumentNullException(Entry.Key);
                }
                if (Entry.Value.Contains("/") || Entry.Value.Contains("\""))
                {
                    Logger.Error("{0} has invalid characters", Entry.Key);
                    throw new FormatException($"{Entry.Key} can't have slash or quote in it.");
                }
            }
            if (CountryCode.Length != 2)
            {
                Logger.Error("CountryCode not two chars in length");
                throw new FormatException("Country code must be 2 letter code");
            }
            Logger.Debug("Arguments OK");
            string Subject = $"/C={CountryCode}/ST={State}/L={Town}/O={Organization}/OU={OrganizationUnit}/CN={CommonName}/emailAddress={EmailAddress}";

            using (var TempKeyFile = new KillHandle())
            {
                Logger.Debug("Using {0} as temporary CA file", TempKeyFile.FileName);
                TempKeyFile.WriteAllText(PrivateKey);

                var RunParams = new string[]
                {
                    "req",
                    "-new",
                    "-x509",
                    //"-nodes",
                    UseSha256 ? "-sha256" : "-sha1",
                    "-key",
                    TempKeyFile.FileName,
                    "-days",
                    ExpirationDays.ToString(),
                    "-subj",
                    Subject,
                    "-extensions",
                    "v3_ca"
                };
                var CACert = Run(RunParams);
                Logger.Debug("CA Cert:\n{0},", CACert);
                return(CACert);
            }
        }