Search code examples
javacertificatecode-signingtrusted-timestamp

How to check if Java Web Start app will continue working after certificate expires


We signed our Java Web Start app with a code signing certificate from CA (Thawte). The signature is timestamped (we pass the -tca https://timestamp.geotrust.com/tsa argument to the jarsigner tool) to be valid after the certificate expires. At present, when the certificate is valid, the app works perfect. But when we try to change the local time forward to simulate expiration of the certificate then the app won't start. We get following exception:

java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Responder's certificate not within the validity period
at com.sun.deploy.security.RevocationChecker.checkOCSP(Unknown Source)
at com.sun.deploy.security.RevocationChecker.check(Unknown Source)
at com.sun.deploy.security.TrustDecider.checkRevocationStatus(Unknown Source)
at com.sun.deploy.security.TrustDecider.getValidationState(Unknown Source)
at com.sun.deploy.security.TrustDecider.validateChain(Unknown Source)
at com.sun.deploy.security.TrustDecider.isAllPermissionGrantedInt(Unknown Source)
at com.sun.deploy.security.TrustDecider.isAllPermissionGranted(Unknown Source)
at com.sun.javaws.security.AppPolicy.grantUnrestrictedAccess(Unknown Source)
at com.sun.javaws.security.JNLPSignedResourcesHelper.checkSignedResourcesHelper(Unknown Source)
at com.sun.javaws.security.JNLPSignedResourcesHelper.checkSignedResources(Unknown Source)
at com.sun.javaws.Launcher.prepareResources(Unknown Source)
at com.sun.javaws.Launcher.prepareAllResources(Unknown Source)
at com.sun.javaws.Launcher.prepareToLaunch(Unknown Source)
at com.sun.javaws.Launcher.prepareToLaunch(Unknown Source)
at com.sun.javaws.Launcher.launch(Unknown Source)
at com.sun.javaws.Main.launchApp(Unknown Source)
at com.sun.javaws.Main.continueInSecureThread(Unknown Source)
at com.sun.javaws.Main.access$000(Unknown Source)
at com.sun.javaws.Main$1.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.security.cert.CertPathValidatorException: Responder's certificate not within the validity period
at sun.security.provider.certpath.OCSPResponse.verify(Unknown Source)
at sun.security.provider.certpath.OCSP.check(Unknown Source)
at sun.security.provider.certpath.OCSP.check(Unknown Source)
at sun.security.provider.certpath.OCSP.check(Unknown Source)
at com.sun.deploy.security.RevocationChecker$2.run(Unknown Source)
at com.sun.deploy.security.RevocationChecker$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.deploy.security.RevocationChecker.doPrivilegedOCSPCheck(Unknown Source)
... 20 more
Caused by: java.security.cert.CertificateExpiredException: NotAfter: Thu Dec 17 00:59:59 CET 2015
at sun.security.x509.CertificateValidity.valid(Unknown Source)
at sun.security.x509.X509CertImpl.checkValidity(Unknown Source)
... 28 more

The certificate is valid from 09.10.2015 to 08.11.2017.

We tried to verify the signed JAR with jarsigner tool. All files seem to have a timestamp:

      [entry was signed on 9.10.15 16:42]
  X.509, CN="GEOVAP, spol. s.r.o.", OU=Software, O="GEOVAP, spol. s.r.o.", L=Pardubice, ST=Czech Republic, C=CZ
  [certificate is valid from 9.10.15 2:00 to 8.11.17 0:59]
  X.509, CN=thawte SHA256 Code Signing CA, O="thawte, Inc.", C=US
  [certificate is valid from 10.12.13 1:00 to 10.12.23 0:59]

So the jarsigner output seems to be correct. Could somebody confirm that this really means that the signature has timestamp?

We noticed that if we change the local time only few (3) days forward then the app works. But if we change it more (week) then we get the exception. Does the CA server check if client local time is valid? If it does how we can simulate the certificate expiration? Thank you.


Solution

  • Reason and workaround

    Your exception stacktrace shows that the certificate revocation check using OCSP (Online Certificate Status Protocol) has failed because of the expiration of the OCSP responder's certificate at your test date (not because of your certificate).

    To perform the test try to switch certificate revocation checks off in the Java Control Panel.

    Also be sure that your certificate has not already been permanently accepted (use "Restore security prompts" in the Java Control Panel).

    Note on time-stamped signing

    Currently (before j8u66 up to j8u144) time stamped signing does not durably prevent signatures from expiring. Web Start will not complain about the expiration of your certificate. However, it will block your application and state "certificate has expired or is not yet valid" at the time your TSA's certificate expires. You might test this using a date even after the expiration date of the TSA's certificate visible in the Timestamp: part of the keytool -printcert output.

    Depending on your type of application this may be a severe problem. Time stamping currently only gives you some more time until the application start will be blocked. We are facing this problem in an embedded environment and have opened an Oracle support request on this issue.

    Update from 2016-01-07: The final answer from Oracle Support is "There is no bug. The behaviour is expected and intentional. There will definitely be no change.". This means there is and will be no way to sign an application without expiration.

    Update from 2017-11-06: Despite Oracle's statement from 2016 signatures remain valid even after the TSA's certificate expiration date with Web Start j8u151 (tested with j8u144 and j8u151, j9 not tested). Dubious if this is by intention or by mistake.