Java网络编程——安全网络通信

在网络上,信息在由源主机到目标主机的传输过程中会经过其他计算机。在一般情况下,中间的计算机不会监听路过的信息。但在使用网上银行或者进行信用卡交易时,网络上的信息有可能被非法分子监听,从而导致个人隐私的泄露。由于Internet和Intranet体系结构存在一些安全漏洞,总有某些人能够截获并替换用户发出的原始信息。随着电子商务的不断发展,人们对信息安全的要求越来越高,于是Netscape公司提出了SSL协议,旨在达到在开放网络(Internet)上安全保密地传输信息的目的。

Java安全套接字扩展(Java Secure Socket Extension,JSSE)为基于SSL和TLS协议的Java网络应用程序提供了Java API以及参考实现。JSSE支持数据加密、服务器端身份验证、数据完整性以及可选的客户端身份验证。使用JSSE,能保证采用各种应用层协议(比如HTTP、Telnet和FTP等)的客户程序与服务器程序安全地交换数据。

JSSE封装了底层复杂的安全通信细节,使得开发人员能方便地利用它来开发安全的网络应用程序。

1、SSL简介

SSL(Secure Socket Layer,安全套接字层)是一种保证网络上的两个节点进行安全通信的协议。IETF(Internet Engineering Task Force)国际组织对SSL作了标准化,制定了RFC2246规范,并将其称为传输层安全(Transport Layer Security,TLS)。从技术上,目前的TLS1.0与SSL3.0的差别非常微小。

如下表所示:

SSL和TLS都建立在TCP/IP的基础上,一些应用层协议,如HTTP和IMAP,都可以采用SSL来保证安全通信。建立在SSL协议上的HTTP被称为HTTPS协议。HTTP使用的默认端口为80,而HTTPS使用的默认端口为443。

用户在网上商店购物,当他输入信用卡信息,进行网上支付交易时,存在以下不安全因素:

  • 用户的信用卡信息在网络上传输时有可能被他人截获。
  • 用户发送的信息在网络上传输时可能被非法篡改,数据完整性被破坏。
  • 用户正在访问的Web站点有可能是个非法站点,专门从事网上欺诈活动,比如骗取客户的资金。

SSL采用加密技术来实现安全通信,保证通信数据的保密性和完整性,并且保证通信双方可以验证对方的身份。

1.1、加密通信

当客户与服务器进行通信时,通信数据有可能被网络上的其他计算机非法监听,SSL使用加密技术实现会话双方信息的安全传递。加密技术的基本原理是:数据从一端发送到另一端时,发送者先对数据加密,然后把它发送给接收者。这样,在网络上传输的是经过加密的数据。如果有人在网络上非法截获了这批数据,由于没有解密的密钥,就无法获得真正的原始数据。接收者接收到加密的数据后,先对数据解密,然后处理。下图显示了采用SSL的通信过程。客户和服务器的加密通信需要在两端进行处理。

1.2、安全证书

除了对数据加密通信,SSL还采用了身份认证机制,确保通信双方都可以验证对方的真实身份。它和现时生活中我们使用身份证来证明自己的身份很相似。比如你到银行去取钱,你自称自己是张三,如何让对方相信你的身份呢?最有效的办法就是出示身份证。每人都拥有唯一的身份证,这个身份证上记录了你的真实信息。身份证由国家权威机构颁发,不允许伪造。在身份证不能被别人假冒复制的前提下,只要你出示身份证,就可以证明你自己的身份。

个人可以通过身份证来证明自己的身份,对于一个单位,比如商场,可以通过营业执照来证明身份。营业执照也由国家权威机构颁发,不允许伪造,它保证了营业执照的可信性。

SSL通过安全证书来证明客户或服务器的身份。当客户通过安全的连接和服务器通信时,服务器会先向客户出示它的安全证书,这个证书声明该服务器是安全的,而且的确是这个服务器。每一个证书在全世界范围内都是唯一的,其他非法服务器无法假冒原始服务器的身份。可以把安全证书比作"电子身份证"。

对于单个客户来说,到公认的权威机构去获取安全证书是一件麻烦的事。为了扩大客户群并且便于客户的访问,许多服务器不要求客户出示安全证书。在某些情况下,服务器也会要求客户出示安全证书,以便核实该客户的身份,这主要是在B2B(Business to Business)事务中。

获取安全证书有两种方式,一种方式是从权威机构获得证书,还有一种方式是创建自我签名证书。

1.从权威机构获得证书

安全证书可以有效地保证通信双方的身份的可信性。安全证书采用加密技术制作而成,他人几乎无法伪造。安全证书由国际权威的证书机构(Certificate Authority,CA)如GlobalSign和WoSign颁发,它们保证了证书的可信性。申请安全证书时,必须支付一定的费用。一个安全证书只对一个IP地址有效,如果用户的系统环境中有多个IP地址,就必须为每个IP地址都购买安全证书。

2.创建自我签名证书

在某些场合,通信双方只关心数据在网络上可以被安全传输,并不需要对方进行身份验证,在这种情况下,可以创建自我签名(self-assign)的证书,比如通过JDK提供的keytool工具就可以创建这样的证书。这样的证书就像用户自己制作的名片,缺乏权威性,达不到身份认证的目的。当你向对方递交名片时,名片上声称你是某个大公司的老总,信不信只能由对方自己去判断。

既然自我签名证书不能有效地证明自己的身份,那么有何意义呢?在技术上,无论是从权威机构获得的证书,还是自己制作的证书,采用的加密技术都是一样的,使用这些证书,都可以实现安全地加密通信。

1.3、SSL握手

安全证书既包含了用于加密数据的密钥,又包含了用于证实身份的数字签名。安全证书采用公钥加密技术。公钥加密指使用一对非对称的密钥进行加密或解密。每一对密钥由公钥和私钥组成。公钥被广泛发布。私钥是隐密的,不公开。用公钥加密的数据只能够被私钥解密。反过来,使用私钥加密的数据只能被公钥解密。这个非对称的特性使得公钥加密很有用。

在安全证书中包含了这一对非对称的密钥。只有安全证书的所有者才知道私钥。如下图所示:

安全证书中的数字签名部分则是通信方A的电子身份证。数字签名告诉通信方B该信息确实由通信方A发出,不是伪造的,也没有被篡改。

客户与服务器通信时,首先要进行SSL握手,SSL握手主要完成以下任务:

  • 协商使用的加密套件。加密套件中包括一组加密参数,这些参数指定了加密算法和密钥的长度等信息。
  • 验证对方的身份。此操作是可选的。
  • 确定使用的加密算法。

SSL握手过程采用非对称加密方法传递数据,由此来建立一个安全的会话。SSL握手完成后,通信双方将采用对称加密方法传递实际的应用数据。所谓对称加密,指通信双方使用同样的密钥来加密数据:

以下是SSL握手的具体流程:

  • (1)客户将自己的SSL版本号、加密参数、与会话有关的数据以及其他一些必要信息发送到服务器。
  • (2)服务器将自己的SSL版本号、加密参数、与会话有关的数据以及其他一些必要信息发送给客户,同时发送给客户的还有服务器的证书。如果服务器需要验证客户身份,那么服务器还会发出要求客户提供安全证书的请求。
  • (3)客户端验证服务器证书,如果验证失败,就提示不能建立SSL连接。如果成功,就继续下一步骤。
  • (4)客户端为本次会话生成预备主密码(pre-master secret),并将其用服务器公钥加密后发送给服务器。
  • (5)如果服务器要求验证客户身份,那么客户端还要再对另外一些数据签名后,将其与客户端证书一起发送给服务器。
  • (6)如果服务器要求验证客户身份,则检查签署客户证书的CA是否可信。如果不在信任列表中,则结束本次会话。如果检查通过,那么服务器用自己的私钥解密收到的预备主密码,并用它通过某些算法生成本次会话的主密码(master secret)。
  • (7)客户端与服务器均使用此主密码生成本次会话的会话密钥(对称密钥)。在双方SSL握手结束后传递任何消息均使用此会话密钥。这样做的主要原因是对称加密比非对称加密的运算量低一个数量级以上,能够显著提高双方会话时的运算速度。
  • (8)客户端通知服务器此后发送的消息都使用这个会话密钥进行加密,并通知服务器客户端已经完成本次SSL握手。
  • (9)服务器通知客户端此后发送的消息都使用这个会话密钥进行加密,并通知客户端服务器已经完成本次SSL握手。
  • (10)本次握手过程结束,会话已经建立。在接下来的会话过程中,双方使用同一个会话密钥分别对发送以及接收的信息进行加密和解密。

1.4、创建自我签名的安全证书

获得安全证书有两种方式:一种方式是到权威机构购买,还有一种方式是创建自我签名的证书,本节将介绍后一种方式。

JDK提供了制作证书的工具keytool。在JDK1.4以上版本中包含了这一工具,它的位置为:<JDK根目录>\bin\keytool.exe

keytool工具提出了密钥库的概念。密钥库中可以包含多个条目。每个条目包括一个自我签名的安全证书以及一对非对称密钥。

通过keytool工具创建密钥库的命令为:

以上命令将生成一个密钥库,这个密钥库中有一个条目。这个命令中的参数的意思如下:

  • -genkeypair:生成一对非对称密钥。
  • -alias:指定条目以及密钥对的别名,该别名是公开的。
  • -keyalg:指定加密算法,本例中采用通用的RSA算法。
  • -keystore:设定密钥库文件的存放路径以及文件名字。

该命令的运行过程如下图所示:

首先会提示输入密钥库的密码(口令),假定输入"123456",然后提示输入个人信息,如姓名、组织单位和所在城市等,只要输入真实信息即可。接着会提示输入信息是否正确,输入"y"表示信息正确。

以上命令将在操作系统的C:\chapter15目录下生成名为"test.keystore"的文件,它是一个密钥库文件,已经包含一个条目,这个条目的别名是"weiqin",该条目具有一对非对称密钥和自我签名的安全证书。

以下命令在test.keystore密钥库中再加入一个名为"lulu"的条目:

以下命令查看test.keystore密钥库的信息,会列出所包含的条目的信息:

以上命令的输出结果如下:

从以上输出结果可以看出,test.keystore密钥库中包含两个条目,别名分别为"weiqin"和"lulu"。

以下命令把test.keystore密钥库中别名为"weiqin"的条目导出到一个安全证书文件中,文件名为weiqin.crt:

以上命令将在C:\chapter15目录下生成一个安全证书文件weiqin.crt。在weiqin.crt文件中包含了自我签名的安全证书,以及密钥对中的公钥,但不包含密钥对中的私钥。

以下命令删除test.keystore密钥库中的别名为"weiqin"的条目:

以下命令把weiqin.crt安全证书导入testTrust.keystore密钥库中,生成别名为"weiqin"的条目,这个条目中包含密钥对中的公钥,但不包含密钥对中的私钥:

2、JSSE简介

JSSE封装了底层复杂的安全通信细节,使得开发人员能方便地用它来开发安全的网络应用程序。JSSE主要包括4个包:

  • javax.net.ssl包:包括进行安全通信的类,比如SSLServerSocket和SSLSocket类。
  • javax.net包:包括安全套接字的工厂类,比如SSLServerSocketFactory和SSLSocket Factory类。
  • java.security.cert包:包括处理安全证书的类,如X509Certificate类。X.509是由国际电信联盟(ITU-T)制定的安全证书的标准。
  • com.sun.net.ssl包:包括Oracle公司提供的JSSE的实现类。

JSSE API允许采用第三方提供的实现,该实现可作为插件集成到JSSE中。这些插件必须支持Oracle公司指定的加密套件,在Oracle官网上指定了这些加密套件,以下是其中的部分内容:

  • SSL_DHE_DSS_EXPORT_WITH_DES_40_CBC_SHA
  • SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
  • SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
  • SSL_DHE_RSA_EXPORT_WITH_DES_40_CBC_SHA
  • SSL_DH_ANON_EXPORT_WITH_DES40_CBC_SHA
  • SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
  • SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
  • SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA
  • TLS_DHE_DSS_WITH_AES_128_CBC_SHA
  • TLS_DHE_RSA_WITH_AES_128_CBC_SHA
  • TLS_DH_ANON_WITH_AES_128_CBC_SHA
  • TLS_DH_ANON_WITH_AES_256_CBC_SHA
  • TLS_DH_DSS_WITH_AES_128_CBC_SHA
  • SSL_CK_RC4_128_WITH_MD5

加密套件包括一组加密参数,这些参数指定了加密算法和密钥的长度等信息。以上列出的加密套件的名字包括4个部分:协议、密钥交换算法、加密算法和校验和。例如加密套件SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA表示采用SSL协议,密钥交换算法为DHE,加密算法为RSA。

JSSE具有以下重要特征:

  • 纯粹用Java语言编写。·可以出口到大多数国家。
  • 提供了支持SSL的JSSE API和JSSE实现。
  • 提供了支持TLS的JSSE API和JSSE实现。
  • 提供了用于创建安全连接的类,如SSLSocket、SSLServerSocket和SSLEngine。·支持加密通信。·支持客户端和服务器端的身份验证。
  • 支持SSL会话。·JSSE的具体实现会支持一些常用的加密算法,比如RSA(加密长度2048位)、RC4(密钥长度128位)和DH(密钥长度1024位)。

3、总结

Java安全套接字扩展(JSSE)为基于SSL和TLS协议的Java网络应用程序提供了Java API以及参考实现。JSSE支持数据加密、服务器端身份验证、数据完整性以及可选的客户端身份验证。使用JSSE,能保证采用各种应用层协议(比如HTTP、Telnet和FTP等)的客户程序与服务器程序安全地交换数据。

JSSE封装了底层复杂的安全通信细节,使得开发人员能方便地利用它来开发安全的网络应用程序。JSSE中负责安全通信的最核心的类是SSLServerSocket类与SSLSocket类,它们分别是ServerSocket与Socket类的子类。SSLSocket对象由SSLSocketFactory创建,此外,SSLServerSocket的accept()方法也会创建SSLSocket对象。SSLServerSocket对象由SSLServerSocketFactory创建。SSLSocketFactory和SSLServerSocketFactory对象都由SSLContext对象创建。SSLContext负责为SSLSocket和SSLSocketFactory设置安全参数,比如使用的安全协议、安全证书、KeyManager、TrustManager和安全随机数等。

相关推荐
吾日三省吾码2 小时前
JVM 性能调优
java
麻瓜也要学魔法2 小时前
链路状态路由协议-OSPF
网络
Estar.Lee3 小时前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
傻啦嘿哟3 小时前
代理IP在后端开发中的应用与后端工程师的角色
网络·网络协议·tcp/ip
弗拉唐3 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
Red Red4 小时前
网安基础知识|IDS入侵检测系统|IPS入侵防御系统|堡垒机|VPN|EDR|CC防御|云安全-VDC/VPC|安全服务
网络·笔记·学习·安全·web安全
oi774 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
2401_857610034 小时前
SpringBoot社团管理:安全与维护
spring boot·后端·安全