您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 公司方案 > JavaSSL_TLS协议
JavaSSL/TLS安全通讯协议介绍Java的安全通讯在人类建立了通信系统之后,如何保证通信的安全始终是一个重要的问题。伴随着现代化通信系统的建立,人们利用数学理论找到了一些行之有效的方法来保证数字通信的安全。简单来说就是把两方通信的过程进行保密处理,比如对双方通信的内容进行加密,这样就可以有效防止偷听者轻易截获通信的内容。目前SSL(SecureSocketsLayer)及其后续版本TLS(TransportLayerSecurity)是比较成熟的通信加密协议,它们常被用于在客户端和服务器之间建立加密通信通道。各种开发语言都给出SSL/TLS协议的具体实现,Java也不例外。在JDK中有一个JSSE(javax.net.ssl)包,提供了对SSL和TLS的支持。通过其所提供的一系列API,开发者可以像使用普通Socket一样使用基于SSL或TLS的安全套接字,而不用关心SSL和TLS协议的细节,例如握手的流程等等。这使得利用Java开发安全的SSL/TLS服务器或客户端非常容易,本文将通过具体的例子来说明如何用Java语言来开发SSL/TLS应用。SSL/TLS协议的介绍SSL/TLS协议(RFC2246RFC4346)处于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。从协议内部的功能层面上来看,SSL/TLS协议可分为两层:1.SSL/TLS记录协议(SSL/TLSRecordProtocol),它建立在可靠的传输层协议(如TCP)之上,为上层协议提供数据封装、压缩、加密等基本功能。2.SSL/TLS握手协议(SSL/TLSHandshakeProtocol),它建立在SSL/TLS记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等初始化协商功能。从协议使用方式来看,又可以分成两种类型:1.SSL/TLS单向认证,就是用户到服务器之间只存在单方面的认证,即客户端会认证服务器端身份,而服务器端不会去对客户端身份进行验证。首先,客户端发起握手请求,服务器收到握手请求后,会选择适合双方的协议版本和加密方式。然后,再将协商的结果和服务器端的公钥一起发送给客户端。客户端利用服务器端的公钥,对要发送的数据进行加密,并发送给服务器端。服务器端收到后,会用本地私钥对收到的客户端加密数据进行解密。然后,通讯双方都会使用这些数据来产生双方之间通讯的加密密钥。接下来,双方就可以开始安全通讯过程了。2.SSL/TLS双向认证,就是双方都会互相认证,也就是两者之间将会交换证书。基本的过程和单向认证完全一样,只是在协商阶段多了几个步骤。在服务器端将协商的结果和服务器端的公钥一起发送给客户端后,会请求客户端的证书,客户端则会将证书发送给服务器端。然后,在客户端给服务器端发送加密数据后,客户端会将私钥生成的数字签名发送给服务器端。而服务器端则会用客户端证书中的公钥来验证数字签名的合法性。建立握手之后过程则和单向通讯完全保持一致。SSL/TLS协议建立通讯的基本流程如图1所示,图1.SSL/TLS基本流程图步骤1.ClientHello–客户端发送所支持的SSL/TLS最高协议版本号和所支持的加密算法集合及压缩方法集合等信息给服务器端。步骤2.ServerHello–服务器端收到客户端信息后,选定双方都能够支持的SSL/TLS协议版本和加密方法及压缩方法,返回给客户端。(可选)步骤3.SendCertificate–服务器端发送服务端证书给客户端。(可选)步骤4.RequestCertificate–如果选择双向验证,服务器端向客户端请求客户端证书。步骤5.ServerHelloDone–服务器端通知客户端初始协商结束。(可选)步骤6.ResponseCertificate–如果选择双向验证,客户端向服务器端发送客户端证书。步骤7.ClientKeyExchange–客户端使用服务器端的公钥,对客户端公钥和密钥种子进行加密,再发送给服务器端。(可选)步骤8.CertificateVerify–如果选择双向验证,客户端用本地私钥生成数字签名,并发送给服务器端,让其通过收到的客户端公钥进行身份验证。步骤9.CreateSecretKey–通讯双方基于密钥种子等信息生成通讯密钥。步骤10.ChangeCipherSpec–客户端通知服务器端已将通讯方式切换到加密模式。步骤11.Finished–客户端做好加密通讯的准备。步骤12.ChangeCipherSpec–服务器端通知客户端已将通讯方式切换到加密模式。步骤13.Finished–服务器做好加密通讯的准备。步骤14.Encrypted/DecryptedData–双方使用客户端密钥,通过对称加密算法对通讯内容进行加密。步骤15.ClosedConnection–通讯结束后,任何一方发出断开SSL连接的消息。除了以上的基本流程,SSL/TLS协议本身还有一些概念需要在此解释说明一下。Key:Key是一个比特(bit)字符串,用来加密解密数据的,就像是一把开锁的钥匙。对称算法(symmetriccryptography):就是需要双方使用一样的key来加密解密消息算法,常用密钥算法有DataEncryptionStandard(DES)、triple-strengthDES(3DES)、RivestCipher2(RC2)和RivestCipher4(RC4)。因为对称算法效率相对较高,因此SSL会话中的敏感数据都用通过密钥算法加密。非对称算法(asymmetriccryptography):就是key的组成是公钥私钥对(key-pair),公钥传递给对方私钥自己保留。公钥私钥算法是互逆的,一个用来加密,另一个可以解密。常用的算法有RivestShamirAdleman(RSA)、Diffie-Hellman(DH)。非对称算法计算量大比较慢,因此仅适用于少量数据加密,如对密钥加密,而不适合大量数据的通讯加密。公钥证书(publickeycertificate):公钥证书类似数字护照,由受信机构颁发。受信组织的公钥证书就是certificateauthority(CA)。多证书可以连接成证书串,第一个是发送人,下一个是给其颁发证书实体,往上到根证书是世界范围受信组织,包括VeriSign,Entrust,和GTECyberTrust。公钥证书让非对称算法的公钥传递更安全,可以避免身份伪造,比如C创建了公钥私钥,对并冒充A将公钥传递给B,这样C与B之间进行的通讯会让B误认是A与B之间通讯。加密哈希功能(CryptographicHashFunctions):加密哈希功能与checksum功能相似。不同之处在于,checksum用来侦测意外的数据变化而前者用来侦测故意的数据篡改。数据被哈希后产生一小串比特字符串,微小的数据改变将导致哈希串的变化。发送加密数据时,SSL会使用加密哈希功能来确保数据一致性,用来阻止第三方破坏通讯数据完整性。SSL常用的哈希算法有MessageDigest5(MD5)和SecureHashAlgorithm(SHA)。消息认证码(MessageAuthenticationCode):消息认证码与加密哈希功能相似,除了它需要基于密钥。密钥信息与加密哈希功能产生的数据结合就是哈希消息认证码(HMAC)。如果A要确保给B发的消息不被C篡改,他要按如下步骤做--A首先要计算出一个HMAC值,将其添加到原始消息后面。用A与B之间通讯的密钥加密消息体,然后发送给B。B收到消息后用密钥解密,然后重新计算出一个HMAC,来判断消息是否在传输中被篡改。SSL用HMAC来保证数据传输的安全。数字签名(DigitalSignature):一个消息的加密哈希被创建后,哈希值用发送者的私钥加密,加密的结果就是叫做数字签名。JSSE(JavaSecureSocketExtension)使用介绍在JavaSDK中有一个叫JSSE(javax.net.ssl)包,这个包中提供了一些类来建立SSL/TLS连接。通过这些类,开发者就可以忽略复杂的协议建立流程,较为简单地在网络上建成安全的通讯通道。JSSE包中主要包括以下一些部分:安全套接字(securesocket)和安全服务器端套接字非阻塞式SSL/TLS数据处理引擎(SSLEngine)套接字创建工厂,用来产生SSL套接字和服务器端套接字套接字上下文,用来保存用于创建和数据引擎处理过程中的信息符合X.509规范密码匙和安全管理接口下面将通过一个简单的例子来展示如何通过JSSE,在客户端和服务器端建立一个SSL/TLS连接。设计两个类SSLClient和SSLServer,分别来表示客户端和服务器端。客户端将会向服务器端发起连接请求,在通过服务器端验证建立SSL连接后,服务器端将会向客户端发送一串内容,客户端将会把收到的内容打印出来。样例代码如下,SSLClientSourcecode:packageexample.ssl.codes;importjava.io.*;importjavax.net.ssl.SSLSocket;importjavax.net.ssl.SSLSocketFactory;classSSLClient{privateSSLSocketsocket=null;publicSSLClient()throwsIOException{//通过套接字工厂,获取一个客户端套接字SSLSocketFactorysocketFactory=(SSLSocketFactory)SSLSocketFactory.getDefault();socket=(SSLSocket)socketFactory.createSocket(localhost,7070);}publicvoidconnect(){try{//获取客户端套接字输出流PrintWriteroutput=newPrintWriter(newOutputStreamWriter(socket.getOutputStream()));//将用户名和密码通过输出流发送到服务器端StringuserName=principal;output.println(userName);Stringpassword=credential;output.println(password);output.flush();//获取客户端套接字输入流BufferedReaderinput=newBufferedReader(newInputStreamReader(socket.getInputStream()));//从输入流中读取服务器端传送的数据内容,并打印出来Stringresponse=input.readLine();response+=\n+input.readLine();System.out.println(response);//关闭流资源和套接字资源output.close();input.close();socket.close();}catch(IOExceptionioException){ioException.printStackTrace();}finally{System.exit(0);}}publicstaticvoidmain(Stringargs[])throwsIOException{newSSLClient().connect();}}SSLServerSourcecode:packageexample.ssl.codes;importjava.io.*;importjavax.net.ssl.SSLServerSocket;importjavax.net.ssl.SSLServerSocketFactory;importjavax.net.ssl.SSLSocket;classSSLServer{//服务器端授权的用户名和密码privatestaticfinalStringUSER_NAME
本文标题:JavaSSL_TLS协议
链接地址:https://www.777doc.com/doc-2878443 .html