java实现单向和双向SSL握手java 开关设计与实现问题,怎么解决

博客分类:
一、SSL(Server Socket Layer)简介
Netscape公司提出的SSL协议,旨在达到
在开放网络(Internet)上安全保密地传输信息的目的,这种协议在WEB上获得了广泛的应用。 之后IETF(
)对SSL作了标准化,即RFC2246,并将其称为TLS(Transport Layer Security),从技术上讲,TLS1.0与SSL3.0的差别非常微小。
二、工作原理
SSL协议使用不对称加密技术实现会话双方之间信息的安全传递。可以实现信息传递的保密性、完整性,并且会话双方能鉴别对方身份。不同于常用的http协议,我们在与网站建立SSL安全连接时使用https协议,即采用
的方式来访问。
当我们与一个网站建立https连接时,我们的浏览器与Web Server之间要经过一个握手的过程来完成身份鉴定与密钥交换,从而建立安全连接。具体过程如下:
用户浏览器将其SSL版本号、加密设置参数、与session有关的数据以及其它一些必要信息发送到服务器。
服务器将其SSL版本号、加密设置参数、与session有关的数据以及其它一些必要信息发送给浏览器,同时发给浏览器的还有服务器的证书。如果配置服务器的SSL需要验证用户身份,还要发出请求要求浏览器提供用户证书。
客户端检查服务器证书,如果检查失败,提示不能建立SSL连接。如果成功,那么继续。
客户端浏览器为本次会话生成pre-master secret,并将其用服务器公钥加密后发送给服务器。
如果服务器要求鉴别客户身份(双向认证),客户端还要再对另外一些数据签名后并将其与客户端证书一起发送给服务器。
如果服务器要求鉴别客户身份,则检查签署客户证书的CA是否可信。如果不在信任列表中,结束本次会话。如果检查通过,服务器用自己的私钥解密收到的pre-master secret,并用它通过某些算法生成本次会话的master secret。
客户端与服务器均使用此master secret生成本次会话的会话密钥(对称密钥)。在双方SSL握手结束后传递任何消息均使用此会话密钥。这样做的主要原因是对称加密比非对称加密的运算量低一个数量级以上,能够显著提高双方会话时的运算速度。
客户端通知服务器此后发送的消息都使用这个会话密钥进行加密。并通知服务器客户端已经完成本次SSL握手。
服务器通知客户端此后发送的消息都使用这个会话密钥进行加密。并通知客户端服务器已经完成本次SSL握手。
本次握手过程结束,会话已经建立。双方使用同一个会话密钥分别对发送以及接受的信息进行加、解密。
三、服务器端证书
命令行打开%java_home%/bin,keytool
是JDK提供的证书生成工具,所有参数的用法参见keytool –help
1、生成服务端
dos状态下执行命令:
keytool ‐genkey ‐v ‐alias
jbossserver
‐keyalg RSA ‐keystore jbossserver.jks ‐dname "CN=127.0.0.1,OU=michael,O=michael,L=SZ,ST=GD,C=CN" ‐validity 3650 ‐storepass ffffff ‐keypass ffffff
是JDK提供的证书生成工具,所有参数的用法参见keytool –help-genkey
创建新证书-v
详细信息-alias
jbossserver
以”jbossserver
”作为该证书的别名。这里可以根据需要修改-keyalg
RSA 指定算法-keystore
jbossserver
.jks 保存在%java_home%/bin目录下-dname
"CN=127.0.0.1,OU=michael,O=michael,L=SZ,ST=GD,C=CN
" 证书发行者身份,这里的CN要与发布后的访问域名一致。但由于我们是自己发行的证书,如果在浏览器访问,仍然会有警告提示
3650证书有效期,单位为天-storepass
证书的存取密码-keypass
证书的私钥
生成证书签名请求
-certreq -alias tomcat_server -sigalg MD5withRSA -file
tomcat_server.csr -keypass 123456 -storepass 123456 -keystore
server_keystore
导出服务端证书
执行命令:keytool -export -alias tomcat -keystore D:/SSL/server/tomcat.keystore -storepass pdepde -rfc -file D:/SSL/server/tomcat.cer
把服务端证书导出。这里提供的密码也是服务端证书的密码。
1.2 生成客户端证书
执行命令:keytool ‐genkey ‐v ‐alias client ‐keyalg RSA ‐storetype PKCS12 ‐keystore D:/SSL/client/client.p12 ‐dname "CN=client,OU=pde,O=pde,L=bj,ST=bj,C=CN" ‐validity 3650 ‐storepass client ‐keypass client
参数说明同上。这里的-dname
证书发行者身份可以和前面不同
1.3 导出客户端证书
执行命令:keytool ‐export ‐alias client ‐keystore D:/SSL/client/client.p12 ‐storetype PKCS12 ‐storepass client ‐
fc ‐file D:/SSL/client/client.cer
导出文件的文件路径
1.4 把客户端证书加入服务端证书信任列表
执行命令:keytool ‐import ‐alias client ‐v ‐file D:/SSL/client/client.cer ‐keystore D:/SSL/server/tomcat.keystore ‐storepass pdepde
参数说明同前。这里提供的密码是服务端
证书的密码。1.5 导出服务端证书
执行命令:keytool -export -alias tomcat -keystore D:/SSL/server/tomcat.keystore -storepass pdepde -rfc -file D:/SSL/server/tomcat.cer
把服务端证书导出。这里提供的密码也是服务端证书的密码。1.6 生成客户端信任列表
执行命令:keytool -import -file D:/SSL/server/tomcat.cer -storepass pdepde -keystore D:/SSL/client/client.truststore -alias tomcat –noprompt
让客户端信任服务端证书
2. 配置服务端参数
2.1 配置Tomcat 目录下的/conf/server.xml
"HTTP/1.1"
SSLEnabled
maxThreads
clientAuth
sslProtocol
keystoreFile
"D:/SSL/server/tomcat.keystore"
keystorePass
truststoreFile
"D:/SSL/server/tomcat.keystore"
truststorePass
这里的参数clientAuth
决定了是否执行强制客户端证书验证,true-只允许持有证书的客户端执行https连接2.2 配置服务端项目web.xml
/services/*
CONFIDENTIAL
这里的“&url-pattern&/services/*&/url-pattern&
”指定了必须采用https的链接,当访问这些路径时,http协议的访问将被转发至https协议。这里需要根据服务端项目中web service的访问地址来配置3. 修改客户端代码
在执行访问之前,增加:
System.setProperty(
"javax.net.ssl.trustStore"
"D:/SSL/client/client.truststore"
System.setProperty("javax.net.ssl.trustStorePassword"
System.setProperty("javax.net.ssl.keyStoreType"
System.setProperty("javax.net.ssl.keyStore"
"D:/SSL/client/client.p12"
System.setProperty("javax.net.ssl.keyStorePassword"
String endPoint="https://127.0.0.1:8443/easbCut/services/ApplyFormService"
通过设置参数来指定客户端连接时所使用的客户端证书,这里还可以采用修改JVM启动参数的的方式来执行,但处于不影响其他功能的考虑,这里采用System.setProperty的方式来设置这些参数,在使用结束后,可以还原这些参数配置。
做为客户端的开发者,可以把拿到的证书文件后,只执行步骤3。
====================================
JDK中keytool常用命令
在用户主目录中创建一个默认文件".keystore",还会产生一个mykey的别名,mykey中包含用户的公钥、私钥和证书
指定密钥库的名称(产生的各类信息将不在.keystore文件中
指定密钥的算法
指定创建的证书有效期多少天
指定密钥长度
-storepass
指定密钥库的密码
指定别名条目的密码
指定证书拥有者信息 例如:
"CN=sagely,OU=atr,O=szu,L=sz,ST=gd,C=cn"
显示密钥库中的证书信息
keytool -list -v -keystore sage -storepass ....
显示密钥库中的证书详细信息
将别名指定的证书导出到文件
keytool -export -alias caroot -file caroot.crt
参数指定导出到文件的文件名
删除密钥库中某条目
keytool -delete -alias sage -keystore sage
-keypasswd
修改密钥库中指定条目口令
keytool -keypasswd -alias sage -keypass .... -new .... -storepass ... -keystore sage
将已签名数字证书导入密钥库
keytool -import -alias sage -keystore sagely -file sagely.crt
导入已签名数字证书用keytool -list -v 以后可以明显发现多了认证链长度,并且把整个CA链全部打印出来。
1.证书的显示
[-v | -rfc] [-alias &alias&]
[-keystore &keystore&] [-storepass &storepass&]
[-storetype &storetype&] [-provider &provider_class_name&]
例如:keytool -list -v -alias RapaServer -keystore cacerts -storepass
keytool -list -v -keystore d2aapplet.keystore -storepass
-storetype IAIKKeystore
2.将证书导出到证书文件
例如:keytool -export -keystore monitor.keystore -alias monitor -file monitor.cer
将把证书库 monitor.keystore 中的别名为 monitor 的证书导出到 monitor.cer 证书文件中,它包含证书主体的信息及证书的公钥,不包括私钥,可以公开。
keytool -export -keystore d2aApplet.keystore -alias RapaServer -file Rapa.cert -storetype IAIKKeystore
3.将keystore导入证书中
这里向Java默认的证书 cacerts导入Rapa.cert
keytool -import -alias RapaServer -keystore cacerts -file Rapa.cert -keystore cacerts
4.证书条目的删除
keytool的命令行参数 -delete 可以删除密钥库中的条目,如: keytool -delete -alias RapaServer -keystore d2aApplet.keystore ,这条命令将 d2aApplet.keystore 中的 RapaServer 这一条证书删除了。
5.证书条目口令的修改
使用 -keypasswd 参数,如:keytool -keypasswd -alias RapaServer -keystore d2aApplet.keystore,可以以交互的方式修改 d2aApplet.keystore证书库中的条目为 RapaServer 的证书。
Keytool -keypasswd -alias RapaServer -keypass 654321 -new 123456 -storepass 888888 -keystore d2aApplet.keystore这一行命令以非交互式的方式修改库中别名为 RapaServer 的证书的密码为新密码 654321,行中的 123456 是指该条证书的原密码, 888888 是指证书库的密码。
捕风的汉子
浏览: 13332 次
来自: 深圳
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'博客分类:
上一篇提到在NGINX中配置了双向SSL的验证, 签名信息及公私钥对都是用OPENSSL生成. 并且用生成的CLIENT端证书放在浏览器上可正常调用,但WEB-SERVICE方式调用却没有试过. 平常WEB-SERVICE的双向SSL都是用KEYTOOL工具生成公私钥信息及签名信息,所以这次同样试一下用KEYTOOL来处理OPENSSL的证书.
很感谢这篇博文: 给我带来的灵感.
接着上一篇 , 我用OPENSSL生成了ca根证书的私钥ca.crt和客户端client.crt.
接着我用KEYTOOL工具把这两个私钥都同时导入到信任库中client.keystore
keytool -import -v -trustcacerts
-alias ca_root -file ca.crt -storepass 1111 -keystore client.keystore
keytool -import -v -alias ipclient_private_key -file client.crt -keypass 1111 -storepass 1111 -keystore client.keystore
接着,可以查看一下这个keystore 的详细信息keytool -list -v -keystore client.keystore
JAVA客户端调用SSL WEB SERVICE
System.setProperty("javax.net.ssl.keyStore", "F:/workspace/TemporaryProgram/cert/client02.p12");
System.setProperty("javax.net.ssl.keyStorePassword","client02");
System.setProperty("javax.net.ssl.keyStoreType","PKCS12");
System.setProperty("javax.net.ssl.trustStore", "F:/workspace/TemporaryProgram/cert/client.keystore");
System.setProperty("javax.net.ssl.trustStorePassword","client02");
System.setProperty("javax.net.ssl.trustStoreType", "jks");
String endpointURL = "https://192.168.40.129:8443/XXXX/services/supplier?wsdl";//
// Web服务端点地址
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(new java.net.URL(endpointURL));
call.setOperationName(new QName("", "getSupplierByCode"));// 设置操作的名称。
call.addParameter("systemSecurityCode", XMLType.XSD_STRING, ParameterMode.IN);// 参数的类型
call.addParameter("code", XMLType.XSD_STRING, ParameterMode.IN);// 参数的类型
call.setReturnType(XMLType.XSD_STRING);// 返回的数据类型
Double ret = (Double) call.invoke(new Object[] { "fdsaf","fdsafdas"});// 执行调用
System.out.println("使用HTTP协议来作为Web服务的传输协议!");
System.out.println("已经成功调用。请参看服务端的输出!");
浏览: 249221 次
来自: 芜湖
还有屌丝啊
非常好啊......
为什么我执行(生成的不以-jar-with-depend ...
怒赞一个!!!很棒!
关键是,我想mvn package就打包好,请问,怎么做
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'6010人阅读
java(33)
最近对产品的通讯方式进行了调整,由原先的socket通信,改用https通信(也支持http). https通信相对于http通信多了一层 客户端与服务端之间的双向认证, 遇到的问题也是出现在这里,抓狂了近一周,任然无结果. 但不管怎样先把这几天学习SSL的一些想法写出来先,以后碰到少走点弯路.
一般我们通过httpClient 发送https请求代码如下:
public static void main(String args[]) throws Exception {
HttpClient client=wrapClient(new DefaultHttpClient());
HttpGet get=new HttpGet(&https://localhost:8000&);
HttpResponse resp=client.execute(get);
System.out.println(resp.getStatusLine().getStatusCode());
public static HttpClient wrapClient(HttpClient base) throws Exception{
SSLContext ctx = SSLContext.getInstance(&TLSv1&);
X509TrustManager tm = new X509TrustManager(){
public X509Certificate[] getAcceptedIssuers()
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
public void checkServerTrusted(X509Certificate[] arg0, String arg1)throws CertificateException{}
ctx.init(null, new TrustManager[] { tm }, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = base.getConnectionManager();
SchemeRegistry registry = ccm.getSchemeRegistry();
registry.register(new Scheme(&https&, 443, ssf));
return new DefaultHttpClient(ccm, base.getParams());
wrapClient(HttpClient base)方法就是网上通用的绕过SSL双向认证的封装方法.一般也不会出错. 但是特殊情况还是会用的,
我遇到的情况是内网有三台window机子:
192.168.64.11 &win7, 192.168.64.101 win7, 192.168.64.102 win2003
11机子与101机子相互发送 https请求没有任何问题, 102机子发送https请求到11没有问题,但是11机子发送https请求到102怎么也发不通,抛出peer not authenticated 异常
刚开始以为是102的防火墙问题,关了之后还是发不通,百度说可能是两台机子的时间对不上,对了下时间也没问题,这就纳闷了.
查了下httpClient 官方发送https请求做法,与上面的代码雷同, 没办法自己看源代码,最后查到是 SSL握手的问题,即数据没交互前出错了.看问题代码:
public static void main(String args[]) throws Exception {
testSslByHttpClient();
public static void testSslByHttpClient() throws Exception{
SSLContext ctx = SSLContext.getInstance(&SSL&);
X509TrustManager tm = new X509TrustManager(){
public X509Certificate[] getAcceptedIssuers()
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
public void checkServerTrusted(X509Certificate[] arg0, String arg1)throws CertificateException{}
ctx.init(null, new TrustManager[] { tm }, null);
SSLSocketFactory ssf=new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Socket socket=ssf.createSocket();
InetSocketAddress addre=new InetSocketAddress(&127.0.0.1&, 8000);
socket.setSoTimeout(1000);
socket.connect(addre,0);
SSLSocket ssl=(SSLSocket)
//ssl.setNeedClientAuth(false);
SSLSession session=ssl.getSession();
System.out.println(session.getCipherSuite());
异常输出结果: &&SSL_NULL_WITH_NULL_NULL.&
正常输出结果: &TLS_RSA_WITH_AES_128_CBC_SHA(值可以变化)&&
普及下 cipherSuite 是双方进行通信的密码套件,约定了双方加密相关的行为. 了解详情参考下:http://blog.chinaunix.net/uid--id-4050413.html.
在来看下 SSLSocket类 getSession()方法的解释:
Returns the SSL Session in use by this connection. These can be long lived, and frequently correspond to an entire login session for some user. The session specifies a particular cipher suite which is being actively used by all connections in that session, as well as the identities of the session's client and server.
This method will initiate the initial handshake if necessary and then block until the handshake has been established.
If an error occurs during the initial handshake, this method returns an invalid session object which reports an invalid cipher suite of &SSL_NULL_WITH_NULL_NULL&.
最后一句是重点, 意思说 第一次握手失败时会返回 一个无效的密码套件(SSL_NULL_WITH_NULL_NULL),但是为什么有些情况下会失败,偶也没解决,等待高手解决.
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:208895次
积分:2278
积分:2278
排名:第17495名
原创:46篇
转载:30篇
评论:18条
(1)(1)(1)(1)(3)(2)(1)(8)(1)(1)(1)(1)(1)(1)(1)(1)(3)(5)(8)(1)(8)(16)(9)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'博客分类:
随着互连网的规模与影响不断扩大,网络通信安全已成为网络程序设计时,需要重点考虑的问题。
SSL(Server Socket Layer)服务套接字层,是Netscape(网景)公司提出的用于internet上安全保密传输信息的协
议,它工作于OSI开放系统互连模型的传输层之上,因此在传输层之上的协议,比如http,ftp,smtp等,都可以基
于ssl实现安全的网络通信。
最近做MCS平台项目,需要实现应用程序平台到MCS平台的安全通信,做了有一阵子,小结一下。
要想保证网络通信的安全,我们第一反应就是给传输的数据加密,这也是现行安全传输通用的模式。但在传统加
密方式(单密钥,对称加密)下,密钥不可避免的要被传送于网络节点之间,(除非是写死到各个节点中,不过那样
就没有任何灵活性和普适性),在一定强度的网络攻击下,这种加密方式是很脆弱的。
SSL的出现解决了这个难题,理解SSL的关键是理解非对称加密的含义。
在对称加密的情况下,源数据A,通过使用密钥B,加密成为密文C。任何人,只要获得了密钥B,就能够对截获
的密文C解密,还原出源数据A。(依靠"算法安全"远不如依靠"密钥安全");在非对称加密中,出现了“密钥对”
的概念,即有一个公共密钥(公钥)和一个私有密钥(私钥),经公钥加密的密文只能由私钥解密,反过来,经私钥
加密的密文只能由公钥解密。这是个重要的特性(数学原理可参考RSA算法),下面的模拟https通信流程说明了这
一特性的重要。
1,客户端向服务端发出请求,服务端将公钥(以及服务端证书)响应给客户端;
2,客户端接收到服务器端端公钥与证书,验证证书是否在信任域内,不信任则结束通信,信任则使用服务端传
过来的公钥生成一个“预备主密码”,返回给服务端。
3,服务端接收客户端传过来的“预备主密码”密文,使用私钥解密。非对称加密的安全性也就在于此了,第三
方无法获取到“预备主密码”的明文,因为除了服务端,其他任何人是没有私钥的。
4,双方使用“预备主密码”生成用于会话的“主密码”。确认后,结束本次SSL握手,停止使用非对称加密。
5,双方使用“主密码”对称加密传输数据,直到本次会话结束。
总结整个流程:先采用非对称加密模式,保证“主密码”只被通信双方获知,而后使用传统的对称加密方式
通信,这样,保证了密钥安全(即“主密码”)就等于保证了数据安全。之所以建立安全连接后,转而使用对称加
密,是因为非对称加密的运算量很大,用于“常态”的数据通信十分低效。
以上描述的仅是SSL协议中加密通信的原理,没有涉及到证书验证,以及客户端,服务端模式。
JDK里面自带了一个密钥生成工具keytool,可以通过它生成SSL通信需要的密钥对,或者生成自签名的证书。
所有密钥对或者签名证书都是存放在“keystore”密钥仓库中,由它来管理。
下面结合具体例子说明:(java WEB容器:tomcat 5.5)
1,生成服务端密钥仓库,
keytool -genkey -alias svrkey -keyalg RSA -keystore d:\svr.jks -validity 365
"alias"是生成的密钥别名,密钥的导入导出都需要由别名来定位。
"keystore"生成的密钥仓库
"validity"生成密钥仓库的有效期(天)
随后会要求输入密钥仓库入口密码,比如: lostsky_11
输完密码后,接着会要求一系列的输入,无非是单位,所在地区之类的信息,
但是第一项很重要!为输入服务端域名或IP,如: 192.168.1.3或
必须与服务器域名或IP相同,否则SSL连接无法建立(这也是SSL通信验证的一部分)
2,在tomcat_home/conf/server.xml中配置:
找到ssl通信配置那一段,加入:
keystoreFile="d:\svr.jks" keystorePass="lostsky_11"
服务器启动时会从中寻找用于建立ssl连接的密钥
3,导出服务端证书
keytool -export -alias svrkey -file d:\svr.cer -keystore d:\svr.jks
"alias"为想导出的密钥的别名,"file"为导出的证书,"keystore"为存储着导出密钥的仓库
4,生成客户端密钥仓库
keytool -genkey -alias clientkey -keyalg RSA -keystore d:\client.jks
会要求输入仓库密码:如:midsky
5,将服务端证书导入到客户端密钥仓库
keytool -import -file d:\svr.cer -keystore d:\client.jks
会要求输入客户端密钥仓库的密码:如上是:midsky
这样服务端的密钥仓库就在tomcat部署完毕了,
6,在客户端,每次访问服务端之前,加入
"System.setProperty("javax.net.ssl.trustStore","d:\\client.jks");
System.setProperty("javax.net.ssl.trustStorePassword","midsky");
就把服务端证书添加到了客户端的信任域中,能够完成ssl通信。
注:ssl通信主要验证三个方面:
a, 证书是否可信(第6步)
b, 证书是否过期(第1步:validity)
c, 证书地址是否和当前访问地址符合(第1步)
客户端添加信任域还有编程的动态方法,但是那样会降低通信的安全性,对于证书相对固定的服务,不建议使
以上是客户端对于服务端的验证,这也是SSL默认的实现方式。在这种方式下,每次通信时,发起请求方(如PC
中的BROWSER)都会验证响应方(如某个WEB服务端)的证书是否在己方信任域中,对方的证书是否过期,对方
的域名或IP,是否与信任域中证书记载的一致;不符合其中任何一项,通信都会被拒绝。但反过来,响应方是不
对请求方做任何验证的。所以有些需要双向验证的服务(比如某些服务只能对特定的拥有证书的用户开放),就需
要添加客户端证书,由服务端来验证了,原理和实现与默认模式类似。
Sarah-Brightman
浏览: 46157 次
来自: 上海
我自己看着英文也小小地翻译了一份。
不错,好好学习下
LZ最好给出一个版本说明,不同的版本目录结构不一样的。看上去像 ...
xieye 写道用range的好处是,可以不用for,继续fo ...
PHP数组函数很好用,自己写很耗时间,而且bug很多,许多算法 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'随笔-1857&
SSL/TLS握手过程可以分成两种类型:
1)SSL/TLS 双向认证,就是双方都会互相认证,也就是两者之间将会交换证书。2)SSL/TLS 单向认证,客户端会认证服务器端身份,而服务器端不会去对客户端身份进行验证。
我们知道,握手过程实际上就是通信双方协商交换一个用于对称加密的密钥的过程,而且握手过程是明文的。这个过程实际上产生三个随机数:client random, server random, pre-master secret. 参考&.前两个随机数都是明文传送的,只有pre-master secret是加密的(RSA或者DH)。一般生成证书的时候,签名算法可以选择RSA或者DSA算法。如果server使用RSA证书,RSA即可以用作签名也可以用作不对称加密,pre-master secret就是用server的RSA证书中包含的公钥加密的。如果server使用DSA证书,DSA只能用作签名,所以还需要使用来交换密钥。
以下是其流程图(摘自),括号中的步骤是可选的。如果是单向认证,那么蓝色字体部分是不需要的。4 server_key_exchange这一步只有在选择了某些密钥交换算法例如DH算法的时候才需要。
1 Client Hello
2 Server Hello3 certificate4 (server_key_exchange)5 (certificate_request)6 server_hello_done
7 (certificate)8 client_key_exchange9 (certifiate_verify)10 change_cypher_spec----finished----
11 change_cypher_spec----finished----
下面使用wireshark抓取握手过程的报文。server/client使用。
server证书签名算法RSA-双向认证
可见包括了除了4以外的所有步骤。因为采取了RSA算法,所以步骤4是不需要的。
(一) 首先,客户端向服务器提供以下信息client_hello(1)支持的协议版本,比如TLS 1.0(2)支持的加密算法(Cipher Specs)(3)客户端生成的随机数1(Challenge),稍后用于生成"对话密钥"。
(二)服务器回答给客户端以下信息server_hello(1) 确认使用的协议版本(2) 服务器生成的随机数2,稍后用于生成"对话密钥"(3) session id(4) 确认使用的加密算法certificate服务器证书server_key_exchange如果是DH算法,这里发送服务器使用的DH参数。RSA算法不需要这一步。certificate_request要求客户端提供证书,包括(1) 客户端可以提供的证书类型(2)服务器接受的证书distinguished name列表,可以是root CA或者subordinate CA。如果服务器配置了trust keystore, 这里会列出所有在trust keystore中的证书的distinguished name。server_hello_doneserver hello结束(三)客户端发送给服务器certificate客户端证书client_key_exchange包含pre-master secret。客户端生成第三个随机数。如果是采用RSA算法,会生成一个48字节随机数,然后用server的公钥加密之后再放入报文中;如果是DH算法,这里发送的就是客户端的DH参数,之后服务器和客户端根据DH算法,各自计算出相同的pre-master secret。certificate_verify发送使用客户端证书给到这一步为止收到和发送的所有握手消息签名结果。change_cipher_spec客户端通知服务器开始使用加密方式发送报文。客户端使用上面的3个随机数client random, server random, pre-master secret, 计算出48字节的master secret, 这个就是对称加密算法的密钥。finished客户端发送第一个加密报文。使用计算收到和发送的所有握手消息的摘要,然后通过RFC5246中定义的一个伪函数计算出结果,加密后发送。
(四) 服务器发送给客户端服务器端发送change_cipher_spec和finished消息。到这里握手结束。
server证书签名算法DSA-双向认证
下面是一个server证书采用DSA算法的握手过程。由于采用了DH算法交换密钥,多了server_key_exchange这一步。
server证书签名算法RSA-单向认证
和双向认证相比,server端少了certificate_request,client端少了certificate&和&certificate_verify。
阅读(...) 评论()

我要回帖

更多关于 java实现汉诺塔问题 的文章

 

随机推荐