Does java’s TrustManager implementation ignore if a certificate has expired?
I tried the following:
– Using keytool and parameter -startdate "1970/01/01 00:00:00" I created a P12 keystore with an expired certificate.
– I exported the certificate:
Keystore type: PKCS12
Keystore provider: SunJSSE
Your keystore contains 1 entry
Alias name: fake
Creation date: 5 ╠ά± 2011
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Malicious, OU=Mal, O=Mal, L=Fake, ST=GR, C=GR
Issuer: CN=Malicious, OU=Mal, O=Mal, L=Fake, ST=GR, C=GR
Serial number: -1c20
Valid from: Thu Jan 01 00:00:00 EET 1970 until: Fri Jan 02 00:00:00 EET 1970
Certificate fingerprints:
MD5: A9:BE:3A:3D:45:24:1B:4F:3C:9B:2E:02:E3:57:86:11
SHA1: 21:9D:E1:04:09:CF:10:58:73:C4:62:3C:46:4C:76:A3:81:56:88:4D
Signature algorithm name: SHA1withRSA
Version: 3
*******************************************
I used this certificate as server certificate for Tomcat.
Then using an apache httpClient I connected to tomcat, but first I added the expired certificate to the client’s trust-store (using a TrustManager
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
and loading the expired certificate).
I was expecting the connection to fail.
Instead the connection succeeds.
Using System.setProperty("javax.net.debug", "ssl");
I see:
***
Found trusted certificate:
[
[
Version: V3
Subject: CN=Malicious, OU=Mal, O=Mal, L=Fake, ST=GR, C=GR
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 1024 bits
modulus: 10350555024148635338735220482157687267055139906998169922552357357346372886164908067983097037540922519808845662295379579697361784480052371935565129553860304254832565723373586277732296157572040989796830623403187557540749531267846797324326299709274902019299
public exponent: 65537
Validity: [From: Thu Jan 01 00:00:00 EET 1970,
To: Fri Jan 02 00:00:00 EET 1970]
Issuer: CN=Malicious, OU=Mal, O=Mal, L=Fake, ST=GR, C=GR
SerialNumber: [ -1c20]
]
I see that in TLS handshake the expired certificate is send by Tomcat connector.
But the client (i.e. the TrustManager) does not reject the connection.
Is this the default behavior?
Am I suppose to configure the trustmanager somehow to check for expiration?
UPDATE:
I found that the actual TrustManager used is X509TrustManagerImpl. Here X509TrustManagerImpl says that this class has a minimal logic.May be I am using the wrong TrustManager?
UPDATE2:
From the javadoc X509TrustManager it is not clear if it checks for certificate expiration
void checkServerTrusted(X509Certificate[] chain,String authType)
throws CertificateException
Given the partial or complete
certificate chain provided by the
peer, build a certificate path to a
trusted root and return if it can be
validated and is trusted for server
SSL authentication based on the
authentication type.The authentication
type is the key exchange algorithm
portion of the cipher suites
represented as a String, such as
“RSA”, “DHE_DSS”. Note: for some
exportable cipher suites, the key
exchange algorithm is determined at
run time during the handshake. For
instance, for
TLS_RSA_EXPORT_WITH_RC4_40_MD5, the
authType should be RSA_EXPORT when an
ephemeral RSA key is used for the key
exchange, and RSA when the key from
the server certificate is used.
Checking is case-sensitive.
Thanks
I did not try your example, but I now I regularly have to regenerate my server certificates (for our development server) since their certificates have quite short validity times.
In our case the client does not have the server certificates themselves in the truststore, but only the certificate of our CA (with longer validity), and when the client tries to connect to the server, both sides get a SSLException (which may be wrapped in another exception in your case).
I guess that the trust manager assumes something like “if you give me expired certificates to trust in, I’ll do it”.
Try our approach instead (it also saves you to update the client each time the server certificate expires).