2727import java .io .ByteArrayInputStream ;
2828import java .io .File ;
2929import java .io .FileInputStream ;
30+ import java .io .FileNotFoundException ;
3031import java .io .IOException ;
3132import java .io .InputStream ;
3233import java .io .InputStreamReader ;
4849import java .security .spec .RSAPrivateCrtKeySpec ;
4950import java .util .Base64 ;
5051import java .util .Collection ;
52+ import java .util .Collections ;
5153import java .util .concurrent .Callable ;
5254import java .util .stream .Collectors ;
5355
@@ -73,15 +75,16 @@ public static ByteArrayInputStream getInputStreamFromDataOrFile(String data, Str
7375 public static KeyStore createTrustStore (String caCertData , String caCertFile , String trustStoreFile ,
7476 String trustStorePassphrase ) throws IOException , CertificateException , KeyStoreException , NoSuchAlgorithmException {
7577 ByteArrayInputStream pemInputStream = getInputStreamFromDataOrFile (caCertData , caCertFile );
76- return createTrustStore (pemInputStream , trustStoreFile ,
78+
79+ KeyStore trustStore = loadTrustStore (trustStoreFile ,
7780 getPassphrase (TRUST_STORE_PASSWORD_SYSTEM_PROPERTY , trustStorePassphrase ));
78- }
7981
80- private static KeyStore createTrustStore (ByteArrayInputStream pemInputStream , String trustStoreFile ,
81- char [] trustStorePassphrase )
82- throws IOException , CertificateException , KeyStoreException , NoSuchAlgorithmException {
82+ return mergePemCertsIntoTrustStore (pemInputStream , trustStore , true );
83+ }
8384
84- final String trustStoreType = System .getProperty (TRUST_STORE_TYPE_SYSTEM_PROPERTY , KeyStore .getDefaultType ());
85+ static KeyStore loadTrustStore (String trustStoreFile , char [] trustStorePassphrase )
86+ throws KeyStoreException , IOException , NoSuchAlgorithmException , CertificateException , FileNotFoundException {
87+ String trustStoreType = System .getProperty (TRUST_STORE_TYPE_SYSTEM_PROPERTY , KeyStore .getDefaultType ());
8588 KeyStore trustStore = KeyStore .getInstance (trustStoreType );
8689
8790 if (Utils .isNotNullOrEmpty (trustStoreFile )) {
@@ -91,19 +94,45 @@ private static KeyStore createTrustStore(ByteArrayInputStream pemInputStream, St
9194 } else {
9295 loadDefaultTrustStoreFile (trustStore , trustStorePassphrase );
9396 }
97+ return trustStore ;
98+ }
9499
100+ static KeyStore mergePemCertsIntoTrustStore (ByteArrayInputStream pemInputStream , KeyStore trustStore , boolean first )
101+ throws CertificateException , KeyStoreException {
95102 CertificateFactory certFactory = CertificateFactory .getInstance ("X509" );
96103 while (pemInputStream .available () > 0 ) {
104+ X509Certificate cert ;
97105 try {
98- X509Certificate cert = (X509Certificate ) certFactory .generateCertificate (pemInputStream );
99- String alias = cert .getSubjectX500Principal ().getName () + "_" + cert .getSerialNumber ().toString (16 );
100- trustStore .setCertificateEntry (alias , cert );
106+ cert = (X509Certificate ) certFactory .generateCertificate (pemInputStream );
101107 } catch (CertificateException e ) {
102108 if (pemInputStream .available () > 0 ) {
103109 // any remaining input means there is an actual problem with the key contents or file format
104110 throw e ;
105111 }
106112 LOG .debug ("The trailing entry generated a certificate exception. More than likely the contents end with comments." , e );
113+ break ;
114+ }
115+ try {
116+ String alias = cert .getSubjectX500Principal ().getName () + "_" + cert .getSerialNumber ().toString (16 );
117+ trustStore .setCertificateEntry (alias , cert );
118+ first = false ;
119+ } catch (KeyStoreException e ) {
120+ if (first ) {
121+ // could be that the store type is not writable, rather than some elaborate check for read-only
122+ // we'll simply try again with a well supported type
123+ pemInputStream .reset ();
124+ KeyStore writableStore = KeyStore .getInstance ("PKCS12" );
125+ try {
126+ writableStore .load (null , null ); // initialize the instance
127+ } catch (NoSuchAlgorithmException | CertificateException | IOException e1 ) {
128+ throw e ; // not usable, just give up
129+ }
130+ for (String alias : Collections .list (trustStore .aliases ())) {
131+ writableStore .setCertificateEntry (alias , trustStore .getCertificate (alias ));
132+ }
133+ return mergePemCertsIntoTrustStore (pemInputStream , writableStore , false );
134+ }
135+ throw e ;
107136 }
108137 }
109138 return trustStore ;
0 commit comments