All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.karasiq.tls.x509.CertExtension.scala Maven / Gradle / Ivy

The newest version!
package com.karasiq.tls.x509

import com.karasiq.tls.TLS
import org.bouncycastle.asn1.x509._
import org.bouncycastle.asn1.{ASN1Encodable, ASN1ObjectIdentifier, DERSequence}
import org.bouncycastle.cert.X509CertificateHolder

case class CertExtension(id: ASN1ObjectIdentifier, value: ASN1Encodable, critical: Boolean = false) {
  require(id ne null)

  override def equals(obj: scala.Any): Boolean = obj match {
    case CertExtension(oid, _, _) ⇒
      this.id == oid

    case _ ⇒
      false
  }

  override def hashCode(): Int = id.hashCode()
}

object CertExtension {
  def wrap(extensionsHolder: Extensions): Seq[CertExtension] = {
    val critical = extensionsHolder.getCriticalExtensionOIDs.map { oid ⇒
      CertExtension(oid, extensionsHolder.getExtension(oid).getParsedValue, critical = true)
    }

    val extensions = extensionsHolder.getNonCriticalExtensionOIDs.map { oid ⇒
      CertExtension(oid, extensionsHolder.getExtension(oid).getParsedValue, critical = false)
    }
    critical.toSeq ++ extensions.toSeq
  }

  def extensionsOf(cert: TLS.Certificate): Seq[CertExtension] = {
    wrap(new X509CertificateHolder(cert).getExtensions)
  }

  def basicConstraints(ca: Boolean, pathLenConstraint: Int = 0): CertExtension = {
    if (ca && pathLenConstraint > 0)
      CertExtension(Extension.basicConstraints, new BasicConstraints(pathLenConstraint), critical = true)
    else
      CertExtension(Extension.basicConstraints, new BasicConstraints(ca), critical = true)
  }

  def keyUsage(usage: Int): CertExtension = {
    CertExtension(Extension.keyUsage, new KeyUsage(usage))
  }

  def authorityKeyId(issuer: TLS.Certificate): CertExtension = {
    val utils = X509Utils.extensionUtils()
    CertExtension(Extension.authorityKeyIdentifier, utils.createAuthorityKeyIdentifier(new X509CertificateHolder(issuer)))
  }

  def subjectKeyId(key: SubjectPublicKeyInfo): CertExtension = {
    val utils = X509Utils.extensionUtils()
    CertExtension(Extension.subjectKeyIdentifier, utils.createSubjectKeyIdentifier(key))
  }

  def identifiers(key: SubjectPublicKeyInfo, issuer: Option[TLS.Certificate] = None): Set[CertExtension] = {
    Set(subjectKeyId(key)) ++ issuer.map(authorityKeyId)
  }

  def alternativeNames(otherName: Seq[String] = Nil, rfc822Name: Seq[String] = Nil, dNSName: Seq[String] = Nil, x400Address: Seq[String] = Nil, directoryName: Seq[String] = Nil, ediPartyName: Seq[String] = Nil, uniformResourceIdentifier: Seq[String] = Nil, iPAddress: Seq[String] = Nil, registeredID: Seq[String] = Nil, extensionId: ASN1ObjectIdentifier = Extension.subjectAlternativeName): CertExtension = {
    val names = Seq(
      otherName.map(new GeneralName(GeneralName.otherName, _)),
      rfc822Name.map(new GeneralName(GeneralName.rfc822Name, _)),
      dNSName.map(new GeneralName(GeneralName.dNSName, _)),
      x400Address.map(new GeneralName(GeneralName.x400Address, _)),
      directoryName.map(new GeneralName(GeneralName.directoryName, _)),
      ediPartyName.map(new GeneralName(GeneralName.ediPartyName, _)),
      uniformResourceIdentifier.map(new GeneralName(GeneralName.uniformResourceIdentifier, _)),
      iPAddress.map(new GeneralName(GeneralName.iPAddress, _)),
      registeredID.map(new GeneralName(GeneralName.registeredID, _))
    )
    CertExtension(extensionId, new GeneralNames(names.flatten.toArray))
  }

  def extendedKeyUsage(keyUsages: KeyPurposeId*): CertExtension = {
    CertExtension(Extension.extendedKeyUsage, new ExtendedKeyUsage(keyUsages.toArray))
  }

  def crlDistributionUrls(issuer: TLS.Certificate, urls: String*): CertExtension = {
    val names = new GeneralNames(urls.map(url ⇒ new GeneralName(GeneralName.uniformResourceIdentifier, url)).toArray)
    val point = new DistributionPoint(new DistributionPointName(names), new ReasonFlags(ReasonFlags.keyCompromise | ReasonFlags.cACompromise | ReasonFlags.certificateHold), new GeneralNames(new GeneralName(issuer.getSubject)))
    CertExtension(Extension.cRLDistributionPoints, new CRLDistPoint(Array(point)))
  }

  def authorityInfoAccess(certUrl: String, ocspUrl: String): CertExtension = {
    val url = new AccessDescription(AccessDescription.id_ad_caIssuers, new GeneralName(GeneralName.uniformResourceIdentifier, certUrl))
    val ocsp = new AccessDescription(AccessDescription.id_ad_ocsp, new GeneralName(GeneralName.uniformResourceIdentifier, ocspUrl))
    val sequence = new DERSequence(Array[ASN1Encodable](url, ocsp))
    val access = AuthorityInformationAccess.getInstance(sequence)
    CertExtension(Extension.authorityInfoAccess, access)
  }

  def defaultExtensions(): Set[CertExtension] = {
    Set(basicConstraints(ca = false), keyUsage(KeyUsage.keyEncipherment | KeyUsage.digitalSignature | KeyUsage.nonRepudiation), extendedKeyUsage(KeyPurposeId.anyExtendedKeyUsage))
  }

  def certificationAuthorityExtensions(pathLenConstraint: Int = 0): Set[CertExtension] = {
    Set(basicConstraints(ca = true, pathLenConstraint), keyUsage(KeyUsage.cRLSign | KeyUsage.keyCertSign | KeyUsage.digitalSignature | KeyUsage.nonRepudiation))
  }
}






















© 2015 - 2024 Weber Informatics LLC | Privacy Policy