2012-05-14 9 views
5

मेरे समस्या:समीक्षा और भरोसा करने के लिए मैं एक अविश्वसनीय SSL सर्वर प्रमाणपत्र कैसे पुनर्प्राप्त करूं?

मैं सर्वर से कनेक्ट करना चाहते हैं (HTTPS प्रोटोकॉल तक ही सीमित नहीं - LDAP-ओवर-एसएसएल हो सकता है, SMTPS हो सकता है, IMAPS, आदि हो सकता है) कि प्रमाण पत्र का उपयोग कर किया जा सकता है कि जावा डिफ़ॉल्ट रूप से भरोसा नहीं करेंगे (क्योंकि वे स्वयं हस्ताक्षरित हैं)।

वांछित वर्कफ़्लो कनेक्शन का प्रयास करना, प्रमाण पत्र जानकारी पुनर्प्राप्त करना, उपयोगकर्ता को प्रस्तुत करना और यदि वह इसे स्वीकार करता है, तो इसे ट्रस्टस्टोर में जोड़ें ताकि इसे आगे बढ़ने पर भरोसा किया जा सके।

मैं प्रमाण पत्र पुनर्प्राप्त करने पर अटक गया हूं। मेरे पास कोड है (पोस्ट के अंत में देखें) कि मैंने जावा एसएसएल के बारे में सवालों के जवाब दिए गए साइटों से और साइट्स से खींचा है। कोड बस SSLSocket बनाता है, एसएसएल हैंडशेक शुरू करता है, और Certificate[] के लिए एसएसएल सत्र पूछता है। कोड पहले से भरोसेमंद प्रमाणपत्र का उपयोग कर किसी सर्वर से कनेक्ट होने पर ठीक काम करता है। लेकिन जब मैं एक स्व-हस्ताक्षरित प्रमाणपत्र का उपयोग कर एक सर्वर से कनेक्ट मैं हमेशा की तरह मिलता है:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: 
    sun.security.validator.ValidatorException: PKIX path building failed: 
    sun.security.provider.certpath.SunCertPathBuilderException: unable to 
    find valid certification path to requested target 
     at sun.security.ssl.Alerts.getSSLException(Unknown Source) 
     at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source) 
     at sun.security.ssl.Handshaker.fatalSE(Unknown Source) 
     at sun.security.ssl.Handshaker.fatalSE(Unknown Source) 
     at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source) 
     [etc] 

मैं देख रहा हूँ अगर मैं -Djavax.net.debug=all के साथ चलाने के JVM स्व-हस्ताक्षरित प्रमाणपत्र को पुनः प्राप्त लेकिन प्रयोग करने के लिए कनेक्शन को उड़ा होगा करता है कि उस बिंदु पर पहुंचने से पहले एक अविश्वसनीय प्रमाण जहां यह प्रमाण पत्र वापस करेगा।

चिकन-एंड-अंडे की समस्या की तरह लगता है। यह मुझे प्रमाणपत्र देखने नहीं देगा क्योंकि वे भरोसेमंद नहीं हैं। लेकिन मुझे प्रमाणपत्रों को ट्रस्टस्टोर में जोड़ने में सक्षम होने की आवश्यकता है ताकि उन्हें भरोसा किया जा सके। आप इससे कैसे बाहर निकलते हैं?

उदाहरण के लिए

, अगर मैं कार्यक्रम के रूप में चलाएँ:

java SSLTest www.google.com 443 

मैं प्रमाणपत्र गूगल उपयोग कर रहा है का एक प्रिंटआउट मिलता है। लेकिन अगर मैं इसे

java SSLTest my.imap.server 993 

पर ऊपर उल्लिखित अपवाद प्राप्त करता हूं।

कोड:

import java.io.InputStream; 
import java.io.OutputStream; 
import java.security.cert.*; 
import javax.net.SocketFactory; 
import javax.net.ssl.*; 

public class SSLTest 
{ 
    public static void main(String[] args) throws Exception { 
     if (args.length != 2) { 
      System.err.println("Usage: SSLTest host port"); 
      return; 
     } 

     String host = args[0]; 
     int port = Integer.parseInt(args[1]); 

     SocketFactory factory = SSLSocketFactory.getDefault(); 
     SSLSocket socket = (SSLSocket) factory.createSocket(host, port); 

     socket.startHandshake(); 

     Certificate[] certs = socket.getSession().getPeerCertificates(); 

     System.out.println("Certs retrieved: " + certs.length); 
     for (Certificate cert : certs) { 
      System.out.println("Certificate is: " + cert); 
      if(cert instanceof X509Certificate) { 
       try { 
        ((X509Certificate) cert).checkValidity(); 
        System.out.println("Certificate is active for current date"); 
       } catch(CertificateExpiredException cee) { 
        System.out.println("Certificate is expired"); 
       } 
      } 
     } 
    } 
} 

उत्तर

2
+3

धन्यवाद! बस जिस तरह की चीज मैं खोज रहा था। और रिकॉर्ड के लिए, यहां एक ही चीज़ का एक कंसोल-केवल संस्करण है: http://code.google.com/p/java-use-examples/source/browse/trunk/src/com/aw/ad/ util/InstallCert.java – QuantumMechanic

7

आप यह एक अस्थायी TrustManager कि सभी प्रमाणपत्र स्वीकार करता है और एक अस्थायी HostnameVerifier कि सभी के नाम की पुष्टि करता है को लागू करने से कर सकते हैं (जाहिर है आप और प्रमाण पत्र को पुनः प्राप्त करने ही उनका उपयोग नहीं कर के लिए निजी डेटा भेजने के लिए)।

निम्नलिखित कोड एक मनमाना HTTPS URL से प्रमाण पत्र को पुनः प्राप्त करने और उन्हें एक फ़ाइल में सहेज लें:

URL url = new URL("https://<yoururl>"); 

SSLContext sslCtx = SSLContext.getInstance("TLS"); 
sslCtx.init(null, new TrustManager[]{ new X509TrustManager() { 

    private X509Certificate[] accepted; 

    @Override 
    public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { 
    } 

    @Override 
    public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { 
     accepted = xcs; 
    } 

    @Override 
    public X509Certificate[] getAcceptedIssuers() { 
     return accepted; 
    } 
}}, null); 

HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); 

connection.setHostnameVerifier(new HostnameVerifier() { 

    @Override 
    public boolean verify(String string, SSLSession ssls) { 
     return true; 
    } 
}); 

connection.setSSLSocketFactory(sslCtx.getSocketFactory()); 

if (connection.getResponseCode() == 200) { 
    Certificate[] certificates = connection.getServerCertificates(); 
    for (int i = 0; i < certificates.length; i++) { 
     Certificate certificate = certificates[i]; 
     File file = new File("/tmp/newcert_" + i + ".crt"); 
     byte[] buf = certificate.getEncoded(); 

     FileOutputStream os = new FileOutputStream(file); 
     os.write(buf); 
     os.close(); 
    } 
} 

connection.disconnect(); 
संबंधित मुद्दे

 संबंधित मुद्दे