/// <summary>
        /// Creates a certificate signing request from an
        /// existing certificate with a private key.
        /// </summary>
        public static byte[] CreateSigningRequest(
            X509Certificate2 certificate,
            IList <String> domainNames = null
            )
        {
            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }
            using (var cfrg = new CertificateFactoryRandomGenerator())
            {
                SecureRandom random = new SecureRandom(cfrg);

                // try to get signing/private key from certificate passed in
                AsymmetricKeyParameter signingKey = X509Utils.GetPrivateKeyParameter(certificate);
                RsaKeyParameters       publicKey  = X509Utils.GetPublicKeyParameter(certificate);

                ISignatureFactory signatureFactory =
                    new Asn1SignatureFactory(X509Utils.GetRSAHashAlgorithm(X509Defaults.HashAlgorithmName), signingKey, random);

                Asn1Set attributes = null;
                var     san        = X509Extensions.FindExtension <X509SubjectAltNameExtension>(certificate);
                X509SubjectAltNameExtension alternateName = new X509SubjectAltNameExtension(san, san.Critical);

                string applicationUri = null;
                domainNames = domainNames ?? new List <String>();
                if (alternateName != null)
                {
                    if (alternateName.Uris.Count > 0)
                    {
                        applicationUri = alternateName.Uris[0];
                    }
                    foreach (var name in alternateName.DomainNames)
                    {
                        if (!domainNames.Any(s => s.Equals(name, StringComparison.OrdinalIgnoreCase)))
                        {
                            domainNames.Add(name);
                        }
                    }
                    foreach (var ipAddress in alternateName.IPAddresses)
                    {
                        if (!domainNames.Any(s => s.Equals(ipAddress, StringComparison.OrdinalIgnoreCase)))
                        {
                            domainNames.Add(ipAddress);
                        }
                    }
                }

                // build CSR extensions
                var generalNames = new List <GeneralName>();

                if (applicationUri != null)
                {
                    generalNames.Add(new GeneralName(GeneralName.UniformResourceIdentifier, applicationUri));
                }

                if (domainNames.Count > 0)
                {
                    generalNames.AddRange(BouncyCastle.X509Extensions.CreateSubjectAlternateNameDomains(domainNames));
                }

                if (generalNames.Count > 0)
                {
                    IList oids   = new ArrayList();
                    IList values = new ArrayList();
                    oids.Add(Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectAlternativeName);
                    values.Add(new Org.BouncyCastle.Asn1.X509.X509Extension(false,
                                                                            new DerOctetString(new GeneralNames(generalNames.ToArray()).GetDerEncoded())));
                    var attribute = new Org.BouncyCastle.Asn1.Pkcs.AttributePkcs(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.Pkcs9AtExtensionRequest,
                                                                                 new DerSet(new Org.BouncyCastle.Asn1.X509.X509Extensions(oids, values)));
                    attributes = new DerSet(attribute);
                }

                var pkcs10CertificationRequest = new Pkcs10CertificationRequest(
                    signatureFactory,
                    new CertificateFactoryX509Name(false, certificate.Subject),
                    publicKey,
                    attributes);

                return(pkcs10CertificationRequest.GetEncoded());
            }
        }
        /// <summary>
        /// Create the extensions.
        /// </summary>
        /// <param name="cg">The cert generator.</param>
        /// <param name="subjectPublicKey">The public key to use for the extensions.</param>
        private void CreateExtensions(X509V3CertificateGenerator cg, AsymmetricKeyParameter subjectPublicKey)
        {
            if (X509Extensions.FindExtension <X509SubjectKeyIdentifierExtension>(m_extensions) == null)
            {
                // Subject key identifier
                cg.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectKeyIdentifier.Id, false,
                                new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(subjectPublicKey)));
            }

            // Basic constraints
            BasicConstraints basicConstraints = new BasicConstraints(m_isCA);

            if (m_isCA && m_pathLengthConstraint >= 0)
            {
                basicConstraints = new BasicConstraints(m_pathLengthConstraint);
            }
            else if (!m_isCA && IssuerCAKeyCert == null)
            {   // self-signed
                basicConstraints = new BasicConstraints(0);
            }

            if (X509Extensions.FindExtension <X509BasicConstraintsExtension>(m_extensions) == null)
            {
                cg.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.BasicConstraints.Id, true, basicConstraints);
            }

            // Authority Key identifier references the issuer cert or itself when self signed
            AsymmetricKeyParameter issuerPublicKey;
            BigInteger             issuerSerialNumber;

            if (IssuerCAKeyCert != null)
            {
                issuerPublicKey    = X509Utils.GetPublicKeyParameter(IssuerCAKeyCert);
                issuerSerialNumber = X509Utils.GetSerialNumber(IssuerCAKeyCert);
            }
            else
            {
                issuerPublicKey    = subjectPublicKey;
                issuerSerialNumber = new BigInteger(1, m_serialNumber.Reverse().ToArray());
            }

            // Authority Key Identifier
            if (X509Extensions.FindExtension <X509AuthorityKeyIdentifierExtension>(m_extensions) == null)
            {
                cg.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.AuthorityKeyIdentifier.Id, false,
                                new AuthorityKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(issuerPublicKey),
                                                           new GeneralNames(new GeneralName(m_issuerIssuerAKI)), issuerSerialNumber));
            }

            if (!m_isCA)
            {
                // Key usage
                var keyUsage = KeyUsage.DataEncipherment | KeyUsage.DigitalSignature |
                               KeyUsage.NonRepudiation | KeyUsage.KeyEncipherment;
                if (IssuerCAKeyCert == null)
                {   // only self signed certs need KeyCertSign flag.
                    keyUsage |= KeyUsage.KeyCertSign;
                }

                if (X509Extensions.FindExtension <X509KeyUsageExtension>(m_extensions) == null)
                {
                    cg.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.KeyUsage, true,
                                    new KeyUsage(keyUsage));
                }

                // Extended Key usage
                if (X509Extensions.FindExtension <X509EnhancedKeyUsageExtension>(m_extensions) == null)
                {
                    cg.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.ExtendedKeyUsage, true,
                                    new ExtendedKeyUsage(new List <DerObjectIdentifier>()
                    {
                        new DerObjectIdentifier(Oids.ServerAuthentication), // server auth
                        new DerObjectIdentifier(Oids.ClientAuthentication), // client auth
                    }));
                }
            }
            else
            {
                if (X509Extensions.FindExtension <X509KeyUsageExtension>(m_extensions) == null)
                {
                    // Key usage CA
                    cg.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.KeyUsage, true,
                                    new KeyUsage(KeyUsage.CrlSign | KeyUsage.DigitalSignature | KeyUsage.KeyCertSign));
                }
            }

            foreach (var extension in m_extensions)
            {
                cg.AddExtension(extension.Oid.Value, extension.Critical, Asn1Object.FromByteArray(extension.RawData));
            }
        }
Example #3
0
        /// <summary>
        /// Create the X509 extensions to build the certificate.
        /// </summary>
        /// <param name="request">A certificate request.</param>
        /// <param name="forECDsa">If the certificate is for ECDsa, not RSA.</param>
        private void CreateX509Extensions(CertificateRequest request, bool forECDsa)
        {
            // Basic Constraints
            X509BasicConstraintsExtension bc = GetBasicContraints();

            request.CertificateExtensions.Add(bc);

            // Subject Key Identifier
            var ski = new X509SubjectKeyIdentifierExtension(
                request.PublicKey,
                X509SubjectKeyIdentifierHashAlgorithm.Sha1,
                false);

            request.CertificateExtensions.Add(ski);

            // Authority Key Identifier
            X509Extension authorityKeyIdentifier = IssuerCAKeyCert != null
                ? X509Extensions.BuildAuthorityKeyIdentifier(IssuerCAKeyCert)
                : new X509AuthorityKeyIdentifierExtension(
                ski.SubjectKeyIdentifier.FromHexString(),
                SubjectName,
                m_serialNumber
                );

            request.CertificateExtensions.Add(authorityKeyIdentifier);

            X509KeyUsageFlags keyUsageFlags;

            if (m_isCA)
            {
                keyUsageFlags = X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyCertSign | X509KeyUsageFlags.CrlSign;
            }
            else
            {
                if (forECDsa)
                {
                    // Key Usage for ECDsa
                    keyUsageFlags = X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation
                                    | X509KeyUsageFlags.KeyAgreement;
                }
                else
                {
                    // Key usage for RSA
                    keyUsageFlags = X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment
                                    | X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation;
                }
                if (IssuerCAKeyCert == null)
                {
                    // self signed case
                    keyUsageFlags |= X509KeyUsageFlags.KeyCertSign;
                }
            }

            request.CertificateExtensions.Add(
                new X509KeyUsageExtension(
                    keyUsageFlags,
                    true));

            if (!m_isCA)
            {
                // Enhanced key usage
                request.CertificateExtensions.Add(
                    new X509EnhancedKeyUsageExtension(
                        new OidCollection {
                    new Oid(Oids.ServerAuthentication),
                    new Oid(Oids.ClientAuthentication)
                }, true));
            }

            foreach (var extension in m_extensions)
            {
                request.CertificateExtensions.Add(extension);
            }
        }
 /// <summary>
 /// Construct revoked certificate with serialnumber,
 /// actual UTC time and the CRL reason.
 /// </summary>
 /// <param name="serialNumber">The serial number</param>
 /// <param name="crlReason">The reason for revocation</param>
 public RevokedCertificate(string serialNumber, CRLReason crlReason)
     : this(serialNumber)
 {
     CrlEntryExtensions.Add(X509Extensions.BuildX509CRLReason(crlReason));
 }