2015-04-13 154 views
0

当我尝试使用自签名证书连接到URL时,Java不允许我这样做。在我的情况下,我无法使用自定义SSL套接字工厂而无需进行证书检查,因此我需要使用PKS12证书并将其添加到可信存储区中。 我的问题是 - 我有什么行动来获得PKS12证书?我通过浏览器工具(它是X.509)从URL导出证书,那我该怎么办?带自签名证书的SSL

+0

查看Javadoc的'keytool'。这里都有描述。 – EJP

回答

0

你可以尝试做这样的事情:

来自

How do I accept a self-signed certificate with a Java HttpsURLConnection?

HttpsURLConnection connection = (HttpsURLConnection) URL.openConnection(); 
connection.setSSLSocketFactory(SSLFACTORY); 
connection.setMethod("POST"); 

KeyStore KEY_STORE = KeyStore.getInstance(KeyStore.getDefaultType()); 
keyStore.load(TRUST_STORE, PASSWORD); 
TRUST_STORE.close(); 

TrustManagerFactory managerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
managerFactory.init(KEY_STORE); 
SSLSocketFactoryEx SSLFACTORY = new SSLSocketFactoryEx(); 
connection.setSSLSocketFactory(factory); 
connection.setRequestProperty("charset", "utf-8"); 

摘自:

Which Cipher Suites to enable for SSL Socket?

感谢@jww

class SSLSocketFactoryEx extends SSLSocketFactory 
{ 
    public SSLSocketFactoryEx() throws NoSuchAlgorithmException, KeyManagementException 
    { 
     initSSLSocketFactoryEx(null,null,null); 
    } 

    public SSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) throws NoSuchAlgorithmException, KeyManagementException 
    { 
     initSSLSocketFactoryEx(km, tm, random); 
    } 

    public SSLSocketFactoryEx(SSLContext ctx) throws NoSuchAlgorithmException, KeyManagementException 
    { 
     initSSLSocketFactoryEx(ctx); 
    } 

    public String[] getDefaultCipherSuites() 
    { 
     return m_ciphers; 
    } 

    public String[] getSupportedCipherSuites() 
    { 
     return m_ciphers; 
    } 

    public String[] getDefaultProtocols() 
    { 
     return m_protocols; 
    } 

    public String[] getSupportedProtocols() 
    { 
     return m_protocols; 
    } 

    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException 
    { 
     SSLSocketFactory factory = m_ctx.getSocketFactory(); 
     SSLSocket ss = (SSLSocket)factory.createSocket(s, host, port, autoClose); 

     ss.setEnabledProtocols(m_protocols); 
     ss.setEnabledCipherSuites(m_ciphers); 

     return ss; 
    } 

    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException 
    { 
     SSLSocketFactory factory = m_ctx.getSocketFactory(); 
     SSLSocket ss = (SSLSocket)factory.createSocket(address, port, localAddress, localPort); 

     ss.setEnabledProtocols(m_protocols); 
     ss.setEnabledCipherSuites(m_ciphers); 

     return ss; 
    } 

    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException 
    { 
     SSLSocketFactory factory = m_ctx.getSocketFactory(); 
     SSLSocket ss = (SSLSocket)factory.createSocket(host, port, localHost, localPort); 

     ss.setEnabledProtocols(m_protocols); 
     ss.setEnabledCipherSuites(m_ciphers); 

     return ss; 
    } 

    public Socket createSocket(InetAddress host, int port) throws IOException 
    { 
     SSLSocketFactory factory = m_ctx.getSocketFactory(); 
     SSLSocket ss = (SSLSocket)factory.createSocket(host, port); 

     ss.setEnabledProtocols(m_protocols); 
     ss.setEnabledCipherSuites(m_ciphers); 

     return ss; 
    } 

    public Socket createSocket(String host, int port) throws IOException 
    { 
     SSLSocketFactory factory = m_ctx.getSocketFactory(); 
     SSLSocket ss = (SSLSocket)factory.createSocket(host, port); 

     ss.setEnabledProtocols(m_protocols); 
     ss.setEnabledCipherSuites(m_ciphers); 

     return ss; 
    } 

    private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) 
    throws NoSuchAlgorithmException, KeyManagementException 
    { 
     m_ctx = SSLContext.getInstance("TLS"); 
     m_ctx.init(km, tm, random); 

     m_protocols = GetProtocolList(); 
     m_ciphers = GetCipherList(); 
    } 

    private void initSSLSocketFactoryEx(SSLContext ctx) 
    throws NoSuchAlgorithmException, KeyManagementException 
    { 
     m_ctx = ctx; 

     m_protocols = GetProtocolList(); 
     m_ciphers = GetCipherList(); 
    } 

    protected String[] GetProtocolList() 
    { 
     String[] preferredProtocols = { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" }; 
     String[] availableProtocols = null; 

     SSLSocket socket = null; 

     try 
     { 
      SSLSocketFactory factory = m_ctx.getSocketFactory(); 
      socket = (SSLSocket)factory.createSocket(); 

      availableProtocols = socket.getSupportedProtocols(); 
      Arrays.sort(availableProtocols); 
     } 
     catch(Exception e) 
     { 
      return new String[]{ "TLSv1" }; 
     } 
     finally 
     { 
      if(socket != null) 
       socket.close(); 
     } 

     List<String> aa = new ArrayList<String>(); 
     for(int i = 0; i < preferredProtocols.length; i++) 
     { 
      int idx = Arrays.binarySearch(availableProtocols, preferredProtocols[i]); 
      if(idx >= 0) 
       aa.add(preferredProtocols[i]); 
     } 

     return aa.toArray(new String[0]); 
    } 

    protected String[] GetCipherList() 
    { 
     String[] preferredCiphers = { 

      // *_CHACHA20_POLY1305 are 3x to 4x faster than existing cipher suites. 
      // http://googleonlinesecurity.blogspot.com/2014/04/speeding-up-and-strengthening-https.html 
      // Use them if available. Normative names can be found at (TLS spec depends on IPSec spec): 
      // http://tools.ietf.org/html/draft-nir-ipsecme-chacha20-poly1305-01 
      // http://tools.ietf.org/html/draft-mavrogiannopoulos-chacha-tls-02 
      "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", 
      "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", 
      "TLS_ECDHE_ECDSA_WITH_CHACHA20_SHA", 
      "TLS_ECDHE_RSA_WITH_CHACHA20_SHA", 

      "TLS_DHE_RSA_WITH_CHACHA20_POLY1305", 
      "TLS_RSA_WITH_CHACHA20_POLY1305", 
      "TLS_DHE_RSA_WITH_CHACHA20_SHA", 
      "TLS_RSA_WITH_CHACHA20_SHA", 

      // Done with bleeding edge, back to TLS v1.2 and below 
      "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", 
      "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", 
      "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 
      "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 

      "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 
      "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 
      "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 
      "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 

      // TLS v1.0 (with some SSLv3 interop) 
      "TLS_DHE_RSA_WITH_AES_256_CBC_SHA384", 
      "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", 
      "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", 
      "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", 

      "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", 
      "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", 
      "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", 
      "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", 

      // RSA key transport sucks, but they are needed as a fallback. 
      // For example, microsoft.com fails under all versions of TLS 
      // if they are not included. If only TLS 1.0 is available at 
      // the client, then google.com will fail too. TLS v1.3 is 
      // trying to deprecate them, so it will be interesteng to see 
      // what happens. 
      "TLS_RSA_WITH_AES_256_CBC_SHA256", 
      "TLS_RSA_WITH_AES_256_CBC_SHA", 
      "TLS_RSA_WITH_AES_128_CBC_SHA256", 
      "TLS_RSA_WITH_AES_128_CBC_SHA" 
     }; 

     String[] availableCiphers = null; 

     try 
     { 
      SSLSocketFactory factory = m_ctx.getSocketFactory(); 
      availableCiphers = factory.getSupportedCipherSuites(); 
      Arrays.sort(availableCiphers); 
     } 
     catch(Exception e) 
     { 
      return new String[] { 
       "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", 
       "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", 
       "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", 
       "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", 
       "TLS_RSA_WITH_AES_256_CBC_SHA256", 
       "TLS_RSA_WITH_AES_256_CBC_SHA", 
       "TLS_RSA_WITH_AES_128_CBC_SHA256", 
       "TLS_RSA_WITH_AES_128_CBC_SHA", 
       "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" 
      }; 
     } 

     List<String> aa = new ArrayList<String>(); 
     for(int i = 0; i < preferredCiphers.length; i++) 
     { 
      int idx = Arrays.binarySearch(availableCiphers, preferredCiphers[i]); 
      if(idx >= 0) 
       aa.add(preferredCiphers[i]); 
     } 

     aa.add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV"); 

     return aa.toArray(new String[0]); 
    } 

    private SSLContext m_ctx; 

    private String[] m_ciphers; 
    private String[] m_protocols; 
} 
+0

请注意:SSLContext.getInstance(“TLS”);'。它返回'SSL'和'TLS'协议;而不仅仅是“TLS”。例如,请参阅[SSLSocketFactoryEx](http://stackoverflow.com/a/23365536)以强制TLS(并删除SSL)。 – jww

+0

@jww更新!谢谢 – dosdebug

0

我推荐使用名为InstallCert的工具。它将下载自签名证书并将其导入新的信任库/密钥库。