SSL
学习笔记
目录
1
SSL基本概念及传输过程
SSL(Secure Socket Layer)是一种允许web浏览器和web服务器通过一个安全的连接进行交流的技术。传统的HTTP传输层位于TCP/IP层之上,应用SSL协议可以对传输过程进行加密保护,从而保证了应用的安全。这对于许多安全敏感应用是非常有帮助的,因此,现在应用SSL技术的网站越来越多。许多我们常见的网站都有SSL协议的实现,例如google的gmail网站:https://mail.google.com.
大家可以看到,应用SSL加密的传输使用的URL与传统的HTTP协议不同,这里使用HTTPS作为协议头。
应用SSL的安全传输层次结构和传统的HTTP结构有所不同,见图1。
__________________
| HTTP |
__________________
| SSL |
__________________
| TCP |
__________________
| IP |
__________________
图1:SSL分层结构
作为应用广泛的加密协议,现在流行的大多数server服务器如:tomcat, IIS都支持SSL传输。在server服务器上进行设置后,就可以利用SSL进行安全传输了。在用户登录服务器端时需要进行证书管理和身份验证等工作,在连接到服务器后,就可以想平时操作HTTP协议的应用一样的工作了。不同的是在浏览器下方将会显示一个黄色的小锁头表示您的这次连接是受到了加密保护的。
1.2
SSL传输过程
SSL
协议支持两种传输过程,需要用户验证的双向验证传输,和不需要用户验证的单向验证传输。这里主要介绍双向验证传输过程。
在开始传输之前我们需要在服务器端和客户端分别准备好各自的证书,以证实自己的身份,在服务器端证书需要安放到相应位置并在server服务器上进行相应配置,在客户端,用户需要将自己的证书导入到web浏览器中。关于证书的相关内容,和sever服务器的配置问题我将在后文中详细介绍。
双向认证 SSL 协议的具体过程如下:
①
浏览器发送一个连接请求给安全服务器。
②
服务器将自己的证书,以及同证书相关的信息发送给客户浏览器。
③
客户浏览器检查服务器送过来的证书是否是由自己信赖的 CA 中心所签发的。如果是,就继续执行协议;如果不是,客户浏览器就给客户一个警告消息:警告客户这个证书不是可以信赖的,询问客户是否需要继续。
④
接着客户浏览器比较证书里的消息,例如域名和公钥,与服务器刚刚发送的相关消息是否一致,如果是一致的,客户浏览器认可这个服务器的合法身份。
⑤
服务器要求客户发送客户自己的证书。收到后,服务器验证客户的证书,如果没有通过验证,拒绝连接;如果通过验证,服务器获得用户的公钥。
⑥
客户浏览器告诉服务器自己所能够支持的通讯对称密码方案。
⑦
服务器从客户发送过来的密码方案中,选择一种加密程度最高的密码方案,用客户的公钥加过密后通知浏览器。
⑧
浏览器针对这个密码方案,选择一个通话密钥,接着用服务器的公钥加过密后发送给服务器。
⑨
服务器接收到浏览器送过来的消息,用自己的私钥解密,获得通话密钥。
⑩
服务器、浏览器接下来的通讯都是用对称密码方案,对称密钥是加过密的。
或许上面的过程有些繁琐,为了便于理解这里给出一个单向验证传输的简单图解,其实两者的本质是相同的,不过是双向验证在形成通话密钥前对客户端的证书进行了验证:
图2:SSL单向验证过程
其实,通俗的理解SSL传输的过程就是先进性用户身份的验证,这里分单向和双向两种;而后进行双方密钥的交换和形成通话密钥即握手协议;最后通讯双方用通话密钥进行安全的信息交换。
所以这里再补充一些细节,SSL协议中可以再大体分成两部分协议:
HandShake Protocal----------------------
负责协商通讯密钥
Record Protocal----------------------
负责管理传输格式
这里我们简要总结一下SSL安全传输的主要作用:
1.
SSL协议使用非对称的加密算法交换协议,使用对称的加密算法进行传输文件的保护,保证了传输过程的安全可靠。
2.
利用加密算法在传输过程中进行校验从而保证了信息的完整和真实。
3.
利用证书签发,验证等机制保证了传输双方的身份。支持灵活的证书验证方式。
至此我们已经介绍了SSL安全传输协议的一些基本概念和基本传输过程。
数字签名作为一种行之有效的用户身份认证机制,在现代电子商务,个人信息管理等领域应用广泛。关于数字签名的原理和概念资料很多,这里简单介绍一下为后文做准备。
数字签名主要应用公钥/密钥加密和证书管理等的技术来实现。关于非对称加密技术我不多说了,这里主要介绍一下CA的概念。
所谓CA(Certificate Authority)认证中心,它是采用PKI(Public Key Infrastructure)公开密钥基础架构技术,专门提供网络身份认证服务,负责签发和管理数字证书,且具有权威性和公正性的第三方信任机构,它的作用就像我们现实生活中颁发证件的公司,如护照办理机构。
通俗的将CA就是有认证权利的权威机构,受人们信任,你信任一个CA就可以初步信任他所颁发的证书,和拿证书的人。而后当然还可以根据证书的不同解析内容进行更进一步的操作。相反的遇到没有见过的CA认证的证书就要小心了。
数字签名的申请和使用过程如下:
1.
用户先申请一份证书申请表,然后将这份申请表提交给用户想要获得证书认证的CA。这份请求申请的证书里可以包含用户自定义的用于今后进行数字签名的证书私钥。
2.
CA利用自己的认证私钥给证书签名,使之成为受CA认证保护的合法证书。
3.
CA将相应证书发放给用户,这份证书可以是明文的也可以是经过加密的文件,例如.p12文件。
4.
用户得到自己受CA认证保护的证书后就可以用他进行身份验证了。具体的可以用自己的私钥进行数字签名,可以出示证书表明自己身份。
一般情况下证书中还包括密钥的有效时间,发证机关(证书授权中心)的名称,及证书的序列号等信息,证书的格式遵循ITUT X.509国际标准。
一个标准的X.509数字证书包含以下一些内容:
证书的版本信息
证书的序列号,每个证书都有一个唯一的证书序列号
证书所使用的签名算法
证书的发行机构名称,命名规则一般采用X.500格式
证书的有效期,现在通用的证书一般采用UTC时间格式,它的计时范围为1950-2049
证书所有人的名称,命名规则一般采用X.500格式
证书所有人的公开密钥
证书发行者对证书的签名
以及一些证书扩展项。
在SSL传输协议中应用证书和数字签名保证了传输双方身份的验证。
1.
在传输两端验证中的应用。
SSL
传输的服务器方需要server证书来表示自己的身份,用户可以通过这个证书来检查自己登陆的页面是否正确。在单向验证中不需要客户端提供自己的身份证书;在双向验证中需要客户端也具备一份证书表示自己的身份。服务器端将允许自己信任的CA下的客户端进入服务,拒绝飞信任CA下的客户端的请求。
2.
在密钥交换中的应用。
在1.2 SSL传输过程中介绍的双向验证过程8中,客户端用服务器端的公钥加密预主密码的过程,实际上是从服务器端的证书中获得了其公钥信息,而后服务器也是从客户端的证书中得到了客户端的相应信息。
所以可以说证书一方面表征用户的身份,进行文件的数字签名,另一方面也是用户传递自己信息的工具。
2.3
管理SSL协议中所使用的证书
下面我们将分步进行证书的生成,以介绍
SSL
协议中证书的管理工作。在这里以
JAVA
环境下
TOMCAT
服务器应用
SSL
为例,
IIS
服务器上使用
SSL
更加简单。
在SSL协议中使用的证书可以简单分类如图3:
1.
分三个文件夹存放证书文件方便管理
2.
在JSSE标准里可以在%JDK_HOME%/jre/lib/security/cacerts中存放trustcacerts。这个信任证书是用于在服务器端进行客户身份验证的。但是这样做并不方便,特别是在迁移服务器时JDK的安装目录不一定就会有麻烦了,因此这里我们将服务器证书和信任证书统一存放到一个证书库中。
3.
以上步骤结束后,将server_keystore 文件保存到%TOMCAT_HOME%/conf目录下方便以后使用。
2.4
TOMCAT环境下配置工作
在TOMCAT环境下要使用SSL需要配置%TOMCAT_HOME%/conf/server.xml和相应webapp目录下的web.xml两个文件。
Server.xml
是配置整个服务器接受请求的文件。通常在大多数HTTP协议中我们习惯于使用8080端口。在SSL应用中我们通常使用8443端口开处理HTTPS传输,因此我们需要在server.xml中加入一个新的连接器。具体设置如下:
<Connector port="8443" minProcessors="5" maxProcessors="75"
enableLookups="true" disableUploadTimeout="true"
acceptCount="100" debug="0"
scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="conf/server_keystore"
keystorePass="1qaz2wsxE"
truststoreFile="conf/server_keystore"
truststorePass="1qaz2wsxE"/>
这里我简单说明几点:
1.
port="8443"
指明这个连接器受理8443端口的请求。
2.
clientAuth="true"
指明SSL传输采用双向验证方式。
3.
keystoreFile
向客户端提供服务器证书。
4.
truststoreFile
用于服务器端验证客户证书。
5.
更多细节可以参考www.apache.org上关于TOMCAT服务器的文档。
这样设置后服务器就可以处理来自
8443
端口的
HTTPS
请求了,对于每一个应用我们还可以进行跟进一步的设置。
Web.xml
是对应每一个应用的配置文件,描述了每个应用的细节,我们在这里只修改两处:
<login-config>
<auth-method>CLIENT-CERT</auth-method>
</login-config>
<security-constraint>
<web-resource-collection >
<web-resource-name >SSL</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
几点说明:
1. <login-config><auth-method> CLIENT-CERT 指明用户登录的验证方式是证书验证。
2. <web-resource-name >SSL 说明这个资源是受SSL保护的。
3.
<url-pattern>/*
说明了受保护资源的
URL
地址,所以在这里可以这是更加细致的信息。如可以在
webapp
下建立目录
ssldir
,在这里这只
/ssldir/*
来启动保护,而对其他目录的信息正常处理。这样分开保护可以提高使用效率。
在
2.3管理SSL应用中所使用的证书
一节中,我们已经简单介绍了生成一些列
SSL
应用中证书的步骤和方法,这里就不再赘述了。在这里提出一些不足和改进方法。
1.
生成的CA私钥(ca-key.pem)以及自签名根证书(ca-cert.pem)均为没有加密的明文, 由于一旦在服务器发布, 以及客户端证书发布之后, 根证书是不能随便修改的, 那么在保管没有加密的CA私钥以及自签名根证书时就会存在安全性问题(如果别人得到你的CA根证书, 他就可以替你生成客户端证书了)。
2.
生成客户端证书的过程比较烦琐, 不方便批量进行客户端证书的生成。
3.
没有统一的配置文件, 生成证书的过程中需要执行相当多的命令, 可重复性差, 出错的可能性比较大。
在实际应用中可以用PKCS12格式的加密文件来保存CA密钥和证书,另外还可以将客户端证书也保存成PKCS12格式进行发放,这样兼顾了便利和安全。
另外可以将繁琐的证书管理过程写入批处理文件中进行操作,方便使用。
在服务器端我们可以按照2.4 TOMCAT环境下配置工作来使用服务器证书。用户在访问相应SSL保护的站点时,若服务器要求验证用户身份,则会提示需要用户出示相应的证书。这时需要将客户端证书导入到浏览器中。
在服务器识别成功后,客户端浏览器将会提示现在要连接相应CA的服务器,询问是否信任证书,这里可以将服务器证书导入到浏览器的信任证书列表中。
这样以来就设置好了服务器端和客户端的证书,可以开始征正常使用了。在连接成功后,浏览器下面会出现一个黄颜色的小锁头,表示现在的传输过程是受保护的。
在
1.2 SSL传输过程
中我们介绍了服务器端客户端证书的简单过程。经过这一过程,服务器可以验证客户端所持证书是否在自己的
trustcacerts
中,从而对客户端证书进行初步的简单的屏蔽。但是这样的简单操作在应用过程中是远远不够的。在实际应用中我们可以对用户请求进行进一步的筛选和操作。
例如可以在前台
jsp
文件中将
request
传入后台进一步处理。
如下是一个处理request的简单例子,我们将客户端证书信息中DN字段保存起来。对与CN=client的用户isAuth = true 允许通过,否则 isAuth = false 不允许通过,代码如下:
import java.security.cert.X509Certificate;
import java.security.Principal;
import javax.servlet.http.HttpServletRequest;
privatestaticbooleanisAuth = false;
//
建立一个
HashMap
存储用户证书信息
privatestatic HashMap<String, ClientCertDN> clientCertDNMap = new HashMap<String, ClientCertDN>();
//
解析用户证书信息
DN
存入相应对象
publicstaticvoid addClientCertDN(String clientName, String certSubject) {
if (clientCertDNMap.containsKey(clientName))
clientCertDNMap
.remove(clientName);
String [] DNSubs = certSubject.split(
"//, "
);
ClientCertDN clientCertDN = new ClientCertDN(DNSubs[0], DNSubs[1], DNSubs[2], DNSubs[3], DNSubs[4], DNSubs[5]);
clientCertDNMap.put(clientName, clientCertDN);
}
//处理request的验证方法
public
static
boolean
authValidate(HttpServletRequest request) {
try
{
String certSubject = null;
X509Certificate[] certChain = (X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");
if (certChain == null) {
isAuth = false;
returnisAuth;
}
int len=certChain.length;
if (len>0){
X509Certificate cert = (X509Certificate)certChain[0];
Principal pSubject = cert.getSubjectDN();
certSubject = pSubject.getName();
addClientCertDN(certSubject.substring(certSubject.indexOf(
"="
) + 1, certSubject.indexOf(
","
)), certSubject);
if (certSubject.substring(certSubject.indexOf("=") + 1, certSubject.indexOf(",")).equals("client") == true)
isAuth
=
true
;
else
isAuth
=
false
;
}
}catch(Exception e){
System.
out
.println(e.toString());
}
return
isAuth
;
}
以上本文介绍了笔者近几天SSL学习中的一些收获。文中主要包含了:
SSL
传输的基本概念
数字签名和证书的基本概念
SSL
协议中应用证书进行验证
TOMCAT
服务器应用SSL协议的配置工作
双向验证的一些简单例子等。
希望能给朋友们一些帮助,共同进步,谢谢。
Simon Lee
2007-9-4