3636import java .nio .file .Path ;
3737import java .security .KeyStore ;
3838import java .security .MessageDigest ;
39- import java .security .cert .Certificate ;
40- import java .security .cert .CertificateExpiredException ;
41- import java .security .cert .CertificateNotYetValidException ;
42- import java .security .cert .X509Certificate ;
43- import java .util .Date ;
44- import java .util .Enumeration ;
45- import java .util .HashMap ;
46- import java .util .HashSet ;
47- import java .util .HexFormat ;
48- import java .util .Map ;
39+ import java .security .cert .*;
40+ import java .util .*;
4941
5042public class VerifyCACerts {
5143
@@ -251,7 +243,6 @@ public class VerifyCACerts {
251243 }
252244 };
253245
254- // Exception list to 90 days expiry policy
255246 // No error will be reported if certificate in this list expires
256247 @ SuppressWarnings ("serial" )
257248 private static final HashSet <String > EXPIRY_EXC_ENTRIES = new HashSet <>() {
@@ -280,14 +271,15 @@ public class VerifyCACerts {
280271
281272 public static void main (String [] args ) throws Exception {
282273 System .out .println ("cacerts file: " + CACERTS );
283- md = MessageDigest .getInstance ("SHA-256" );
284274
275+ // verify integrity of cacerts
276+ md = MessageDigest .getInstance ("SHA-256" );
285277 byte [] data = Files .readAllBytes (Path .of (CACERTS ));
286278 String checksum = HEX .formatHex (md .digest (data ));
287279 if (!checksum .equals (CHECKSUM )) {
288280 atLeastOneFailed = true ;
289- System .err .println ("ERROR: wrong checksum\n " + checksum );
290- System .err .println ("Expected checksum\n " + CHECKSUM );
281+ System .err .println ("ERROR: wrong checksum" + checksum );
282+ System .err .println ("Expected checksum" + CHECKSUM );
291283 }
292284
293285 KeyStore ks = KeyStore .getInstance ("JKS" );
@@ -300,6 +292,15 @@ public static void main(String[] args) throws Exception {
300292 + COUNT );
301293 }
302294
295+ System .out .println ("Trusted CA Certificate count: " + ks .size ());
296+
297+ // also ensure FINGERPRINT_MAP lists correct count
298+ if (FINGERPRINT_MAP .size () != COUNT ) {
299+ atLeastOneFailed = true ;
300+ System .err .println ("ERROR: " + FINGERPRINT_MAP .size ()
301+ + " FINGERPRINT_MAP entries, should be " + COUNT );
302+ }
303+
303304 // check that all entries in the map are in the keystore
304305 for (String alias : FINGERPRINT_MAP .keySet ()) {
305306 if (!ks .isCertificateEntry (alias )) {
@@ -313,66 +314,66 @@ public static void main(String[] args) throws Exception {
313314 Enumeration <String > aliases = ks .aliases ();
314315 while (aliases .hasMoreElements ()) {
315316 String alias = aliases .nextElement ();
316- System .out .println ("\n Verifying " + alias );
317+ System .out .println ("Verifying " + alias );
318+
319+ // Is cert trusted?
317320 if (!ks .isCertificateEntry (alias )) {
318321 atLeastOneFailed = true ;
319- System .err .println ("ERROR: " + alias
320- + " is not a trusted cert entry" );
322+ System .err .println ("ERROR: " + alias + " is not a trusted cert entry" );
321323 }
324+
325+ // Does fingerprint match?
322326 X509Certificate cert = (X509Certificate ) ks .getCertificate (alias );
323327 if (!checkFingerprint (alias , cert )) {
324328 atLeastOneFailed = true ;
325329 System .err .println ("ERROR: " + alias + " SHA-256 fingerprint is incorrect" );
326330 }
327- // Make sure cert can be self-verified
331+
332+ // Can cert be self-verified?
328333 try {
329334 cert .verify (cert .getPublicKey ());
330335 } catch (Exception e ) {
331336 atLeastOneFailed = true ;
332- System .err .println ("ERROR: cert cannot be verified:"
333- + e .getMessage ());
337+ System .err .println ("ERROR: cert cannot be verified:" + e .getMessage ());
334338 }
335339
336- // Make sure cert is not expired or not yet valid
340+ // Is cert expired?
337341 try {
338342 cert .checkValidity ();
339343 } catch (CertificateExpiredException cee ) {
340344 if (!EXPIRY_EXC_ENTRIES .contains (alias )) {
341345 atLeastOneFailed = true ;
342- System .err .println ("ERROR: cert is expired" );
346+ System .err .println ("ERROR: cert is expired but not in EXPIRY_EXC_ENTRIES " );
343347 }
344348 } catch (CertificateNotYetValidException cne ) {
345349 atLeastOneFailed = true ;
346350 System .err .println ("ERROR: cert is not yet valid" );
347351 }
348352
349- // If cert is within 90 days of expiring, mark as failure so
353+ // If cert is within 90 days of expiring, mark as warning so
350354 // that cert can be scheduled to be removed/renewed.
351355 Date notAfter = cert .getNotAfter ();
352356 if (notAfter .getTime () - System .currentTimeMillis () < NINETY_DAYS ) {
353357 if (!EXPIRY_EXC_ENTRIES .contains (alias )) {
354- atLeastOneFailed = true ;
355- System .err .println ("ERROR: cert \" " + alias + "\" expiry \" "
356- + notAfter .toString () + "\" will expire within 90 days" );
358+ System .err .println ("WARNING: cert \" " + alias + "\" expiry \" "
359+ + notAfter + "\" will expire within 90 days" );
357360 }
358361 }
359362 }
360363
361364 if (atLeastOneFailed ) {
362- throw new Exception ("At least one cacert test failed" );
365+ throw new RuntimeException ("At least one cacert test failed" );
363366 }
364367 }
365368
366369 private static boolean checkFingerprint (String alias , Certificate cert )
367- throws Exception {
370+ throws CertificateEncodingException {
368371 String fingerprint = FINGERPRINT_MAP .get (alias );
369372 if (fingerprint == null ) {
370373 // no entry for alias
371- return true ;
374+ return false ;
372375 }
373- System .out .println ("Checking fingerprint of " + alias );
374376 byte [] digest = md .digest (cert .getEncoded ());
375377 return fingerprint .equals (HEX .formatHex (digest ));
376378 }
377-
378379}
0 commit comments