/// <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)); } }
/// <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)); }