什么是SSL
SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密。
SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。SSL协议可分为两层: SSL记录协议(SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能的支持。 SSL握手协议(SSL Handshake Protocol):它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。[百度百科]
SSL记录协议
SSL纪录协议(Record Protocol)为SSL连提供两种服务。
- 保密性:利用握手协议所定义的共享密钥对SSL净荷(Payload)加密。
- 完整性:利用握手协议所定义的共享的MAC密钥来生成报文的鉴别码(MAC)。
工作流程
发送方
- 从应用层获取要发送的数据(包括各种消息和数据)
- 对信息进行分段,分成若干纪录
- 使用指定的压缩算法进行数据压缩(Optional)
- 使用指定的MAC算法生成MAC
- 使用指定的加密算法进行数据加密(RC4)
- 添加SSL纪录协议的头,发送数据
接收方
- 接收数据并从SSL纪录协议的头中获取相关信息
- 使用指定的解密算法解密数据(RC4)
- 使用指定的MAC算法校验MAC
- 使用压缩算法对数据解压缩(如指定)
- 将纪录进行数据重组
- 将数据发送给应用层
SSL握手协议
SSL握手协议(Handshake Protocol)提供为SSL提供加密信道的建立服务。
- 身份认证:通过证书或者可信公钥文件进行身份认证
- 协商密钥:通过信息交换,相互协商一个流加密密钥
原理
SSL在信道加密之前,首先要进行握手通信,协商出流加密密钥,其握手过程如下图:
在网页浏览过程中,网站服务器为Client端,浏览器为Server端。这是因为此时网站为不可信源,所以需要对不可信源进行验证。
在Android开发过程中,APP为不可信源,所以APP为Client端,服务器为Server端。
从上图可以看出,当建立连接时,客户端主动发起请求,服务器监听后应答,并寻求身份验证,身份验证可通过证书或者服务器所发送的公钥进行识别。客户端发送服务器签发的证书或者公钥信息、随机密码,服务器验证后也会发送给客户端一个随机密码,当双方都有一对随机密码后,通过协商的算法将一对随机密码合成为最终的流加密密钥,到此握手协商完成。
SSLEngine的使用
SSLEngine的握手流程
在实际开发过程中,一般使用 SSLEngine进行SSL信道建立。SSLEngine可以和阻塞、非阻塞的Socket一起工作。
阻塞的Socket一般为SSLServerSocket和SSLSocke,虽然使用方便,但是扩展性和并发性较差。没法满足大并发的业务要求,所以暂且不在继续分析。
非阻塞的Socket一般是与SocketChannel结合使用。SSLEngine在工作时,有以下几个阶段:
- 创建:在此阶段,程序可以设置SSLEngine,其中包括:证书或者公钥文件的指定、通过SSLContext生成SSLEngine、设置SSLEngine在握手过程中的角色身份。
- 握手协商: SSLEngine根据上一节的握手过程进行握手操作。
- 数据传输:握手完成后,SSLEngine通过协商的流密钥进行加解密数据并传输数据。
- 重新握手:程序可以在数据传输的任意时间,请求重新协商握手密钥。SSLEngine会重置通信参数,但不能更改客户端/服务器角色模式,设置完成后,会在下一次通信中开始重新握手。
- 关闭引擎: 当关闭SSLEngine时,SSLEngine会完成剩余数据的处理工作,并关闭连接。
SSLEngine的状态标志
SSLEngine在握手协商过程中会根据握手数据交互,设置自己的不同状态:NEED_UNWRAP、NEED_WRAP、NEED_TASK、FINISHED、NOT_HANDSHAKING。
- NEED_UNWRAP: SSLEngine在等待握手数据时,状态为NEED_UNWRAP,表明为解包数据的状态。
- NEED_TASK:由于SSLEngine为异步处理,所以当进行解包完毕后,采用回调方式触发,这个中间过程SSLEngine状态为NEED_TASK。
- NEED_WRAP:当解包数据处理完毕后,SSLEngine的状态为NEED_WRAP,这时候是将回告数据打包,等待下一步操作。
- FINISHED:当握手协商结束时,SSLEngine的状态为FINISHED,SSLEngine准备做随后的一些整理操作。
- NOT_HANDSHAKING:此时的SSLEngine已经完成握手协商,准备对应用数据进行加解密处理。
Naga 库中 SSL 使用
Naga提供了对SSL的支持,并且通过封装NIOServerSocketSSL、SSLServerSocketChannelResponder、SSLSocketChannelResponder、SSLSocketObserver使SSL与channel完美结合,形成AIO Sokcet + SSL完整的通信加密方案。
自签名认证证书的申请
SSLEngine认证过程中有时需要使用自签名的认证证书及其认证文件,SSLContext可以引入自签名文件并由SSLContext.createSSLEngine()所产生SSLEngine,由于SSLContext