How to use a file in a jar as javax.net.ssl.keystore?

后端 未结 3 770
渐次进展
渐次进展 2020-12-01 08:13

I\'m trying to do something like

URL clientks = com.messaging.SubscriptionManager.class.getResource( \"client.ks\" );
String path = clientks.toURI().getPath         


        
相关标签:
3条回答
  • 2020-12-01 08:43

    Here's a cleaned-up version of user2529737's answer, in case it helps. It has removed unneeded trust store setup and added required imports, parameters for keystore type and key password.

    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.KeyManager;
    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.SSLContext;
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.URL;
    import java.security.KeyStore;
    
    public class PlainJavaHTTPS2Test {
    
        public void setUp() throws Exception {
            final String KEYSTOREPATH = "clientkeystore.p12"; // or .jks
    
            // store password can be null if there is no password
            final char[] KEYSTOREPASS = "keystorepass".toCharArray();
    
            // key password can be null if there is no password
            final char[] KEYPASS = "keypass".toCharArray();
    
            try (InputStream storeStream = this.getClass().getResourceAsStream(KEYSTOREPATH)) {
                setSSLFactories(storeStream, "PKCS12", KEYSTOREPASS, KEYPASS);
            }
        }
        private static void setSSLFactories(InputStream keyStream, String keystoreType, char[] keyStorePassword, char[] keyPassword) throws Exception
        {
            KeyStore keyStore = KeyStore.getInstance(keystoreType);
    
            keyStore.load(keyStream, keyStorePassword);
    
            KeyManagerFactory keyFactory =
                    KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    
            keyFactory.init(keyStore, keyPassword);
    
            KeyManager[] keyManagers = keyFactory.getKeyManagers();
    
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(keyManagers, null, null);
            SSLContext.setDefault(sslContext);
        }
    }
    
    0 讨论(0)
  • 2020-12-01 08:48

    You can get an InputStream to a resource in a jar file, but not a File. If the "thing" that ultimately reads the keystore expects a File or a path to a file, your only option is to extract it to the filesystem.

    0 讨论(0)
  • 2020-12-01 08:53

    Still working on implementation, but I believe it is possible to load the keystore from the jar via InputStream and explicitly set the TrustStore programatically (vs setting the System properties). See the article: Setting multiple truststore on the same JVM

    Got it working!

    InputStream keystoreInput = Thread.currentThread().getContextClassLoader()
        .getResourceAsStream(<path in jar>/client.ks");
    InputStream truststoreInput = Thread.currentThread().getContextClassLoader()
        .getResourceAsStream(<path in jar>/client.ts");
    setSSLFactories(keystoreInput, "password", truststoreInput);
    keystoreInput.close();
    truststoreInput.close();
    
    private static void setSSLFactories(InputStream keyStream, String keyStorePassword, 
        InputStream trustStream) throws Exception
    {    
      // Get keyStore
      KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());    
    
      // if your store is password protected then declare it (it can be null however)
      char[] keyPassword = keyStorePassword.toCharArray();
    
      // load the stream to your store
      keyStore.load(keyStream, keyPassword);
    
      // initialize a key manager factory with the key store
      KeyManagerFactory keyFactory = 
      KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());    
      keyFactory.init(keyStore, keyPassword);
    
      // get the key managers from the factory
      KeyManager[] keyManagers = keyFactory.getKeyManagers();
    
      // Now get trustStore
      KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());    
    
      // if your store is password protected then declare it (it can be null however)
      //char[] trustPassword = password.toCharArray();
    
      // load the stream to your store
      trustStore.load(trustStream, null);
    
      // initialize a trust manager factory with the trusted store
      TrustManagerFactory trustFactory = 
      TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());    
      trustFactory.init(trustStore);
    
      // get the trust managers from the factory
      TrustManager[] trustManagers = trustFactory.getTrustManagers();
    
      // initialize an ssl context to use these managers and set as default
      SSLContext sslContext = SSLContext.getInstance("SSL");
      sslContext.init(keyManagers, trustManagers, null);
      SSLContext.setDefault(sslContext);    
    }
    
    0 讨论(0)
提交回复
热议问题