https淺析

單向驗證:

生成證書:

keytool -genkey -alias zhy_server -keyalg RSA -keystore zhy_server.jks -validity 3600 -storepass 123456 -ext san=ip:192.168.1.113(你本地的ip地址)

tomcat配置:

<Connector SSLEnabled="true" acceptCount="100" clientAuth="false" 
        disableUploadTimeout="true" enableLookups="true" keystoreFile="C:/Users/Administrator/zhy_server.jks" keystorePass="123456" maxSpareThreads="75" 
        maxThreads="200" minSpareThreads="5" port="8443" 
        protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https" 
        secure="true" sslProtocol="TLS"
      /> 

雙向驗證:

生成證書:

客戶端證書:

keytool -genkey -alias zhy_client -keyalg RSA -keystore zhy_client.jks -validity 3600 -storepass 123456 -ext san=ip:192.168.1.113
keytool -export -alias zhy_client -file zhy_client.cer -keystore zhy_client.jks -storepass 123456

將公鑰放進jks文件中再配置到tomcat,
keytool -import -alias zhy_client -file zhy_client.cer -keystore zhy_client_for_sever.jks

tomcat配置:

<Connector SSLEnabled="true" acceptCount="100"  
        disableUploadTimeout="true" enableLookups="true" keystoreFile="C:/Users/Administrator/zhy_server.jks" keystorePass="123456" maxSpareThreads="75" 
        maxThreads="200" minSpareThreads="5" port="8443" 
        protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https" 
        secure="true" sslProtocol="TLS"
        clientAuth="true"
        truststoreFile="C:/Users/Administrator/zhy_client_for_sever.jks"
      /> 

android客戶端公鑰變成字符串,使用命令:

keytool -printcert -rfc -file zhy_server.cer

HttpsUrlConnection使用

1、直連

Android系統校驗服務端數字證書的合法性,用可信CA簽發的數字證書的網站纔可以正常訪問,私有CA簽發的數字證書的網站無法訪問。
示例:

            URL url = new URL("https://www.alipay.com/");
            HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
            InputStream input = urlConnection.getInputStream();

            BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
            StringBuffer result = new StringBuffer();
            String line = "";
            while ((line = reader.readLine()) != null) {
                result.append(line);
            }

2、自己生成的證書

單向:

CertificateFactory cf = CertificateFactory.getInstance("X.509");
        Certificate ca = cf.generateCertificate(in);
        in.close();

        KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
        keystore.load(null, null);
        keystore.setCertificateEntry("ca", ca);

        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keystore);

        X509TrustManager trustManager = null;
        trustManager = new MyTrustManager(chooseTrustManager(tmf.getTrustManagers()));

        // Create an SSLContext that uses our TrustManager
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, new TrustManager[]{trustManager}, new SecureRandom());
        URL url = new URL(urlString);
        HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
        urlConnection.setSSLSocketFactory(context.getSocketFactory());
        InputStream input = urlConnection.getInputStream();

        BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
        StringBuffer result = new StringBuffer();
        String line = "";
        while ((line = reader.readLine()) != null) {
            result.append(line);
        }

其中MyTrustManager先會用系統信任的證書列表去校驗服務器的證書,如果不是CA簽發的,再用預埋的服務器端公鑰證書(上面的in輸入流代表的證書)處理。

雙向:

CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream in = activity.getAssets().open("zhy_server.cer");
        Certificate ca = cf.generateCertificate(in);

        KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
        keystore.load(null, null);
        keystore.setCertificateEntry("ca", ca);

        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keystore);

        /*雙向驗證*/
        KeyStore clientKeyStore = KeyStore.getInstance("bks");
        //Java平臺默認識別jks格式的證書文件,但是android平臺只識別bks格式的證書文件。用Portecle進行轉化

        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(clientKeyStore, "123456".toCharArray());
        // Create an SSLContext that uses our TrustManager
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
        URL url = new URL("https://10.5.20.34:8443/");
        HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
        urlConnection.setSSLSocketFactory(context.getSocketFactory());
        InputStream input = urlConnection.getInputStream();

        BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
        StringBuffer result = new StringBuffer();
        String line = "";
        while ((line = reader.readLine()) != null) {
            result.append(line);
        }

Fiddler查看

1、用預埋的證書校驗服務器,也查看不到響應數據
2、沒做校驗、信任所有的話,能看到響應數據

參考資料:
Android安全開發之安全使用HTTPS
Android Https相關完全解析 當OkHttp遇到Https
使用HTTPS與SSL

源碼:
https://yunpan.cn/cvtqXAKJwn44S (提取碼:25fc)

發佈了59 篇原創文章 · 獲贊 5 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章