Https四次握手

2018-08-12  本文已影响0人  feifei_fly

Https 协议

Https是在Http协议只上 加上了SSL

Http四次握手协议

image

1、客户端请求建立SSL链接,并向服务端发送一个随机数–Client random和客户端支持的加密方法,比如RSA公钥加密,此时是明文传输。

  1. 服务端回复一种客户端支持的加密方法、一个随机数–Server random、授信的服务器证书和非对称加密的公钥。

3.客户端收到服务端的回复后利用服务端的公钥,加上新的随机数–Premaster secret 通过服务端下发的公钥及加密方法进行加密,发送给服务器。

  1. 服务端收到客户端的回复,利用已知的加解密方式进行解密,同时利用Client random、Server random和Premaster secret通过一定的算法生成HTTP链接数据传输的对称加密key – session key。

X509TrustManager 自定义证书信任类:

1、Android 中的证书管理类 是X509TrustManager。

X509TrustManager是一个接口类,自定义证书管理类 需要实现X509TrustManager接口

public interface X509TrustManager extends TrustManager {
   
   /*
   *
   */
    public void checkClientTrusted(X509Certificate[] chain, String authType)
        throws CertificateException;

   
    public void checkServerTrusted(X509Certificate[] chain, String authType)
        throws CertificateException;

    /**
     返回受信任的X509证书数组。
     */
    public X509Certificate[] getAcceptedIssuers();
}

该接口中只有三个方法:

2、自定义X509TrustManager

自定义509TrustManager其核心方法为checkServerTrusted 指定信任哪些服务端证书
实现思路如下:

(1)实现一个默认的X509TrustManager,来校验标准的CA证书,若校验通过则return。
(2)若默认509TrustManager 校验CA证书失败。则尝试校验我们是不是我们内置的证书,若校验通过直接return,不抛异常。
(3) 以上两步均为通过,则抛异常,判定证书不合法。

public class MyX509TrustManager implements X509TrustManager {
    private static final String TAG = "MyX509TrustManager";
    /*
     * The default X509TrustManager returned by SunX509.  We'll delegate
     * decisions to it, and fall back to the logic in this class if the
     * default X509TrustManager doesn't trust it.
     */
    private X509TrustManager sunJSSEX509TrustManager;

    //自签名keystore
    private KeyStore truststore;
    private List<X509Certificate> x509caList = new ArrayList<X509Certificate>(1); //存储自签名的 X509证书列表
    private List<InputStream> certificates;//自签名证书 输入流

    public static MyX509TrustManager newInstance(List<InputStream> certificates) {
        return new MyX509TrustManager(certificates);
    }

    private MyX509TrustManager(List<InputStream> certificates) {
        this.certificates = certificates;

        try {

            // create a "default" JSSE X509TrustManager.
            KeyStore ks = KeyStore.getInstance("JKS");

            TrustManager[] tms = new TrustManager[0];
            if (ks != null) {
                FileInputStream is = null;

                try {
                    is = new FileInputStream("trustedCerts");
                    ks.load(is, "passphrase".toCharArray());
                    TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509", "SunJSSE");
                    tmf.init(ks);
                    tms = tmf.getTrustManagers();
                } finally {
                    if (is != null) {
                        try {
                            is.close();
                        } catch (IOException e) {
                            LogUtil.e(TAG, e.getMessage(), e);
                        }

                    }

                    is = null;
                }
            } else {
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                tmf.init((KeyStore) null);
                tms = tmf.getTrustManagers();
            }

            /*
             * Iterate over the returned trustmanagers, look
             * for an instance of X509TrustManager.  If found,
             * use that as our "default" trust manager.
             */
            for (int i = 0; i < tms.length; i++) {
                if (tms[i] instanceof X509TrustManager) {
                    sunJSSEX509TrustManager = (X509TrustManager) tms[i];
                    break;
                }
            }

        } catch (Exception e) {
            try {
                TrustManager[] tms = new TrustManager[0];
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                tmf.init((KeyStore) null);
                tms = tmf.getTrustManagers();
                for (int i = 0; i < tms.length; i++) {
                    if (tms[i] instanceof X509TrustManager) {
                        sunJSSEX509TrustManager = (X509TrustManager) tms[i];
                        break;
                    }
                }
            } catch (Exception e1) {
                LogUtil.e(TAG, "@@@Couldn't initialize https ca JSSE|" + e.getMessage(), e);
            }

        }

        /**
         * 自签名初始化
         */
        this.truststore = createKeyStore(); //将自签名证书 加载KeyStore中
        try {
            Enumeration<String> aliasesIt = truststore.aliases();
            if (aliasesIt != null) {
                while (aliasesIt.hasMoreElements()) {
                    Certificate ca = truststore.getCertificate(aliasesIt.nextElement());

                    // Turn it to X509 format.
                    InputStream is = new ByteArrayInputStream(ca.getEncoded());
                    X509Certificate x509ca1 = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is);
                    x509caList.add(x509ca1);

                    //close input stream
                    closeIS(is);
                }
            }
        } catch (Exception e) {
            LogUtil.e(TAG, "@@@Couldn't initialize https ca custom|" + e.getMessage(), e);
        }


    }

    /*
     * Delegate to the default trust manager.
     */
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    /*
     * Delegate to the default trust manager.
     */

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

        //同时支持可信CA认证和自签名认证(任一种认证通过认为可信)

        boolean ok = false;

        //CA认证
        if (sunJSSEX509TrustManager != null) {
            try {

                sunJSSEX509TrustManager.checkServerTrusted(chain, authType);
                ok = true;
                LogUtil.i(TAG, "@@@@@@@@@@@@@@@@@ ca checkServerTrusted success");
                return;

            } catch (CertificateException e) {
                // do any special handling here, or rethrow exception.
                ok = false;
            }
        }

        //自签名认证
        try {

            for (X509Certificate cert : chain) {

                for (X509Certificate ca : x509caList) {
                    try {

                        cert.verify(ca.getPublicKey());
                        ok = true;
                        LogUtil.i(TAG, "@@@@@@@@@@@@@@@@@ custom checkServerTrusted success");
                        return;

                    } catch (Exception e) {
                        ok = false;
                    }
                }

            }


        } catch (Exception e) {
            // do any special handling here, or rethrow exception.
            ok = false;
        }

        if (!ok) {
            LogUtil.i(TAG, "@@@@@@@@@@@@@@@@@ checkServerTrusted fails");
            throw new CertificateException("https cert verify fails");
        }

    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return sunJSSEX509TrustManager.getAcceptedIssuers();
    }

    private static void closeIS(InputStream is) {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                LogUtil.e(TAG, e.getMessage(), e);
            }
        }
    }

    /**
     * 得到HTTPS KeyStore
     *
     * @return
     */
    private KeyStore createKeyStore() {


        // https支持
        try {

            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null, null);

            int index = 0;

            if (certificates != null && !certificates.isEmpty()) {
                for (InputStream is : certificates) {
                    try {

                        CertificateFactory cerFactory = CertificateFactory.getInstance("X509");
                        Certificate ca = cerFactory.generateCertificate(is);
                        String certificateAlias = Integer.toString(index++);
                        keyStore.setCertificateEntry(certificateAlias, ca);

                    } catch (Exception e) {
                        LogUtil.e(TAG, e.getMessage(), e);
                    } finally {
                        try {
                            if (is != null) {
                                is.close();
                            }
                        } catch (IOException e) {
                            LogUtil.e(TAG, e.getMessage(), e);
                        }
                    }
                }
            }

            return keyStore;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}

3、X509TrustManager的使用

//(1)创建SSLContext对象,并使用我们指定的信任管理器初始化
MyX509TrustManager trustManager = new MyX509TrustManager ()
TrustManager[] tm = {trustManager};
SSLContext sslContext = SSLContext.getInstance("SSL","SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());

//(2)从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();

//(3) 设置OkhttpClient的sslSocketFactory

        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(TimeOut, TimeUnit.SECONDS)
                .readTimeout(TimeOut,TimeUnit.SECONDS)
                .writeTimeout(TimeOut,TimeUnit.SECONDS)
                .sslSocketFactory(ssf, trustManager)//https证书认证
                .hostnameVerifier(new HttpsUtils.MyHostnameVerifier())//自定义了HostnameVerifier。在握手期间,如果 URL 的主机名和服务器的标识主机名不匹配,则验证机制可以回调此接口的实现程序来确定是否应该允许此连接。
                .addInterceptor(MakeupInterceptor.newInstance())
                .build();
        Retrofit retrofit = new Retrofit.Builder()
                .client(client)
                .baseUrl(URL)
                .addConverterFactory(ResponseConvertFactory.create())
               .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
         retrofit.create(RequestService.class);
    

Chares 大花瓶 抓包原理

实际上 Chares 作为中间人代理,对客户端伪装服务器,通知对服务器伪装客户端。

关键的两点:

参考链接:

https://www.zybuluo.com/Sweetfish/note/706401
https://www.jianshu.com/p/870451cb4eb0

上一篇 下一篇

猜你喜欢

热点阅读