Interface KeyAndCertificateFactory

All Known Implementing Classes:
BCKeyAndCertificateFactory

public interface KeyAndCertificateFactory
Author:
jamesdbloom
  • Field Details

    • DEFAULT_KEY_GENERATION_AND_SIGNING_ALGORITHM

      static final AsymmetricKeyPairAlgorithm DEFAULT_KEY_GENERATION_AND_SIGNING_ALGORITHM
      default key pair generation and signing algorithm
    • CERTIFICATE_VALIDITY_YEARS

      static final long CERTIFICATE_VALIDITY_YEARS
      Number of years the generated Certificate Authority remains valid. The generated CA is the trust anchor users pin into their trust stores, so it needs to outlive a typical test/CI lifetime rather than expiring after a single year and silently breaking pinned-CA deployments. Ten years is long enough to avoid surprise expiry while staying well below the X.509 ceiling that older clients (e.g. Apple iOS 8, issue #6) reject.

      This governs the CA only. The short-lived leaf (server) certificate has its own, much shorter validity — see LEAF_CERTIFICATE_VALIDITY_DAYS_DEFAULT. It also governs the HTTP/3 legacy echo-mode self-signed certificate, which is simultaneously trust anchor and server cert and so must keep the long CA-style life (it has no renewal loop behind it).

      See Also:
    • LEAF_CERTIFICATE_VALIDITY_DAYS_DEFAULT

      static final long LEAF_CERTIFICATE_VALIDITY_DAYS_DEFAULT
      Default number of days the auto-generated leaf (server) certificate remains valid: 397.

      The operative constraint is Apple's 825-day maximum for TLS server certificates (iOS 13 / macOS 10.15, support.apple.com/en-us/103769), which the previous 3650-day (10-year) leaf blew straight through — the likely cause of handshake failures on Apple platforms (issue #2531). That 825-day cap has no carve-out for user-added roots. (Apple's better-known 398-day ATS limit does not apply here: it explicitly exempts certificates issued from user-added or administrator-added roots, which is exactly MockServer's dynamically generated CA — so the 398/ATS reasoning cited by the reporter is not the rule that bites.) 397 days sits comfortably inside the 825-day cap and inside the CA/Browser Forum's tightening trend, while the Wave 1 proactive renewal (leaf regenerated at RENEWAL_ELAPSED_FRACTION of validity elapsed, ~318 days here) keeps a long-running server from ever serving an expired leaf. Override via mockserver.sslCertificateLeafValidityInDays to restore the old long-lived behaviour.

      See Also:
    • LEAF_CERTIFICATE_VALIDITY_DAYS_MIN

      static final long LEAF_CERTIFICATE_VALIDITY_DAYS_MIN
      Minimum honoured leaf validity, in days: 30.

      A positive override below this floor is a genuinely broken configuration, not a shorter-lived certificate. The leaf's not-before bound is back-dated 5 days (notBefore()), so a validity of 1..5 days would place notAfter at or before now — the leaf would be born already expired and checkValidity(now) would throw, failing generation outright. A validity of ~6 days would place the fresh leaf already past its 80%-elapsed renewal threshold, so it would be re-minted on every handshake — a non-progress loop. The 30-day floor clears the 5-day back-date plus a comfortable renewal margin: at 30 days the effective forward life is ~25 days and renewal fires ~19 days out. A positive value below the floor is clamped UP to it with a WARN so the operator sees their value was not honoured; a non-positive value instead falls back to LEAF_CERTIFICATE_VALIDITY_DAYS_DEFAULT (the documented "unset/invalid" behaviour).

      See Also:
    • LEAF_CERTIFICATE_VALIDITY_DAYS_MAX

      static final long LEAF_CERTIFICATE_VALIDITY_DAYS_MAX
      Maximum honoured leaf validity, in days: CERTIFICATE_VALIDITY_YEARS * 365 (3650, ten years).

      An unbounded override could push notAfter past the X.509 year-9999 ceiling (9999-12-31, new Date(253402300799000L)) — or, well before that, past the point older Apple clients accept (iOS 8, ~24 Jan 6084, issue #6) — producing an unusable certificate. A leaf can never usefully outlive the CA that signs it (CERTIFICATE_VALIDITY_YEARS years) anyway, so this cap both restores the historical long-lived (10-year) leaf exactly and keeps notAfter safely in range. A value above the cap is clamped DOWN to it with a WARN.

      See Also:
    • RENEWAL_ELAPSED_FRACTION

      static final double RENEWAL_ELAPSED_FRACTION
      Fraction of a certificate's validity window that must elapse before it is proactively renewed. Renewing at 80% elapsed keeps a comfortable safety margin for both today's 10-year certificates and the short-lived certificates a later hardening wave will introduce, so a long-running server never keeps serving an expired leaf from its cached SSL context.
      See Also:
    • ROOT_COMMON_NAME

      static final String ROOT_COMMON_NAME
      CN for CA distinguishing name
      See Also:
    • CERTIFICATE_DOMAIN

      static final String CERTIFICATE_DOMAIN
      default CN for leaf distinguishing name
      See Also:
    • ORGANISATION

      static final String ORGANISATION
      O for distinguishing name
      See Also:
    • LOCALITY

      static final String LOCALITY
      L for distinguishing name
      See Also:
    • STATE

      static final String STATE
      ST for distinguishing name
      See Also:
    • COUNTRY

      static final String COUNTRY
      C for distinguishing name
      See Also:
    • PROXY_SETUP_CA_CERTIFICATE_FILE_NAME

      static final String PROXY_SETUP_CA_CERTIFICATE_FILE_NAME
      Stable filename, under directoryToSaveDynamicSSLCertificate, that the active Certificate Authority X.509 certificate (public certificate only — never the private key) is written to so it can be pinned into client trust stores when MockServer is used as a TLS-intercepting proxy.
      See Also:
  • Method Details

    • isPastRenewalThreshold

      static boolean isPastRenewalThreshold(X509Certificate certificate, double fraction, long now)
      Parameters:
      certificate - the certificate to test (may be null)
      fraction - the proportion of the validity window that must elapse before renewal
      now - the current time in epoch milliseconds
      Returns:
      true when now is at or past notBefore + fraction * (notAfter - notBefore); false when certificate is null (nothing to renew yet)
    • certificateNeedsRenewal

      default boolean certificateNeedsRenewal()
      Returns:
      true when the in-memory self-generated leaf (or the dynamically generated CA) has passed its renewal threshold and must be regenerated before the cached TLS context is reused. Always false for user-supplied fixed certificates — those are validated (and loudly rejected on expiry) by CertificateConfigurationValidator. Defaults to false for factories that do not self-renew (so third-party/mock implementations keep working unchanged).
    • notBefore

      static Date notBefore()
      The not-before validity bound for a freshly issued certificate: the current time minus 5 days, just in case the software clock goes back due to time synchronization.

      Computed per issuance (rather than once at class load) so that certificates generated on the fly — e.g. leaf certificates minted long after the JVM started — are anchored to issuance time rather than to JVM start time.

    • notAfter

      static Date notAfter()
      The not-after validity bound for a freshly issued Certificate Authority (or the HTTP/3 echo-mode self-signed anchor), CERTIFICATE_VALIDITY_YEARS years in the future from issuance time. Anchored to now (not to notBefore()) so the full documented CA life is available from issuance regardless of the notBefore back-dating.

      The maximum possible value in the X.509 specification is 9999-12-31 23:59:59 (new Date(253402300799000L)), but Apple iOS 8 fails with a certificate expiration date greater than Mon, 24 Jan 6084 02:07:59 GMT (issue #6).

      Computed per issuance (rather than once at class load) so that on-the-fly generated certificates are anchored to issuance time rather than to JVM start time.

    • notAfter

      static Date notAfter(Date notBefore, long validityDays)
      The not-after validity bound for a freshly issued leaf (server) certificate, positioned so the total validity window (notAfter - notBefore) is exactly validityDays days.

      Anchored to the supplied notBefore (the 5-day back-dated bound) so the whole certificate lifetime — the span Apple's 825-day cap actually measures — is bounded by validityDays. With the default of 397, the effective forward validity from issuance is ~392 days, still far inside the 825-day cap.

      Parameters:
      notBefore - the leaf's not-before bound (from notBefore())
      validityDays - the total validity window in days
    • positiveSerialNumber

      static BigInteger positiveSerialNumber()
      A positive, unpredictable certificate serial number. RFC 5280 §4.1.2.2 requires the serial to be a positive integer, but new BigInteger(64, SecureRandom) draws from [0, 2^64) and so can (rarely) yield zero, which strict validators reject. Falls back to 1 in that single case, preserving full entropy for every other draw.
    • buildAndSaveCertificateAuthorityPrivateKeyAndX509Certificate

      void buildAndSaveCertificateAuthorityPrivateKeyAndX509Certificate()
    • buildAndSavePrivateKeyAndX509Certificate

      void buildAndSavePrivateKeyAndX509Certificate()
    • certificateNotYetCreated

      boolean certificateNotYetCreated()
    • privateKey

      PrivateKey privateKey()
    • x509Certificate

      X509Certificate x509Certificate()
    • certificateAuthorityX509Certificate

      X509Certificate certificateAuthorityX509Certificate()
    • certificateChain

      List<X509Certificate> certificateChain()
    • writeCertificateAuthorityToDisk

      default String writeCertificateAuthorityToDisk()
      Materialise the active Certificate Authority X.509 certificate (the baked-in public CA, a custom supplied CA, or the dynamically generated CA, whichever is in effect) to <directoryToSaveDynamicSSLCertificate>/"mockserver-ca.pem". Only the public certificate is written, never the private key.

      This default implementation is self-contained (no BouncyCastle dependency): it PEM-encodes the DER bytes of certificateAuthorityX509Certificate() and writes them atomically, using the directory from the global ConfigurationProperties.directoryToSaveDynamicSSLCertificate(). Implementations that hold their own Configuration (e.g. the BouncyCastle factory) override this to honour their instance-scoped directory.

      Returns:
      the absolute path of the written CA certificate PEM file
    • writeCertificateAuthorityPem

      static String writeCertificateAuthorityPem(X509Certificate caCertificate, String directory)
      PEM-encode the public certificate (never a private key) and write it atomically to <directory>/"mockserver-ca.pem" — written to a sibling temp file then moved into place (ATOMIC_MOVE where supported) so a concurrent reader never observes a truncated/empty file.
      Parameters:
      caCertificate - the public CA certificate to write
      directory - the directory to write the "mockserver-ca.pem" file into
      Returns:
      the absolute path of the written CA certificate PEM file