11/*
22 * MIT License
33 *
4- * Copyright (c) 2024 Hydrologic Engineering Center
4+ * Copyright (c) 2026 Hydrologic Engineering Center
55 *
66 * Permission is hereby granted, free of charge, to any person obtaining a copy
77 * of this software and associated documentation files (the "Software"), to deal
2424
2525package mil .army .usace .hec .cwms .http .client .auth ;
2626
27- import javax .net .ssl .KeyManager ;
28- import javax .net .ssl .KeyManagerFactory ;
29- import javax .net .ssl .X509KeyManager ;
3027import java .io .IOException ;
3128import java .security .KeyStore ;
3229import java .security .KeyStoreException ;
3835import java .security .cert .X509Certificate ;
3936import java .util .ArrayList ;
4037import java .util .Collection ;
41- import java .util .Enumeration ;
38+ import java .util .Date ;
4239import java .util .List ;
4340import java .util .Set ;
4441import java .util .TreeSet ;
4542import java .util .logging .Level ;
4643import java .util .logging .Logger ;
4744import java .util .regex .Pattern ;
45+ import javax .net .ssl .KeyManager ;
46+ import javax .net .ssl .KeyManagerFactory ;
47+ import javax .net .ssl .X509KeyManager ;
4848
4949
5050public final class CacKeyManagerUtil {
5151 static final Pattern EDIPI_PATTERN = Pattern .compile ("\\ d{10}@" , Pattern .CASE_INSENSITIVE );
5252 private static final Logger LOGGER = Logger .getLogger (CacKeyManagerUtil .class .getName ());
53- private static KeyStore WINDOWS_KEY_STORE ;
53+ private static CacKeyManager WINDOWS_KEY_STORE ;
5454
5555 private CacKeyManagerUtil () {
5656 throw new AssertionError ("Utility class" );
5757 }
5858
5959 public static KeyManager createKeyManager () throws CacCertificateException {
60- return getKeyManagerFromWindowsKeyStore (null );
60+ return loadWindowsKeyStore (null );
6161 }
6262
6363 public static KeyManager createKeyManager (String certificateAlias ) throws CacCertificateException {
64- return getKeyManagerFromWindowsKeyStore (certificateAlias );
64+ return loadWindowsKeyStore (certificateAlias );
6565 }
6666
67- private static synchronized KeyStore loadWindowsKeyStore () throws CertificateException , IOException , NoSuchAlgorithmException , KeyStoreException {
67+ private static synchronized CacKeyManager loadWindowsKeyStore (String certificateAlias )
68+ throws CacCertificateException {
6869 if (WINDOWS_KEY_STORE == null ) {
69- KeyStore keystore = KeyStore .getInstance ("WINDOWS-MY" );
70- keystore .load (null , null );
71- WINDOWS_KEY_STORE = keystore ;
70+ WINDOWS_KEY_STORE = getKeyManagerFromWindowsKeyStore ();
7271 }
72+ WINDOWS_KEY_STORE .setCertificateAlias (certificateAlias );
7373 return WINDOWS_KEY_STORE ;
7474 }
7575
76- private static CacKeyManager getKeyManagerFromWindowsKeyStore (String certificateAlias ) throws CacCertificateException {
76+ private static CacKeyManager getKeyManagerFromWindowsKeyStore () throws CacCertificateException {
7777 try {
78- KeyStore keystore = loadWindowsKeyStore ();
78+ KeyStore keystore = KeyStore .getInstance ("WINDOWS-MY" );
79+ keystore .load (null , null );
7980 KeyManagerFactory kmf = KeyManagerFactory .getInstance (KeyManagerFactory .getDefaultAlgorithm ());
8081 kmf .init (keystore , null );
8182 KeyManager [] kms = kmf .getKeyManagers ();
8283 for (KeyManager km : kms ) {
8384 if (km instanceof X509KeyManager ) {
84- return new CacKeyManager ((X509KeyManager ) km , keystore , certificateAlias );
85+ return new CacKeyManager ((X509KeyManager ) km );
8586 }
8687 }
8788 throw new CacCertificateException ("Failed to get X509KeyManager from Windows OS" );
@@ -95,26 +96,28 @@ private static CacKeyManager getKeyManagerFromWindowsKeyStore(String certificate
9596 public static List <String > getCertificateAliases () {
9697 Set <String > aliases = new TreeSet <>();
9798 try {
98- KeyStore keystore = loadWindowsKeyStore ();
99- Enumeration <String > keystoreAliases = keystore .aliases ();
100- while (keystoreAliases .hasMoreElements ()) {
101- String alias = keystoreAliases .nextElement ();
99+ var keystore = loadWindowsKeyStore (null );
100+ var keystoreAliases = keystore .aliases ();
101+ for (String alias : keystoreAliases ) {
102102 Certificate [] certificateChain = keystore .getCertificateChain (alias );
103- if (certificateChain != null && certificateChain .length > 1 && certificateChain [0 ] instanceof X509Certificate ) {
104- if (isPivCertificate ((X509Certificate ) certificateChain [0 ])) {
105- aliases .add (alias );
106- }
103+ if (certificateChain != null
104+ && certificateChain .length > 1
105+ && certificateChain [0 ] instanceof X509Certificate
106+ && isPivCertificate ((X509Certificate ) certificateChain [0 ])) {
107+ aliases .add (alias );
107108 }
108109 }
109- } catch (IOException | NoSuchAlgorithmException | CertificateException | CacCertificateException |
110- KeyStoreException e ) {
110+ } catch (CacCertificateException e ) {
111111 LOGGER .log (Level .WARNING , "Error reading certificates from WINDOWS-MY keystore" , e );
112112 }
113113 return new ArrayList <>(aliases );
114114 }
115115
116116 public static boolean isPivCertificate (X509Certificate cr ) throws CacCertificateException {
117117 try {
118+ if (new Date ().after (cr .getNotAfter ())) {
119+ return false ;
120+ }
118121 Collection <List <?>> subjectAlternativeNames = cr .getSubjectAlternativeNames ();
119122 if (subjectAlternativeNames == null ) {
120123 return false ;
0 commit comments