Android中的TLS/SSL(Https)浅谈

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xiaoxiao_job/article/details/53064611

最近在工作中,处理到了一些Https的技术点,所以,在这里做一个梳理和普及,本文将围绕三个问题展开:

1.Https是啥?

2.Android中怎么使用Https?

3.如何使用Charles等工具对Https链接抓包?

1.Https是啥?

以下是摘自网络的关于Https比较清晰的表述和原理:

Https和Http一样,都是我们浏览网页时候使用的一种协议。HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全。为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS

HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。TLS/SSL中使用了非对称加密,对称加密以及HASH算法。握手过程的简单描述如下:
1.浏览器将自己支持的一套加密规则发送给网站。
2.网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。
3.获得网站证书之后浏览器要做以下工作:
a) 验证证书的合法性(颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致等),如果证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示。
b) 如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。
c) 使用约定好的HASH计算握手消息,并使用生成的随机数对消息进行加密,最后将之前生成的所有信息发送给网站。
4.网站接收浏览器发来的数据之后要做以下的操作:
a) 使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。
b) 使用密码加密一段握手消息,发送给浏览器。
5.浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。
这里浏览器与网站互相发送加密的握手消息并验证,目的是为了保证双方都获得了一致的密码,并且可以正常的加密解密数据,为后续真正数据的传输做一次测试。另外,HTTPS一般使用的加密与HASH算法如下:
非对称加密算法:RSA,DSA/DSS
对称加密算法:AES,RC4,3DES
HASH算法:MD5,SHA1,SHA256
其中非对称加密算法用于在握手过程中加密生成的密码,对称加密算法用于对真正传输的数据进行加密,而HASH算法用于验证数据的完整性。由于浏览器生成的密码是整个数据加密的关键,因此在传输的时候使用了非对称加密算法对其加密。非对称加密算法会生成公钥和私钥,公钥只能用于加密数据,因此可以随意传输,而网站的私钥用于对数据进行解密,所以网站都会非常小心的保管自己的私钥,防止泄漏。

2.Android中怎么使用Https?

Android中使用https分为有安全证书和无安全证书两种情况,其实两者在代码上的差别并不大,有安全证书无非就是多了加载证书这一步,但是更加安全,没有证书容易被人仿冒。

以下以没有安全证书的情况为例:
1.首先,需要定义HostnameVerifier(主机名称匹配校验),这里我们不校验了,直接返回true即可,代码如下:

/**
 * Created by dwb on 2016/10/26.
 */
// 忽视证书HostName
public class MeituanVerifier
        implements HostnameVerifier
{
    public MeituanVerifier(MeituanHttp paramMeituanHttp)
    {

    }

    public boolean verify(String paramString, SSLSession paramSSLSession)
    {
        return true;
    }
}

2.然后,我们需要定义SocketFactory,主要是设置SSLContext(这个类是负责证书管理和信任管理的),可以看到主要是加载了一个null(证书管理器)和一个TrustAllManager(信任管理器)即可,代码如下:

    //信任所有的证书
    public  static class AllowAllSSLSocketFactory extends SSLSocketFactory
    {
        private SocketFactory socketFactory;
        private SSLContext sslContext;

        public AllowAllSSLSocketFactory()
        {
            try
            {
                this.sslContext = SSLContext.getInstance("TLS");
                TrustAllManager trustAllManager = new TrustAllManager(this);
                this.sslContext.init(null, new TrustManager[] { trustAllManager }, new SecureRandom());
                this.socketFactory = this.sslContext.getSocketFactory();
                return;
            }
            catch (NoSuchAlgorithmException localNoSuchAlgorithmException)
            {
                    localNoSuchAlgorithmException.printStackTrace();
            }
            catch (KeyManagementException localKeyManagementException)
            {
                    localKeyManagementException.printStackTrace();
            }
        }
    }
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

/**
 * Created by dwb on 2016/10/26.
 */

public class TrustAllManager implements X509TrustManager {
    public TrustAllManager (HttpUtil.AllowAllSSLSocketFactory paramAllowAllSSLSocketFactory)
    {

    }

    @Override
    public void checkClientTrusted(X509Certificate[] arg0, String arg1)
            throws CertificateException {
        // TODO Auto-generated method stub
    }

    @Override
    public void checkServerTrusted(X509Certificate[] arg0, String arg1)
            throws CertificateException {
        // TODO Auto-generated method stub
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        // TODO Auto-generated method stub
        return null;
    }
}

3.最后,在HttpURLConnection里设置下setSSLSocketFactory和setHostnameVerifier,比如:

        protected HttpURLConnection openConnection(Request paramRequest) throws IOException
        {
            localHttpURLConnection = super.openConnection(paramRequest);
            if ((localHttpURLConnection instanceof HttpsURLConnection))
            {
                if (this.hostnameVerifier != null)
                    ((HttpsURLConnection)localHttpURLConnection).setHostnameVerifier(this.hostnameVerifier);
                if (this.socketFactory != null)
                    ((HttpsURLConnection)localHttpURLConnection).setSSLSocketFactory(this.socketFactory);
            }
            return localHttpURLConnection;
        }

这样,就能建立https的访问请求了。

3.如何使用Charles等工具对Https连接抓包?

1.首先,下载Charles,下载链接如下:https://www.charlesproxy.com/download/
注意按照系统来下载相应版本
这里写图片描述

2.让安卓手机和电脑连接到同一个局域网内,然后设置安卓手机的代理,步骤如下:
一:查看电脑的ip地址,Mac系统可以在系统偏好设置-网络中相应的wifi节点下查看,Windows可以在cmd下ipconfig查看,例如,本机查询出来是192.168.100.7
这里写图片描述

二:打开手机的设置-无线网络-选择相应的wifi节点-高级设置-手动Http代理,代理服务器主机名填刚才查询出来的ip,代理服务器端口填写8888:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
经过上面的步骤,再打开Charles,你就能对http的请求进行抓包了,如下是对xx外卖的获取订单接口抓包:
这里写图片描述

3.打开Charles,Help- SSLProxying
这里写图片描述
然后在连接上好的安卓手机中,用安卓自带的浏览器,输入chls.pro/ssl 去下载证书并且安装,如下:
这里写图片描述
现在,就可以正式抓取https的链接了,如下是抓取的xx外卖的https订单请求:
这里写图片描述
安卓中的https大概就聊到这里!会持续更新~~

展开阅读全文

没有更多推荐了,返回首页