private string EvaluateUrl(
     CertificateUrlTemplateBindModel model,
     string uri
     )
 {
     return(_urlEvaluator == null
         ? uri
         : (String.IsNullOrWhiteSpace(uri) ? null : _urlEvaluator.Evaluate(uri, model)));
 }
        protected X509Certificate GenerateCertificate(
            SecureRandom random,
            string algorithm,
            string subjectName,
            AsymmetricCipherKeyPair subjectKeyPair,
            BigInteger subjectSerialNumber,
            string[] subjectAlternativeNames,
            DateTime notBefore,
            DateTime notAfter,
            string issuerName,
            AsymmetricCipherKeyPair issuerKeyPair,
            KeyUsage keyUsage,
            KeyPurposeID[] usages,
            CertificateEndPoints certificateEndPoints)
        {
            var certificateGenerator = new X509V3CertificateGenerator();

            certificateGenerator.SetSerialNumber(subjectSerialNumber);

            // Key emite o certificado
            X509Name issuerDN = BuildDistinguishedName(issuerName);

            certificateGenerator.SetIssuerDN(issuerDN);

            // Nota: Pode ser omitido se for indicado o 'subject alternative name' (SAN).
            certificateGenerator.SetSubjectDN(BuildDistinguishedName(subjectName));

            // CIUDADO !!!! tempo em UTC!!!!!!
            certificateGenerator.SetNotBefore(notBefore);
            // CIUDADO !!!! tempo em UTC!!!!!!
            certificateGenerator.SetNotAfter(notAfter);

            // A chave pública do emissor é incluida no certificado..
            certificateGenerator.SetPublicKey(subjectKeyPair.Public);

            // Secção 4.2.1.1, Authority Key Identifier pode ser omitido em CA´s.
            // No nosso caso para as CA's emitidas, o KeyId será igual ao seu subjectid
            AddAuthorityKeyIdentifier(certificateGenerator, issuerKeyPair);
            AddSubjectKeyIdentifier(certificateGenerator, subjectKeyPair);

            if (certificateEndPoints != null)
            {
                CertificateUrlTemplateBindModel urlTemplateBindModel = BuildUrlTemplateBindModel(
                    subjectName,
                    subjectName,
                    issuerName,
                    new SubjectKeyIdentifier(
                        SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(subjectKeyPair.Public)),
                    new AuthorityKeyIdentifier(
                        SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(issuerKeyPair.Public)),
                    subjectSerialNumber,
                    notBefore,
                    notAfter
                    );
                certificateEndPoints.CaDistributionEndPoint = EvaluateUrl(urlTemplateBindModel,
                                                                          certificateEndPoints.CaDistributionEndPoint);
                certificateEndPoints.CrlDistributionEndPoint = EvaluateUrl(urlTemplateBindModel,
                                                                           certificateEndPoints.CrlDistributionEndPoint);
                certificateEndPoints.OcspEndPoint = EvaluateUrl(urlTemplateBindModel,
                                                                certificateEndPoints.OcspEndPoint);
            }

            // VER
            AddPolicies(certificateGenerator);

            Setup(certificateGenerator, certificateEndPoints);

            if (keyUsage != null)
            {
                AddKeyUsage(certificateGenerator, keyUsage);
            }

            if (!usages.IsNullOrEmpty())
            {
                AddExtendedKeyUsage(certificateGenerator, usages);
            }

            if (!subjectAlternativeNames.IsStringListNullOrEmpty())
            {
                AddSubjectAlternativeNames(certificateGenerator, subjectAlternativeNames);
            }

            // Assinar o certificado com a chave privada do emissor.
            return(certificateGenerator.Generate(
                       new Asn1SignatureFactory(
                           algorithm,
                           issuerKeyPair.Private
                           )));
        }