22
33import java .io .BufferedReader ;
44import java .io .File ;
5- import java .io .FileReader ;
65import java .io .IOException ;
6+ import java .io .Reader ;
7+ import java .io .StringReader ;
78import java .security .KeyFactory ;
8- import java .security .KeyPair ;
99import java .security .KeyStore ;
1010import java .security .KeyStoreException ;
1111import java .security .NoSuchAlgorithmException ;
1212import java .security .PrivateKey ;
13- import java .security .PublicKey ;
1413import java .security .cert .Certificate ;
1514import java .security .cert .CertificateException ;
1615import java .security .spec .InvalidKeySpecException ;
1716import java .security .spec .PKCS8EncodedKeySpec ;
18- import java .security .spec .X509EncodedKeySpec ;
1917import java .util .ArrayList ;
2018import java .util .List ;
2119
22- import org .apache .commons .io .IOUtils ;
20+ import edu .umd .cs .findbugs .annotations .SuppressFBWarnings ;
21+ import org .bouncycastle .asn1 .ASN1ObjectIdentifier ;
22+ import org .bouncycastle .asn1 .pkcs .PrivateKeyInfo ;
2323import org .bouncycastle .cert .X509CertificateHolder ;
2424import org .bouncycastle .cert .jcajce .JcaX509CertificateConverter ;
2525import org .bouncycastle .openssl .PEMKeyPair ;
2626import org .bouncycastle .openssl .PEMParser ;
27+ import org .slf4j .Logger ;
28+ import org .slf4j .LoggerFactory ;
29+
30+ import javax .annotation .CheckForNull ;
31+
32+ import static java .util .Objects .requireNonNull ;
2733
2834public class CertificateUtils {
35+ private static final Logger LOG = LoggerFactory .getLogger (CertificateUtils .class );
36+
2937 private CertificateUtils () {
3038 // utility class
3139 }
@@ -41,115 +49,157 @@ public static boolean verifyCertificatesExist(String dockerCertPath) {
4149 return result ;
4250 }
4351
52+ /**
53+ * @param dockerCertPath with standard named files.
54+ */
4455 public static KeyStore createKeyStore (final String dockerCertPath ) throws NoSuchAlgorithmException ,
4556 InvalidKeySpecException , IOException , CertificateException , KeyStoreException {
46- KeyPair keyPair = loadPrivateKey (dockerCertPath );
47- List <Certificate > privateCertificates = loadCertificates (dockerCertPath );
57+ return createKeyStore ("key.pem" , "cert.pem" );
58+ }
59+
60+
61+ @ SuppressFBWarnings (value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE" )
62+ public static KeyStore createKeyStore (final String keypem , final String certpem ) throws NoSuchAlgorithmException ,
63+ InvalidKeySpecException , IOException , CertificateException , KeyStoreException {
64+ PrivateKey privateKey = loadPrivateKey (keypem );
65+ requireNonNull (privateKey );
66+ List <Certificate > privateCertificates = loadCertificates (certpem );
4867
4968 KeyStore keyStore = KeyStore .getInstance ("JKS" );
5069 keyStore .load (null );
5170
52- keyStore .setKeyEntry ("docker" , keyPair .getPrivate (), "docker" .toCharArray (),
53- privateCertificates .toArray (new Certificate [privateCertificates .size ()]));
71+ keyStore .setKeyEntry ("docker" ,
72+ privateKey ,
73+ "docker" .toCharArray (),
74+ privateCertificates .toArray (new Certificate [privateCertificates .size ()])
75+ );
76+
5477 return keyStore ;
5578 }
5679
57- public static KeyStore createTrustStore (final String dockerCertPath ) throws IOException , CertificateException ,
58- KeyStoreException , NoSuchAlgorithmException {
59- File caPath = new File (dockerCertPath , "ca.pem" );
60- BufferedReader reader = new BufferedReader (new FileReader (caPath ));
61- PEMParser pemParser = null ;
62-
63- try {
64- pemParser = new PEMParser (reader );
65- X509CertificateHolder certificateHolder = (X509CertificateHolder ) pemParser .readObject ();
66- Certificate caCertificate = new JcaX509CertificateConverter ().setProvider ("BC" ).getCertificate (
67- certificateHolder );
68-
69- KeyStore trustStore = KeyStore .getInstance ("JKS" );
70- trustStore .load (null );
71- trustStore .setCertificateEntry ("ca" , caCertificate );
72- return trustStore ;
73-
74- } finally {
75- if (pemParser != null ) {
76- IOUtils .closeQuietly (pemParser );
77- }
78-
79- if (reader != null ) {
80- IOUtils .closeQuietly (reader );
81- }
80+ /**
81+ * from "cert.pem" String
82+ */
83+ private static List <Certificate > loadCertificates (final String certpem ) throws IOException ,
84+ CertificateException {
85+ final StringReader certReader = new StringReader (certpem );
86+ try (BufferedReader reader = new BufferedReader (certReader )) {
87+ return loadCertificates (reader );
8288 }
83-
8489 }
8590
86- private static List <Certificate > loadCertificates (final String dockerCertPath ) throws IOException ,
91+ /**
92+ * "cert.pem" from reader
93+ */
94+ private static List <Certificate > loadCertificates (final Reader reader ) throws IOException ,
8795 CertificateException {
88- File certificate = new File (dockerCertPath , "cert.pem" );
89- BufferedReader reader = new BufferedReader (new FileReader (certificate ));
90- PEMParser pemParser = null ;
91-
92- try {
96+ try (PEMParser pemParser = new PEMParser (reader )) {
9397 List <Certificate > certificates = new ArrayList <>();
94- pemParser = new PEMParser ( reader );
98+
9599 JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter ().setProvider ("BC" );
96100 Object certObj = pemParser .readObject ();
97101
98- while (certObj != null ) {
102+ if (certObj instanceof X509CertificateHolder ) {
99103 X509CertificateHolder certificateHolder = (X509CertificateHolder ) certObj ;
100104 certificates .add (certificateConverter .getCertificate (certificateHolder ));
101-
102- certObj = pemParser .readObject ();
103105 }
104106
105107 return certificates ;
106- } finally {
107- if (pemParser != null ) {
108- IOUtils .closeQuietly (pemParser );
109- }
110-
111- if (reader != null ) {
112- IOUtils .closeQuietly (reader );
113- }
114108 }
115-
116109 }
117110
118- private static KeyPair loadPrivateKey (final String dockerCertPath ) throws IOException , NoSuchAlgorithmException ,
119- InvalidKeySpecException {
120- File certificate = new File (dockerCertPath , "key.pem" );
121- BufferedReader reader = new BufferedReader (new FileReader (certificate ));
122111
123- PEMParser pemParser = null ;
112+ /**
113+ * Return private key ("key.pem") from Reader
114+ */
115+ @ CheckForNull
116+ private static PrivateKey loadPrivateKey (final Reader reader ) throws IOException , NoSuchAlgorithmException ,
117+ InvalidKeySpecException {
118+ try (PEMParser pemParser = new PEMParser (reader )) {
119+ Object readObject = pemParser .readObject ();
120+ while (readObject != null ) {
121+ if (readObject instanceof PEMKeyPair ) {
122+ PEMKeyPair pemKeyPair = (PEMKeyPair ) readObject ;
123+ PrivateKey privateKey = guessKey (pemKeyPair .getPrivateKeyInfo ().getEncoded ());
124+ if (privateKey != null ) {
125+ return privateKey ;
126+ }
127+ } else if (readObject instanceof PrivateKeyInfo ) {
128+ PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo ) readObject ;
129+ PrivateKey privateKey = guessKey (privateKeyInfo .getEncoded ());
130+ if (privateKey != null ) {
131+ return privateKey ;
132+ }
133+ } else if (readObject instanceof ASN1ObjectIdentifier ) {
134+ // no idea how it can be used
135+ final ASN1ObjectIdentifier asn1ObjectIdentifier = (ASN1ObjectIdentifier ) readObject ;
136+ LOG .trace ("Ignoring asn1ObjectIdentifier {}" , asn1ObjectIdentifier );
137+ } else {
138+ LOG .warn ("Unknown object '{}' from PEMParser" , readObject );
139+ }
140+
141+ readObject = pemParser .readObject ();
142+ }
143+ }
124144
125- try {
126- pemParser = new PEMParser ( reader );
145+ return null ;
146+ }
127147
128- PEMKeyPair pemKeyPair = (PEMKeyPair ) pemParser .readObject ();
148+ @ CheckForNull
149+ private static PrivateKey guessKey (byte [] encodedKey ) throws NoSuchAlgorithmException {
150+ //no way to know, so iterate
151+ for (String guessFactory : new String []{"RSA" , "ECDSA" }) {
152+ try {
153+ KeyFactory factory = KeyFactory .getInstance (guessFactory );
129154
130- byte [] pemPrivateKeyEncoded = pemKeyPair .getPrivateKeyInfo ().getEncoded ();
131- byte [] pemPublicKeyEncoded = pemKeyPair .getPublicKeyInfo ().getEncoded ();
155+ PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec (encodedKey );
156+ return factory .generatePrivate (privateKeySpec );
157+ } catch (InvalidKeySpecException ignore ) {
158+ }
159+ }
132160
133- KeyFactory factory = KeyFactory .getInstance ("RSA" );
161+ return null ;
162+ }
134163
135- X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec (pemPublicKeyEncoded );
136- PublicKey publicKey = factory .generatePublic (publicKeySpec );
164+ /**
165+ * Return KeyPair from "key.pem"
166+ */
167+ @ CheckForNull
168+ private static PrivateKey loadPrivateKey (final String keypem ) throws IOException , NoSuchAlgorithmException ,
169+ InvalidKeySpecException {
170+ try (StringReader certReader = new StringReader (keypem );
171+ BufferedReader reader = new BufferedReader (certReader )) {
172+ return loadPrivateKey (reader );
173+ }
174+ }
137175
138- PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec (pemPrivateKeyEncoded );
139- PrivateKey privateKey = factory .generatePrivate (privateKeySpec );
176+ /**
177+ * "ca.pem" from String
178+ */
179+ public static KeyStore createTrustStore (String capem ) throws IOException , CertificateException ,
180+ KeyStoreException , NoSuchAlgorithmException {
181+ try (Reader certReader = new StringReader (capem )) {
182+ return createTrustStore (certReader );
183+ }
184+ }
140185
141- return new KeyPair (publicKey , privateKey );
186+ /**
187+ * "ca.pem" from Reader
188+ */
189+ public static KeyStore createTrustStore (final Reader certReader ) throws IOException , CertificateException ,
190+ KeyStoreException , NoSuchAlgorithmException {
191+ try (PEMParser pemParser = new PEMParser (certReader )) {
192+ X509CertificateHolder certificateHolder = (X509CertificateHolder ) pemParser .readObject ();
193+ Certificate caCertificate = new JcaX509CertificateConverter ()
194+ .setProvider ("BC" )
195+ .getCertificate (certificateHolder );
142196
143- } finally {
144- if (pemParser != null ) {
145- IOUtils .closeQuietly (pemParser );
146- }
197+ KeyStore trustStore = KeyStore .getInstance ("JKS" );
198+ trustStore .load (null );
199+ trustStore .setCertificateEntry ("ca" , caCertificate );
147200
148- if (reader != null ) {
149- IOUtils .closeQuietly (reader );
150- }
201+ return trustStore ;
151202 }
152-
153203 }
154204
155205}
0 commit comments