深入理解JavaHTTPS中的公钥与证书交互
==========================
一、引言
随着网络安全意识的不断提高,HTTPS已成为现代Web应用不可或缺的一部分。
在HTTPS通信过程中,公钥和证书扮演着至关重要的角色。
Java作为流行的编程语言,支持HTTPS协议的通信,其中涉及到公钥和证书的交互。
本文将深入解析Java HTTPS中的公钥与证书交互过程。
二、HTTPS概述
HTTPS是一种通过计算机网络进行安全通信的协议,它是在HTTP协议基础上通过SSL(Secure Sockets Layer)或TLS(Transport Layer Security)协议提供的安全通信通道。
HTTPS协议采用公钥加密技术,确保数据传输过程中的安全性。
三、公钥与证书基础
1. 公钥:公钥是一种加密算法,用于加密数据。与之相对应的是私钥,用于解密数据。公钥可以公开分享,而私钥则需要妥善保管。
2. 证书:证书是一种包含公钥、所有者信息以及一个数字签名的电子文档。证书由可信任的第三方机构(如证书颁发机构CA)签发,用于验证公钥所有者的身份。
四、Java HTTPS中的公钥与证书交互过程
在Java中使用HTTPS进行通信时,涉及到以下公钥和证书的交互过程:
1. 客户端向服务器发起HTTPS请求。
2. 服务器接收到请求后,会返回一个包含其公钥的证书。这个证书由服务器信任的证书颁发机构(CA)签发。
3. 客户端接收到服务器返回的证书后,会验证证书的合法性。这个过程包括检查证书的颁发机构是否可信、证书是否过期以及域名是否匹配等。如果证书验证通过,则继续下一步;否则,客户端会中断通信并报告错误。
4. 客户端使用从证书中获取的服务器公钥对服务器发送的数据进行解密。同时,客户端会生成一个随机的对称密钥(如AES密钥),并使用服务器的公钥进行加密,然后将加密后的对称密钥发送给服务器。这个过程称为密钥交换。
5. 服务器接收到加密的对称密钥后,使用自己的私钥解密得到对称密钥。此后,服务器和客户端之间的通信将使用对称密钥进行加密和解密。由于对称密钥的加密和解密速度较快,因此可以提高通信效率。
6. 在整个通信过程中,服务器和客户端都可以通过公钥和证书实现身份的相互验证,确保通信的双方是可信的。
五、Java中实现HTTPS通信的示例代码
在Java中,可以使用`HttpsURLConnection`或`SSLContext`等类实现HTTPS通信。以下是一个简单的使用`HttpsURLConnection`实现HTTPS通信的示例代码:
“`java
import java.io.;
import java.net.;
import java.security.;
import javax.net.ssl.;
public class HttpsURLConnectionExample {
publicstatic void main(String[] args) throws Exception {
URL url = newURL(connection = (HttpsURLConnection) url.openConnection();
SSLContext sslContext = SSLContext.getInstance(TLS); // 使用TLS协议进行安全通信
sslContext.init(null,null, null); // 不使用特定的密钥管理器和信任管理器,使用默认设置即可满足大多数需求
connection.setSSLSocketFactory(sslContext.getSocketFactory()); // 设置SSLSocket工厂以使用自定义的SSLContext进行安全通信
InputStreaminputStream = connection.getInputStream(); // 获取输入流以读取响应数据
//… 其他处理响应数据的代码 …
}
}
“`
六、总结与展望
本文深入解析了Java HTTPS中的公钥与证书交互过程,并介绍了在Java中实现HTTPS通信的示例代码。
随着网络安全技术的不断发展,对HTTPS协议的理解和应用将变得越来越重要。
未来,随着TLS协议的升级和新技术的应用,Java HTTPS中的公钥与证书交互过程可能会有新的变化和发展趋势。
因此,我们需要持续关注网络安全领域的最新动态和技术发展,以便更好地理解和应用JavaHTTPS中的公钥与证书交互技术。
HTTPS请求证书时候的握手是SSL/ TLS 还是TCP的握手?
1. HTTPS是基于SSL安全连接的HTTP协议。
HTTPS通过SSL提供的数据加密、身份验证和消息完整性验证等安全机制,为Web访问提供了安全性保证,广泛应用于网上银行、电子商务等领域。
此图为HTTPS在网上银行中的应用。
某银行为了方便客户,提供了网上银行业务,客户可以通过访问银行的Web服务器进行帐户查询、转帐等。
通过在客户和银行的Web服务器之间建立SSL连接,可以保证客户的信息不被非法窃取。
2.只需要验证SSL服务器身份,不需要验证SSL客户端身份时,SSL的握手过程为:(1) SSL客户端通过Client Hello消息将它支持的SSL版本、加密算法、密钥交换算法、MAC算法等信息发送给SSL服务器。
(2) SSL服务器确定本次通信采用的SSL版本和加密套件,并通过Server Hello消息通知给SSL客户端。
如果SSL服务器允许SSL客户端在以后的通信中重用本次会话,则SSL服务器会为本次会话分配会话ID,并通过Server Hello消息发送给SSL客户端。
(3) SSL服务器将携带自己公钥信息的数字证书通过Certificate消息发送给SSL客户端。
(4) SSL服务器发送Server Hello Done消息,通知SSL客户端版本和加密套件协商结束,开始进行密钥交换。
(5) SSL客户端验证SSL服务器的证书合法后,利用证书中的公钥加密SSL客户端随机生成的premaster secret,并通过Client Key Exchange消息发送给SSL服务器。
(6) SSL客户端发送Change Cipher Spec消息,通知SSL服务器后续报文将采用协商好的密钥和加密套件进行加密和MAC计算。
(7) SSL客户端计算已交互的握手消息(除Change Cipher Spec消息外所有已交互的消息)的Hash值,利用协商好的密钥和加密套件处理Hash值(计算并添加MAC值、加密等),并通过Finished消息发送给SSL服务器。
SSL服务器利用同样的方法计算已交互的握手消息的Hash值,并与Finished消息的解密结果比较,如果二者相同,且MAC值验证成功,则证明密钥和加密套件协商成功。
(8) 同样地,SSL服务器发送Change Cipher Spec消息,通知SSL客户端后续报文将采用协商好的密钥和加密套件进行加密和MAC计算。
(9) SSL服务器计算已交互的握手消息的Hash值,利用协商好的密钥和加密套件处理Hash值(计算并添加MAC值、加密等),并通过Finished消息发送给SSL客户端。
SSL客户端利用同样的方法计算已交互的握手消息的Hash值,并与Finished消息的解密结果比较,如果二者相同,且MAC值验证成功,则证明密钥和加密套件协商成功。
SSL客户端接收到SSL服务器发送的Finished消息后,如果解密成功,则可以判断SSL服务器是数字证书的拥有者,即SSL服务器身份验证成功,因为只有拥有私钥的SSL服务器才能从Client Key Exchange消息中解密得到premaster secret,从而间接地实现了SSL客户端对SSL服务器的身份验证。
& 说明:l Change Cipher Spec消息属于SSL密码变化协议,其他握手过程交互的消息均属于SSL握手协议,统称为SSL握手消息。
l 计算Hash值,指的是利用Hash算法(MD5或SHA)将任意长度的数据转换为固定长度的数据。
java中的ssh框架原理
典型的J2EE三层结构,分为表现层、中间层(业务逻辑层)和数据服务层。
三层体系将业务规则、数据访问及合法性校验等工作放在中间层处理。
客户端不直接与数据库交互,而是通过组件与中间层建立连接,再由中间层与数据库交互。
表现层是传统的JSP技术,自1999年问世以来,经过多年的发展,其广泛的应用和稳定的表现,为其作为表现层技术打下了坚实的基础。
中间层采用的是流行的Spring+Hibernate,为了将控制层与业务逻辑层分离,又细分为以下几种。
Web层,就是MVC模式里面的“C”(controller),负责控制业务逻辑层与表现层的交互,调用业务逻辑层,并将业务数据返回给表现层作组织表现,该系统的MVC框架采用Struts。
Service层(就是业务逻辑层),负责实现业务逻辑。
业务逻辑层以DAO层为基础,通过对DAO组件的正面模式包装,完成系统所要求的业务逻辑。
DAO层,负责与持久化对象交互。
该层封装了数据的增、删、查、改的操作。
PO,持久化对象。
通过实体关系映射工具将关系型数据库的数据映射成对象,很方便地实现以面向对象方式操作数据库,该系统采用Hibernate作为ORM框架。
Spring的作用贯穿了整个中间层,将Web层、Service层、DAO层及PO无缝整合,其数据服务层用来存放数据。
一个良好的框架可以让开发人员减轻重新建立解决复杂问题方案的负担和精力;它可以被扩展以进行内部的定制化;并且有强大的用户社区来支持它。
框架通常能很好的解决一个问题。
然而,你的应用是分层的,可能每一个层都需要各自的框架。
仅仅解决UI问题并不意味着你能够很好的将业务逻辑和持久性逻辑和UI 组件很好的耦合。
不可否认,对于简单的应用,采用ASP或者PHP的开发效率比采用J2EE框架的开发效率要高。
甚至有人会觉得:这种分层的结构,比一般采用JSP + Servlet的系统开发效率还要低。
笔者从一下几个角度来阐述这个问题。
— 开发效率:软件工程是个特殊的行业,不同于传统的工业,例如电器、建筑及汽车等行业。
这些行业的产品一旦开发出来,交付用户使用后将很少需要后续的维护。
但软件行业不同,软件产品的后期运行维护是个巨大的工程,单纯从前期开发时间上考虑其开发效率是不理智的,也是不公平的。
众所周知,对于传统的ASP和 PHP等脚本站点技术,将整个站点的业务逻辑和表现逻辑都混杂在ASP或PHP页面里,从而导致页面的可读性相当差,可维护性非常低。
即使需要简单改变页面的按钮,也不得不打开页面文件,冒着破坏系统的风险。
但采用严格分层J2EE架构,则可完全避免这个问题。
对表现层的修改即使发生错误,也绝对不会将错误扩展到业务逻辑层,更不会影响持久层。
因此,采用J2EE分层架构,即使前期的开发效率稍微低一点,但也是值得的。
— 需求的变更:以笔者多年的开发经验来看,很少有软件产品的需求从一开始就完全是固定的。
客户对软件需求,是随着软件开发过程的深入,不断明晰起来的。
因此,常常遇到软件开发到一定程度时,由于客户对软件需求发生了变化,使得软件的实现不得不随之改变。
当软件实现需要改变时,是否可以尽可能多地保留软件的部分,尽可能少地改变软件的实现,从而满足客户需求的变更?答案是——采用优秀的解耦架构。
这种架构就是J2EE的分层架构,在优秀的分层架构里,控制层依赖于业务逻辑层,但绝不与任何具体的业务逻辑组件耦合,只与接口耦合;同样,业务逻辑层依赖于DAO层,也不会与任何具体的DAO组件耦合,而是面向接口编程。
采用这种方式的软件实现,即使软件的部分发生改变,其他部分也尽可能不要改变。
注意:即使在传统的硬件行业,也有大量的接口规范。
例如PCI接口、显卡或者网卡,只要其遵守PCI的规范,就可以插入主板,与主板通信。
至于这块卡内部的实现,不是主板所关心的,这也正是面向接口编程的好处。
假如需要提高电脑的性能,需要更新显卡,只要更换另一块PCI接口的显卡,而不是将整台电脑抛弃。
如果一台电脑不是采用各种接口组合在一起,而是做成整块,那将意味着即使只需要更新网卡,也要放弃整台电脑。
同样,对于软件中的一个个组件,当一个组件需要重构时,尽量不会影响到其他组件。
实际上,这是最理想的情况,即使采用目前最优秀的架构,也会有或多或少的影响,这也是软件工程需要努力提高的地方。
技术的更新,系统重构:软件行业的技术更新很快,虽然软件行业的发展不快,但小范围的技术更新特别快。
一旦由于客观环境的变化,不得不更换技术时,如何保证系统的改变最小呢?答案还是选择优秀的架构。
在传统的Model 1的程序结构中,只要有一点小的需求发生改变,将意味着放弃整个页面。
或者改写。
虽然前期的开发速度快,除非可以保证以后永远不会改变应用的结构,否则不要采用Model 1的结构。
采用Hibernate作为持久层技术的最大的好处在于:可以完全以面向对象的方式进行系统分析、系统设计。
DAO模式需要为每个DAO组件编写DAO接口,同时至少提供一个实现类,根据不同需要,可能有多个实现类。
用Spring容器代替DAO工厂 通常情况下,引入接口就不可避免需要引入工厂来负责DAO组件的生成。
Spring实现了两种基本模式:单态模式和工厂模式。
而使用Spring可以完全避免使用工厂模式,因为Spring就是个功能非常强大的工厂。
因此,完全可以让Spring充当DAO工厂。
由Spring充当DAO工厂时,无须程序员自己实现工厂模式,只需要将DAO组件配置在Spring容器中,由 ApplicationContext负责管理DAO组件的创建即可。
借助于Spring提供的依赖注入,其他组件甚至不用访问工厂,一样可以直接使用 DAO实例。
优点: Struts跟Tomcat、Turbine等诸多Apache项目一样,是开源软件,这是它的一大优点。
使开发者能更深入的了解其内部实现机制。
除此之外,Struts的优点主要集中体现在两个方面:Taglib和页面导航。
Taglib是Struts的标记库,灵活动用,能大大提高开发效率。
另外,就目前国内的JSP开发者而言,除了使用JSP自带的常用标记外,很少开发自己的标记,或许Struts是一个很好的起点。
关于页面导航,我认为那将是今后的一个发展方向,事实上,这样做,使系统的脉络更加清晰。
通过一个配置文件,即可把握整个系统各部分之间的联系,这对于后期的维护有着莫大的好处。
尤其是当另一批开发者接手这个项目时,这种优势体现得更加明显。
缺点: Taglib是Struts的一大优势,但对于初学者而言,却需要一个持续学习的过程,甚至还会打乱你网页编写的习惯,但是,当你习惯了它时,你会觉得它真的很棒。
Struts将MVC的Controller一分为三,在获得结构更加清晰的同时,也增加了系统的复杂度。
Struts从产生到现在还不到半年,但已逐步越来越多运用于商业软件。
虽然它现在还有不少缺点,但它是一种非常优秀的J2EE MVC实现方式,如果你的系统准备采用J2EE MVC架构,那么,不妨考虑一下Struts。
如何用Wireshark查看HTTPS消息里的加密内容
1. 配置Wireshark选中Wireshark主菜单Edit->Preferences,将打开一个配置窗口;窗口左侧是一棵树(目录),你打开其中的Protocols,将列出所有Wireshark支持的协议;在其中找到SSL并选中,右边窗口里将列出几个参数,其中“RSA keys list”即用于配置服务器私钥。
该配置的格式为: ,,, 各字段的含义为: —- 服务器IP地址(对于HTTPS即为WEB服务器)。
—- SSL的端口(HTTPS的端口,如443,8443)。
—- 表示SSL里加密的是什么协议,对于HTTPS,这项应该填HTTP。
—- 服务器密钥文件,文件里的私钥必须是明文(没有密码保护的格式)。
例如: 192.168.1.1,8443,http,C:/myserverkey/ 若你想设置多组这样的配置,可以用分号隔开,如: 192.168.1.1,8443,http,C:/myserverkey/;10.10.1.2,443,http,C:/myserverkey/ 2. 导出服务器密钥(私钥)的明文格式(即前面提到的) 大家当初在配置HTTPS服务器,服务器私钥时,一般都会输入一个保护私钥的密码。
那如何导出明文形式的服务器私钥呢,需要视情况而定: (1)若你是像《如何用Tomcat和Openssl构建HTTPS双向认证环境(HTTPS客户端认证)》里所述的那样,用类似于如下命令生成服务器私钥的: openssl req -newkey rsa:1024 -keyout -keyform PEM -out / -outform PEM -subj /O=ABCom/OU=servers/CN=servernameM 而且你的服务器私钥文件还在,则可以这样导出服务器私钥明文文件: openssl rsa -in > 执行命令式需要输入私钥的保护密码就可以得到私钥明文文件了。
(2)若你已把丢了,但还有pkcs12格式的服务器证书库文件,该文件当初用类似于以下命令生成的: openssl pkcs12 -export -in -inkey / -out tomcat.p12 -name tomcat -CAfile $HOME/testca/ / -caname root -chain 则,你可以用下面命令把服务器私钥从tomcat.p12(pkcs12格式)文件里导出来: openssl pkcs12 -in tomcat.p12 -nocerts -nodes -out 执行命令式需要输入pkcs12的保护密码。
然后编辑一下生成的文件,把“—–BEGIN RSA PRIVATE KEY—–”之前的内容删掉就可以了。
(3)若你的服务器私钥是用java的keytool命令生成的keystore文件,则要弄出来比较麻烦,建议服务器keystore最好用《如何用Tomcat和Openssl构建HTTPS双向认证环境(HTTPS客户端认证)》里的openssl生成服务器公钥私钥和证书的方法,生成pkcs12格式的keystore。

