Interface KeyAndCertificateFactory
- All Known Implementing Classes:
BCKeyAndCertificateFactory
- Author:
- jamesdbloom
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final Stringdefault CN for leaf distinguishing namestatic final longNumber of years the generated Certificate Authority remains valid.static final StringC for distinguishing namestatic final AsymmetricKeyPairAlgorithmdefault key pair generation and signing algorithmstatic final longDefault number of days the auto-generated leaf (server) certificate remains valid: 397.static final longMaximum honoured leaf validity, in days:CERTIFICATE_VALIDITY_YEARS * 365(3650, ten years).static final longMinimum honoured leaf validity, in days: 30.static final StringL for distinguishing namestatic final StringO for distinguishing namestatic final StringStable filename, underdirectoryToSaveDynamicSSLCertificate, 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.static final doubleFraction of a certificate's validity window that must elapse before it is proactively renewed.static final StringCN for CA distinguishing namestatic final StringST for distinguishing name -
Method Summary
Modifier and TypeMethodDescriptionvoidvoiddefault booleanbooleanstatic booleanisPastRenewalThreshold(X509Certificate certificate, double fraction, long now) static DatenotAfter()The not-after validity bound for a freshly issued Certificate Authority (or the HTTP/3 echo-mode self-signed anchor),CERTIFICATE_VALIDITY_YEARSyears in the future from issuance time.static DateThe not-after validity bound for a freshly issued leaf (server) certificate, positioned so the total validity window (notAfter - notBefore) is exactlyvalidityDaysdays.static DateThe 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.static BigIntegerA positive, unpredictable certificate serial number.static StringwriteCertificateAuthorityPem(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.default StringMaterialise 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".
-
Field Details
-
DEFAULT_KEY_GENERATION_AND_SIGNING_ALGORITHM
default key pair generation and signing algorithm -
CERTIFICATE_VALIDITY_YEARS
static final long CERTIFICATE_VALIDITY_YEARSNumber 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_DEFAULTDefault 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_FRACTIONof validity elapsed, ~318 days here) keeps a long-running server from ever serving an expired leaf. Override viamockserver.sslCertificateLeafValidityInDaysto restore the old long-lived behaviour.- See Also:
-
LEAF_CERTIFICATE_VALIDITY_DAYS_MIN
static final long LEAF_CERTIFICATE_VALIDITY_DAYS_MINMinimum 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 placenotAfterat or beforenow— the leaf would be born already expired andcheckValidity(now)would throw, failing generation outright. A validity of ~6 days would place the fresh leaf already past its80%-elapsedrenewal 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 toLEAF_CERTIFICATE_VALIDITY_DAYS_DEFAULT(the documented "unset/invalid" behaviour).- See Also:
-
LEAF_CERTIFICATE_VALIDITY_DAYS_MAX
static final long LEAF_CERTIFICATE_VALIDITY_DAYS_MAXMaximum honoured leaf validity, in days:CERTIFICATE_VALIDITY_YEARS * 365(3650, ten years).An unbounded override could push
notAfterpast 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_YEARSyears) anyway, so this cap both restores the historical long-lived (10-year) leaf exactly and keepsnotAftersafely 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_FRACTIONFraction 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
CN for CA distinguishing name- See Also:
-
CERTIFICATE_DOMAIN
default CN for leaf distinguishing name- See Also:
-
ORGANISATION
O for distinguishing name- See Also:
-
LOCALITY
L for distinguishing name- See Also:
-
STATE
ST for distinguishing name- See Also:
-
COUNTRY
C for distinguishing name- See Also:
-
PROXY_SETUP_CA_CERTIFICATE_FILE_NAME
Stable filename, underdirectoryToSaveDynamicSSLCertificate, 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
- Parameters:
certificate- the certificate to test (may be null)fraction- the proportion of the validity window that must elapse before renewalnow- the current time in epoch milliseconds- Returns:
- true when
nowis at or pastnotBefore + fraction * (notAfter - notBefore); false whencertificateis 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
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
The not-after validity bound for a freshly issued Certificate Authority (or the HTTP/3 echo-mode self-signed anchor),CERTIFICATE_VALIDITY_YEARSyears in the future from issuance time. Anchored tonow(not tonotBefore()) 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
The not-after validity bound for a freshly issued leaf (server) certificate, positioned so the total validity window (notAfter - notBefore) is exactlyvalidityDaysdays.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 byvalidityDays. With thedefault 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 (fromnotBefore())validityDays- the total validity window in days
-
positiveSerialNumber
A positive, unpredictable certificate serial number. RFC 5280 §4.1.2.2 requires the serial to be a positive integer, butnew BigInteger(64, SecureRandom)draws from[0, 2^64)and so can (rarely) yield zero, which strict validators reject. Falls back to1in 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
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 globalConfigurationProperties.directoryToSaveDynamicSSLCertificate(). Implementations that hold their ownConfiguration(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
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 writedirectory- the directory to write the "mockserver-ca.pem" file into- Returns:
- the absolute path of the written CA certificate PEM file
-