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+
22+ import org .bouncycastle .asn1 .ASN1ObjectIdentifier ;
23+ import org .bouncycastle .asn1 .pkcs .PrivateKeyInfo ;
2324import org .bouncycastle .cert .X509CertificateHolder ;
2425import org .bouncycastle .cert .jcajce .JcaX509CertificateConverter ;
2526import org .bouncycastle .openssl .PEMKeyPair ;
2627import org .bouncycastle .openssl .PEMParser ;
28+ import org .slf4j .Logger ;
29+ import org .slf4j .LoggerFactory ;
30+
31+ import javax .annotation .CheckForNull ;
32+
33+ import static java .util .Objects .requireNonNull ;
2734
2835public class CertificateUtils {
36+ private static final Logger LOG = LoggerFactory .getLogger (CertificateUtils .class );
37+
2938 private CertificateUtils () {
3039 // utility class
3140 }
@@ -41,115 +50,148 @@ public static boolean verifyCertificatesExist(String dockerCertPath) {
4150 return result ;
4251 }
4352
44- public static KeyStore createKeyStore (final String dockerCertPath ) throws NoSuchAlgorithmException ,
53+ @ SuppressFBWarnings (value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE" )
54+ public static KeyStore createKeyStore (final String keypem , final String certpem ) throws NoSuchAlgorithmException ,
4555 InvalidKeySpecException , IOException , CertificateException , KeyStoreException {
46- KeyPair keyPair = loadPrivateKey (dockerCertPath );
47- List <Certificate > privateCertificates = loadCertificates (dockerCertPath );
56+ PrivateKey privateKey = loadPrivateKey (keypem );
57+ requireNonNull (privateKey );
58+ List <Certificate > privateCertificates = loadCertificates (certpem );
4859
4960 KeyStore keyStore = KeyStore .getInstance ("JKS" );
5061 keyStore .load (null );
5162
52- keyStore .setKeyEntry ("docker" , keyPair .getPrivate (), "docker" .toCharArray (),
53- privateCertificates .toArray (new Certificate [privateCertificates .size ()]));
63+ keyStore .setKeyEntry ("docker" ,
64+ privateKey ,
65+ "docker" .toCharArray (),
66+ privateCertificates .toArray (new Certificate [privateCertificates .size ()])
67+ );
68+
5469 return keyStore ;
5570 }
5671
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- }
72+ /**
73+ * from "cert.pem" String
74+ */
75+ private static List <Certificate > loadCertificates (final String certpem ) throws IOException ,
76+ CertificateException {
77+ final StringReader certReader = new StringReader (certpem );
78+ try (BufferedReader reader = new BufferedReader (certReader )) {
79+ return loadCertificates (reader );
8280 }
83-
8481 }
8582
86- private static List <Certificate > loadCertificates (final String dockerCertPath ) throws IOException ,
83+ /**
84+ * "cert.pem" from reader
85+ */
86+ private static List <Certificate > loadCertificates (final Reader reader ) throws IOException ,
8787 CertificateException {
88- File certificate = new File (dockerCertPath , "cert.pem" );
89- BufferedReader reader = new BufferedReader (new FileReader (certificate ));
90- PEMParser pemParser = null ;
91-
92- try {
88+ try (PEMParser pemParser = new PEMParser (reader )) {
9389 List <Certificate > certificates = new ArrayList <>();
94- pemParser = new PEMParser ( reader );
90+
9591 JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter ().setProvider ("BC" );
9692 Object certObj = pemParser .readObject ();
9793
98- while (certObj != null ) {
94+ if (certObj instanceof X509CertificateHolder ) {
9995 X509CertificateHolder certificateHolder = (X509CertificateHolder ) certObj ;
10096 certificates .add (certificateConverter .getCertificate (certificateHolder ));
101-
102- certObj = pemParser .readObject ();
10397 }
10498
10599 return certificates ;
106- } finally {
107- if (pemParser != null ) {
108- IOUtils .closeQuietly (pemParser );
109- }
110-
111- if (reader != null ) {
112- IOUtils .closeQuietly (reader );
113- }
114100 }
115-
116101 }
117102
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 ));
122103
123- PEMParser pemParser = null ;
104+ /**
105+ * Return private key ("key.pem") from Reader
106+ */
107+ @ CheckForNull
108+ private static PrivateKey loadPrivateKey (final Reader reader ) throws IOException , NoSuchAlgorithmException ,
109+ InvalidKeySpecException {
110+ try (PEMParser pemParser = new PEMParser (reader )) {
111+ Object readObject = pemParser .readObject ();
112+ while (readObject != null ) {
113+ if (readObject instanceof PEMKeyPair ) {
114+ PEMKeyPair pemKeyPair = (PEMKeyPair ) readObject ;
115+ PrivateKey privateKey = guessKey (pemKeyPair .getPrivateKeyInfo ().getEncoded ());
116+ if (privateKey != null ) {
117+ return privateKey ;
118+ }
119+ } else if (readObject instanceof PrivateKeyInfo ) {
120+ PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo ) readObject ;
121+ PrivateKey privateKey = guessKey (privateKeyInfo .getEncoded ());
122+ if (privateKey != null ) {
123+ return privateKey ;
124+ }
125+ } else if (readObject instanceof ASN1ObjectIdentifier ) {
126+ // no idea how it can be used
127+ final ASN1ObjectIdentifier asn1ObjectIdentifier = (ASN1ObjectIdentifier ) readObject ;
128+ LOG .trace ("Ignoring asn1ObjectIdentifier {}" , asn1ObjectIdentifier );
129+ } else {
130+ LOG .warn ("Unknown object '{}' from PEMParser" , readObject );
131+ }
132+
133+ readObject = pemParser .readObject ();
134+ }
135+ }
124136
125- try {
126- pemParser = new PEMParser ( reader );
137+ return null ;
138+ }
127139
128- PEMKeyPair pemKeyPair = (PEMKeyPair ) pemParser .readObject ();
140+ @ CheckForNull
141+ private static PrivateKey guessKey (byte [] encodedKey ) throws NoSuchAlgorithmException {
142+ //no way to know, so iterate
143+ for (String guessFactory : new String []{"RSA" , "ECDSA" }) {
144+ try {
145+ KeyFactory factory = KeyFactory .getInstance (guessFactory );
129146
130- byte [] pemPrivateKeyEncoded = pemKeyPair .getPrivateKeyInfo ().getEncoded ();
131- byte [] pemPublicKeyEncoded = pemKeyPair .getPublicKeyInfo ().getEncoded ();
147+ PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec (encodedKey );
148+ return factory .generatePrivate (privateKeySpec );
149+ } catch (InvalidKeySpecException ignore ) {
150+ }
151+ }
132152
133- KeyFactory factory = KeyFactory .getInstance ("RSA" );
153+ return null ;
154+ }
134155
135- X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec (pemPublicKeyEncoded );
136- PublicKey publicKey = factory .generatePublic (publicKeySpec );
156+ /**
157+ * Return KeyPair from "key.pem"
158+ */
159+ @ CheckForNull
160+ private static PrivateKey loadPrivateKey (final String keypem ) throws IOException , NoSuchAlgorithmException ,
161+ InvalidKeySpecException {
162+ try (StringReader certReader = new StringReader (keypem );
163+ BufferedReader reader = new BufferedReader (certReader )) {
164+ return loadPrivateKey (reader );
165+ }
166+ }
137167
138- PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec (pemPrivateKeyEncoded );
139- PrivateKey privateKey = factory .generatePrivate (privateKeySpec );
168+ /**
169+ * "ca.pem" from String
170+ */
171+ public static KeyStore createTrustStore (String capem ) throws IOException , CertificateException ,
172+ KeyStoreException , NoSuchAlgorithmException {
173+ try (Reader certReader = new StringReader (capem )) {
174+ return createTrustStore (certReader );
175+ }
176+ }
140177
141- return new KeyPair (publicKey , privateKey );
178+ /**
179+ * "ca.pem" from Reader
180+ */
181+ public static KeyStore createTrustStore (final Reader certReader ) throws IOException , CertificateException ,
182+ KeyStoreException , NoSuchAlgorithmException {
183+ try (PEMParser pemParser = new PEMParser (certReader )) {
184+ X509CertificateHolder certificateHolder = (X509CertificateHolder ) pemParser .readObject ();
185+ Certificate caCertificate = new JcaX509CertificateConverter ()
186+ .setProvider ("BC" )
187+ .getCertificate (certificateHolder );
142188
143- } finally {
144- if (pemParser != null ) {
145- IOUtils .closeQuietly (pemParser );
146- }
189+ KeyStore trustStore = KeyStore .getInstance ("JKS" );
190+ trustStore .load (null );
191+ trustStore .setCertificateEntry ("ca" , caCertificate );
147192
148- if (reader != null ) {
149- IOUtils .closeQuietly (reader );
150- }
193+ return trustStore ;
151194 }
152-
153195 }
154196
155197}
0 commit comments