okhttp学习笔记--Https与SSL

https安全的http协议是建立在SSL层或TLS层上的http协议,在普通的传输层和http应用层之间插入SSL或TLS安全层。
https使用非对称加密进行加密秘钥协商,采用对称加密方式对报文进行加密处理以保证安全性
https不同于http,使用443端口作为默认端口,建立TCP连接后,会初始化SSL层,对加密参数进行沟通并交换秘钥。

非对称加密
数字签名技术

数字签名技术是为了证明数据的完整性,未经过的三方修改(发送者身份的真实性);主要包括两个方面:摘要算法和加密。
1.摘要算法通过哈希处理将原始信息转换成固定长度的序列,确保输入到输出的一一映射,原始信息的变化将导致输出结果的变化,常见的有MD5,SHA-1,SHA-256等。
2.加密采用非对称加密,私钥加密保证加密后的摘要信息无法更改
数字签名流程:
1、对原始信息进行摘要算法处理,得到摘要信息,使用私钥对摘要信息进行加密,生成签名。
2、签名与原始信息合并成最终签名文件发布
3、接收方使用公钥将签名文件中的数字签名进行解密
4、对原始信息进行摘要算法处理
5、对比3、4步的结果,一致说明文件未被更改;

数字证书

1.数字证书包含有公钥,证书有效期,发证机构等信息;数字证书需要向CA机构申请,获取到的数字证书是经过签名处理的。
2. CA机构的根证书是没有经过签名的数字证书,可以直接拿到其公钥。
3. CA机构颁发的次级证书已经使用私钥进行了签名处理,可以使用CA根证书中的公钥进行解密获得次级证书中的公钥。能正常解密才能说明次级证书的合法性。
4. 客户端持有CA根证书,在服务端发送申请到的数字证书给客户端后,客户端使用根证书公钥解密处理,验证服务端证书。

SSL握手过程

ssl握手过程完成加密算法的协商和加密秘钥的确定,双方数字证书的认证工作。
具体流程如下:
1.客户端发起连接请求,发送客户端支持的SSL版本号,加密算法(密码套件/Cipher Suites)列表,随机数给服务端
密码套件格式:每个套件都以“SSL”开头,紧跟着的是密钥交换算法。用“With”这个词把密钥交换算法、加密算法、散列算法分开,例如:SSL_DHE_RSA_WITH_DES_CBC_SHA, 表示把DHE_RSA(带有RSA数字签名的暂时Diffie-HellMan)定义为密钥交换算法;把DES_CBC定义为加密算法;把SHA定义为散列算法。
2.服务端在客户端支持的加密算法中选择一组,和服务端证书(包含公钥)、一个随机数一起发给客户端
3.客户端对服务端的证书进行验证并获取公钥,产生一个称作pre_master_secret的随机密码串,并使用服务器的公用密钥对其进行加密(参考非对称加/解密),并将加密后的信息发送给服务器;
4.客户端与服务器端根据pre_master_secret以及客户端与服务器的随机数值(第1,2步中的随机数)独立计算出加密和MAC密钥。

这里有三个秘钥:服务端证书传递的公钥,隐含的服务端持有的私钥,最终的加密秘钥;
公钥和私钥是非对称加密算法的秘钥,主要用于服务端和客户端协商生成最终的加密秘钥,保证协商过程的保密性
最终生成的加密秘钥匙对称加密算法的秘钥,主要用于后面数据交换的加密
pre_master_secret是客户端生成的一段随机码用于生成最终的加密秘钥(使用秘钥交换算法)。
以上流程是单向认证流程即只有客户端对服务端进行认证

java相关实现

相关类与接口:SSLCntext、SSLSocketFactory、TrustManager、KeyStore、TrustManagerFactory等,盗张图,类图如下
okhttp学习笔记--Https与SSL_第1张图片
SSLContext是SSL连接的上下文,设置SSL版本,创建SSLSocketFactory、SSLServerSocketFactory。
SSLSocketFactory是创建SSLSocket的工厂类,方法createSocket、getDefaultCipherSuites、getSupportedCipherSuites
SSLSocket继承自Socket,安全套接字
TrustManagerFactory TrustManager 认证信任逻辑处理,TrustManager对象有两种创建方式:1.使用Factory 2.继承
When initializing an SSLContext, you can use trust managers created from a trust manager factory, or you can write your own trust manager, for example, using the CertPath API. For details, see the Java PKI Programmer’s Guide. You do not need to use a trust manager factory if you implement a trust manager using the X509TrustManager interface.
KeyStore用于存储秘钥
更多相关资料参考资料6

okhttp中的SSL相关实现

okhttp中的默认SSL设置实现,由于一般只有单向认证,这里客户端的秘钥存储KeyStore为空,使用TrustManagerFactory生成默认的信任逻辑,TrustManagerFactory.getDefaultAlgorithm,Java8中默认是SunX509,AndroidSDK默认是PKIX

 private X509TrustManager systemDefaultTrustManager() {
    try {
      TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
          TrustManagerFactory.getDefaultAlgorithm());
      trustManagerFactory.init((KeyStore) null);
      TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
      if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
        throw new IllegalStateException("Unexpected default trust managers:"
            + Arrays.toString(trustManagers));
      }
      return (X509TrustManager) trustManagers[0];
    } catch (GeneralSecurityException e) {
      throw new AssertionError(); // The system has no TLS. Just give up.
    }
  }

  private SSLSocketFactory systemDefaultSslSocketFactory(X509TrustManager trustManager) {
    try {
      SSLContext sslContext = SSLContext.getInstance("TLS");
      sslContext.init(null, new TrustManager[] { trustManager }, null);
      return sslContext.getSocketFactory();
    } catch (GeneralSecurityException e) {
      throw new AssertionError(); // The system has no TLS. Just give up.
    }
  }

okhttp支持的加密算法在CipherSuite中以下是代码节选

public final class CipherSuite {
  /**
   * Holds interned instances. This needs to be above the of() calls below so that it's
   * initialized by the time those parts of {@code ()} run.
   */
  private static final ConcurrentMap INSTANCES = new ConcurrentHashMap<>();

  // Last updated 2016-07-03 using cipher suites from Android 24 and Java 9.

  // public static final CipherSuite TLS_NULL_WITH_NULL_NULL = of("TLS_NULL_WITH_NULL_NULL", 0x0000);
  public static final CipherSuite TLS_RSA_WITH_NULL_MD5 = of("SSL_RSA_WITH_NULL_MD5", 0x0001);
  public static final CipherSuite TLS_RSA_WITH_NULL_SHA = of("SSL_RSA_WITH_NULL_SHA", 0x0002);
  public static final CipherSuite TLS_RSA_EXPORT_WITH_RC4_40_MD5 = of("SSL_RSA_EXPORT_WITH_RC4_40_MD5", 0x0003);
  public static final CipherSuite TLS_RSA_WITH_RC4_128_MD5 = of("SSL_RSA_WITH_RC4_128_MD5", 0x0004);
  public static final CipherSuite TLS_RSA_WITH_RC4_128_SHA = of("SSL_RSA_WITH_RC4_128_SHA", 0x0005);
  // public static final CipherSuite TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = of("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5", 0x0006);
  // public static final CipherSuite TLS_RSA_WITH_IDEA_CBC_SHA = of("TLS_RSA_WITH_IDEA_CBC_SHA", 0x0007);
  public static final CipherSuite TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = of("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x0008);
  public static final CipherSuite TLS_RSA_WITH_DES_CBC_SHA = of("SSL_RSA_WITH_DES_CBC_SHA", 0x0009);
  public static final CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_SHA = of("SSL_RSA_WITH_3DES_EDE_CBC_SHA", 0x000a);
  // public static final CipherSuite TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = of("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", 0x000b);
  // public static final CipherSuite TLS_DH_DSS_WITH_DES_CBC_SHA = of("TLS_DH_DSS_WITH_DES_CBC_SHA", 0x000c);
  // public static final CipherSuite TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = of("TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", 0x000d);
  // public static final CipherSuite TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = of("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x000e);
  // public static final CipherSuite TLS_DH_RSA_WITH_DES_CBC_SHA = of("TLS_DH_RSA_WITH_DES_CBC_SHA", 0x000f);
  // public static final CipherSuite TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = of("TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", 0x0010);
  public static final CipherSuite TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = of("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", 0x0011);
  public static final CipherSuite TLS_DHE_DSS_WITH_DES_CBC_SHA = of("SSL_DHE_DSS_WITH_DES_CBC_SHA", 0x0012)

参考资料:
1.图解SSL/TLS协议
2.SSL协议详解
3.SSL握手过程
4.https连接的前几毫秒发生了什么
5.Java SSLSocket的使用
6.JSSERefGuide

你可能感兴趣的:(http,ssl,http协议,okhttp)