/// <summary>
        /// Create new certificate that is signed with private key from signing certificate that resides
        /// in Windows certificate store on local machine in intermediate certificate authorities.
        /// The private key does NOT have to be exportable.
        /// </summary>
        /// <param name="subject"></param>
        /// <param name="publicKeyBase64DerEncoded"></param>
        /// <param name="signingCertificate"></param>
        /// <returns>Freshly created certificate in PEM format</returns>
        public string CreateCertificate(DistinguishedName subject, string publicKeyBase64DerEncoded, X509Certificate2 signingCertificate)
        {
            var definition = new CertificateDefinition
            {
                Subject            = ToX509Name(subject),
                SubjectAltNames    = ToSans(subject.SubjectAltNames),
                PublicKey          = ToPublicKey(publicKeyBase64DerEncoded),
                SigningCertificate = signingCertificate
            };

            X509Certificate certificate = CreateCertificate(definition);

            return(ToPem(certificate));
        }
        public X509Certificate CreateCertificate(CertificateDefinition definition)
        {
            var randomGenerator = new CryptoApiRandomGenerator();

            BigInteger serialNumber = CreateSerialNumber(randomGenerator);


            if (definition.SigningCertificate == null)
            {
                throw new CertificateIssuerException("Cannot create certificate without signing certificate (null).");
            }

            (AsymmetricCipherKeyPair caKeyPair, X509Name issuer) = GetSigningKeyPair(definition.SigningCertificate);

            var publicKeyForNewCert = PublicKeyFactory.CreateKey(definition.PublicKey);

            var certGen = new X509V3CertificateGenerator();

            certGen.SetSerialNumber(serialNumber);
            certGen.SetIssuerDN(issuer);
            certGen.SetSubjectDN(definition.Subject);
            certGen.SetPublicKey(publicKeyForNewCert);

            var now = DateTime.Now;

            certGen.SetNotBefore(now.Subtract(new TimeSpan(0, 0, 10, 0))); // start 10 min before now

            // add max 2 weeks from now but not more then L2 expiration date
            var certExpirationDate         = now.Add(definition.ExpireIn);
            var signingCertificateNotAfter = definition.SigningCertificate.NotAfter;

            if (signingCertificateNotAfter < now)
            {
                throw new CertificateIssuerException(
                          "Cannot create derived certificate because signing certificate already expired. Signing certificate subject name: " +
                          definition.SigningCertificate?.SubjectName.Name);
            }

            if (certExpirationDate > signingCertificateNotAfter)
            {
                certExpirationDate = signingCertificateNotAfter;
            }

            certGen.SetNotAfter(certExpirationDate);


            // certGen.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));

            AddExtensionSubjectKeyIdentifier(certGen, publicKeyForNewCert);

            AddExtensionAuthorityKeyIdentifier(certGen, caKeyPair);

            AddExtensionSubjectAltNames(certGen, definition.SubjectAltNames);

            // var s = @"file:////my-CA.com/CertEnroll/my-CA.com_my-Dev%20L2%20CA.crt";
            // AddExtensionAuthorityInfo(certGen, s);

            // string certificateTemplateExtension = "IPSECIntermediateOffline";
            // AddExtensionCertificateTemplateName(certGen, certificateTemplateExtension);

            // var crl = @"file:////my-CA.com/CertEnroll/my-Dev%20L2%20CA.crl";
            // AddExtensionCrlDistributionPoints(certGen, crl);

            // other supported algorithms:

            /* SHA1withECDSA
             * SHA224withECDSA
             * SHA256withECDSA
             * SHA384withECDSA
             * SHA512withECDSA
             * NONEwithECDSA
             */
            const string algorithm = "SHA256WITHECDSA";

            // This is the most interesting part where we use our custom signature factory that utilizes
            // the custom private key PksEcPrivateKey
            ISignatureFactory signatureFactory =
                new PksAsn1SignatureFactory(algorithm, caKeyPair.Private, new SecureRandom(randomGenerator));

            X509Certificate cert = certGen.Generate(signatureFactory);

            return(cert);
        }