关于HTTPS一篇文章就够了
本文出自:【余志强的博客】
HTTP是明文请求的,它的域名、路径和参数都被中间人看得一清二楚。Google鼓励所有的网站都要使用Https,AppStore也要求新的app也要是https协议,随着各大巨头对网络安全的重视,对用户隐私的重视,是时候系统的研究下Https了。
以前在开发App的时候,在App里面内嵌H5界面,我们这个H5是http协议的,不是https的。每次开打这个H5界面总是在界面底部有小广告条,被流氓的运营商插入了他们家的广告。浏览器和安全软件也可能监听用户搜索在结果页植入广告,所以使用HTTPS愈加显得重要。
一、Https初体验
例如我们打开Chrome浏览器,输入网址 https://github.com 如下图所示:
可以看到网址
左侧有个像锁
一样的图标。Google Chrome浏览器认为这是一个安全的网站,可以有效的保护用户的隐私。
要想很好的理解Https,那我们起码要搭建一个服务器,然后然后在浏览器访问它,就像访问github一样,Google Chrome浏览器也出现一个锁图标。
接下来我们在本地搭建一个Tomcat Web容器,搭建很简单,首先下载一个Tomcat,我下载的是Tomcat7.0.73 然后解压,在conf文件夹里找到server.xml文件并打开,把下面这段代码注释打开:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
- 1
- 2
- 3
然后我们启动Tomcat发现报错了:
严重: Failed to initialize end point associated with ProtocolHandler ["http-bio-
8443"]
java.io.IOException: Keystore was tampered with, or password was incorrect
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:780)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:5
6)
at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.
java:225)
at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeySt
ore.java:70)
at java.security.KeyStore.load(KeyStore.java:1445)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
说keystore被篡改或者密码不正确,但是我们并没有设置Keystore,说明我们缺少这个玩意。它要什么我就给它什么嘛。接下来就使用Java工具生成一个keystore,流程如下:
C:\Users\johnny>keytool -genkey -alias tomcat -keyalg RSA
输入**库口令:
再次输入新口令:
您的名字与姓氏是什么?
[Unknown]: yu
您的组织单位名称是什么?
[Unknown]: chiclaim
您的组织名称是什么?
[Unknown]: chiclaim
您所在的城市或区域名称是什么?
[Unknown]: hangzhou
您所在的省/市/自治区名称是什么?
[Unknown]: zhejiang
该单位的双字母国家/地区代码是什么?
[Unknown]: cn
CN=yu, OU=chiclaim, O=chiclaim, L=hangzhou, ST=zhejiang, C=cn是否正确?
[否]: y
输入 <tomcat> 的**口令
(如果和**库口令相同, 按回车):
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
密码我设置为 123456
。在C盘用户目录下就有一个.keystore
文件,在Tomcat目录下新建一个keystore文件夹,将文件拷贝到该目录下,然后修改server.xml中我们取消注释的那段配置加两个属性keystoreFile
,keystorePass
。keystoreFile代表我们刚才生成keystore文件路径,keystorePass就是我们生成时设置的密码:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
keystoreFile="keystore/.keystore" keystorePass="123456"
clientAuth="false" sslProtocol="TLS" />
- 1
- 2
- 3
- 4
然后往浏览器框里输入:https://localhost:8443/
结果如下所示:
点击高级
然后点击继续前往localhost(不安全)
然后就会出现成功界面:
我们发现,网址左侧的带锁的图标被打了一个叉,而且https
也被划了一条斜线。
那么接下来就需要探讨下Https的证书了
二、Https证书(Certificate)
为什么需要证书
假如我们要去买一颗价值不菲的钻石,那么我们肯定很关心我们想买的钻石的真伪,但是我们对甄别钻石的真伪不是很在行,那么我们怎么办?其实每颗钻石都有一个证书,这个证书就是为了证明钻石的真伪的。那么第一个问题来了,我们怎么知道这个钻石的证书不是伪造的呢?每个证书都是由机构颁发的。那第二个问题来了,我怎么知道这个机构是不是权威的机构呢?而且第二个问题整个问题的关键所在。因为如果机构有问题,那么下面的所有的东西都可能是假的。要想得到客户的信任,那么这个机构肯定是得到业界的认可。(关于钻石的比喻来自网上,为了更好的理解做了部分修改,点击查看原文)
在Https验证证书也是这样的,怎么验证证书是合法的,首先证书是由受信任的数字证书颁发机构CA[Certificate Authority]
颁发的,为什么要说是受信任
的呢?并不是所有CA机构签发的SSL证书都受浏览器信任,不受浏览器信任的SSL证书会报错该证书不受信任
。如果该CA机构被WebTrust
机构认证,那么该CA机构是被信任的。那么什么是WebTrust
认证呢?
什么是WebTrust
认证
Webtrust
认证是电子认证服务行业唯一的国际性认证标准。
起步于1998年初,由美国注册会计师协会(AICPA)、加拿大注册会计师协会(CICA)联合设立。
作为一项规范CA机构运营服务的国际标准,Webtrust
认证得到了国际上大多数CA
的认可,成为微软等大厂商支持的标准,目前Verisign
、Entrust
、Identrust
等国际上的大型CA机构以及发达国家和地区的认证机构大多数都获得了Webtrust
认证。
香港、*、澳门等也各有一家CA获得了这一认证。
通过认证后,意味着CA机构的运营管理和服务水平符合国际标准,并且有能力、有资质提供全球化认证服务,是可靠电子认证服务的有效证明。
主流的浏览器厂商,例如微软IE浏览器、 Mozilla火狐浏览器、苹果Safari浏览器以及谷歌Chrome浏览器在根证书植入项目中,一个基本
的要求就是要通过Webtrust
认证,实现浏览器与数字证书的无缝嵌入。
关于上面WebTrust
的科普来自此处
证书链和根证书
有时一个被信任的证书机构可能授权另一个证书机构颁发证书,也就是说会出现多个认证层级,这样就出现了证书链。如下图所示:
上图的证书C
就是根证书。除了根证书,其它证书都要依靠上一级的证书,来证明自己。
根证书是一份特殊的证书,它的签发者是它本身,下载根证书就表明您对该根证书以下所签发的证书都表示信任,而技术上则是建立起一个验证证书信息的链条,证书的验证追溯至根证书即为结束。所以说用户在使用某个数字证书之前必须先下载其根证书。
证书有多种格式
X.509 证书通常用于包含一个公钥
PKCS12 证书通常用来包含一个私钥,PKCS12需要密码才能打开。
- 1
- 2
- 3
创建和导入自签名证书
在上面的Https初体验
中我们知道,当输入https://localhost:8443/
后,Chrome浏览器会提示 您的连接不是私密连接
,为什么呢?
通过上面对证书
的介绍,我想大家应该已经明白了,因为证书是我们自己签名的,并不是权威机构发布的。所以我们访问https://github.com
的时候,显示安全的,但是访问https://localhost:8443/
会出现安全提示。
那有什么办法访问https://localhost:8443/
像访问github那样直接显示安全呢?如果明白了证书的原理,这也是很简单的,我们访问https://github.com
的时候显示安全,是因为Chrome浏览器内置了许多根证书,也就是说信任了这些根证书,我们只需要让系统信任我们自己的根证书就可以实现这样的需求了。
下面来生成一个证书:
1)生成一个别名为tomcat的keystore
keytool -genkey -alias tomcat -keyalg RSA
需要注意的是,注意把您的名字与姓氏是什么?
设置为你的本地IP
2)对刚才生成的keystore自签名一下
keytool -selfcert -alias tomcat -keystore C:/Users/johnny/.keystore
3)导出证书
keytool -export -alias tomcat -keystore C:/Users/johnny/.keystore -storepass 123456 -rfc -file C:/Users/johnny/tomcat.cer
主要就是三个步骤,具体的细节,可以参考我下面的记录。
下面是在我计算机上的生成证书的完整记录:
C:\Users\johnny>keytool -genkey -alias tomcat -keyalg RSA
输入**库口令:
再次输入新口令:
您的名字与姓氏是什么?
[Unknown]: 192.168.0.103
您的组织单位名称是什么?
[Unknown]: Chiclaim
您的组织名称是什么?
[Unknown]: Chiclaim
您所在的城市或区域名称是什么?
[Unknown]: Hangzhou
您所在的省/市/自治区名称是什么?
[Unknown]: Zhejiang
该单位的双字母国家/地区代码是什么?
[Unknown]: cn
CN=192.168.0.103, OU=Chiclaim, O=Chiclaim, L=Hangzhou, ST=Zhejiang, C=cn是否正确
?
[否]: y
输入 <tomcat> 的**口令
(如果和**库口令相同, 按回车):
C:\Users\johnny>keytool -selfcert -alias tomcat -keystore C:/Users/johnny/.keyst
ore
输入**库口令:
C:\Users\johnny>keytool -export -alias tomcat -keystore C:/Users/johnny/.keystor
e -storepass 123456 -rfc -file C:/Users/johnny/tomcat.cer
存储在文件 <C:/Users/johnny/tomcat.cer> 中的证书
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
在用户目录生成了两个文件(.keystore
和tomcat.cer
):
接下来就是要让系统信任我们的证书了(我用的是Chrome浏览器,当然也可以使用IE):
1)打开Google Chrome浏览器设置界面,滑倒最底部:
2)点击 管理证书
3)点击受信任的根证书颁发机构
后面就是傻瓜式的下一步了,最后系统可能会弹出一个警告,直接确定就可以了。
我们操作的其实是系统的信任的证书,虽然我们设置了Chrome浏览器,在IE也是生效的。我们在Windows命令框里输入 certmgr.msc
,可以看到我们刚刚设置的受信任的根证书
:
最后,我们看看浏览器访问的结果,记得输入的不是localhost,而是你本地的IP:
Chrome浏览器:
IE浏览器:
至此,我们在宏观上对证书有了一个比较全面的了解。当我们访问 https://192.168.0.103:8443 的时候,浏览器又是怎么对证书进行校验的呢?
证书格式介绍
PKCS 全称是 Public-Key Cryptography Standards ,是由 RSA 实验室与其它安全系统开发商为促进公钥密码的发展而制订的一系列标准,PKCS 目前共发布过 15 个标准。 常用的有:
PKCS#7 Cryptographic Message Syntax Standard
PKCS#10 Certification Request Standard
PKCS#12 Personal Information Exchange Syntax Standard
X.509 是常见通用的证书格式。所有的证书都符合为Public Key Infrastructure (PKI) 制定的 ITU-T X509 国际标准。
PKCS#7 常用的后缀是: .P7B .P7C .SPC
PKCS#12 常用的后缀有: .P12 .PFX
X.509 DER 编码(ASCII)的后缀是: .DER .CER .CRT
X.509 PAM 编码(Base64)的后缀是: .PEM .CER .CRT
.cer/.crt 是用于存放证书,它是2进制形式存放的,不含私钥。
.pem 跟crt/cer的区别是它以Ascii来表示。
pfx/p12 用于存放个人证书/私钥,他通常包含保护密码,2进制方式
p10 是证书请求
p7r 是CA对证书请求的回复,只用于导入
p7b 以树状展示证书链(certificate chain),同时也支持单个证书,不含私钥。
关于证书后缀格式来自: https://www.chinassl.net/ssltools/convert-ssl-commands.html
客户端验证证书
浏览器校验证书的时候,主要校验以下条件:
1)证书被系统的某个根证书信任
为什么证书要被系统某个根证书信任呢?就是为了判断用户访问的服务器端的证书是否是权威机构签发的。
当然,如果用户自己导入第三方根证书,那说明用户信任该证书,这就另当别论了。就像上面我们把自定义的根证书导入到了系统,让浏览器信任。
2)证书上绑定的域名和该网站的域名一致
我们在生成证书的时候,把您的名字与姓氏是什么?
设置为你的本地IP(192.168.0.103)
证书上绑定的域名和该网站的域名一致。所以我们访问的时候是没有问题的。
假如我们在生成证书的时候绑定的不是本地IP(192.168.0.103),那么会怎么样?我们现在重新生成一个证书吧,把IP设置为192.168.0.104,然后导入根证书,然后访问 https://192.168.0.103:8443/
:
Chrome浏览器的错误提醒:
IE浏览器错误提醒:
如果不使用Https,用户访问服务器,可能会被第三方拦截,如下图所示:
从上面的证书域名绑定的问题可以看出,Https可以有效的避免客户端(Client)和服务器端(Server)之间通信被其他人第三方截获。因为我们在通信的过程中能确保对方是合法的服务提供商。但是能确保对方的合法身份还是不够,还要确保在交互的过程中发送的数据是加密的,只有彼此才能解密,这样才能最终保证安全,关于Https
加密
与解密
后面会介绍。
3)证书没有过期
但是上面我们生成证书的时候并没有设置证书的有效期,那么证书的有效期是多久?
证书是1月24日生成的,到4月24日过期,所以证书的默认有效期为三个月
如果证书过期,IE浏览器会提示证书错误
:
当然,生成证书的时候也可以指定有效期,通过 -validity
参数,如 -validity 365 有效期365天。
向读者提出的问题
写到这里,对证书这块有了一个非常全面的了解了,最后向读者提一个问题,如果这篇文章真的理解了,这个问题很好解答。
问题描述如下:当我们访问12306的时候,如:https://www.12306.cn/mormhweb/ 结果如下:
问题1:为什么浏览器会在网址左侧的https上打了斜线(红叉)?
问题2:为什么12306界面里提示用户要安装根证书?
三、加密技术
为了更好的理解Https,先要来了解下加密技术。主要包括 对称加密
和 非对称加密
。
对称加密
对称加密采用了对称密码编码技术,它的特点是对内容使用相同的**来加密或者解密,即加***
也可以用作解***
,这种方法在密码学中叫做对称加密算法,对称加密算法使用起来简单快捷,**较短,且破译困难。
常用的对称加密算法有DES、DESede、IDEA、AES、Blowfish等等。
DES算法**偏短(56位),受到诸如查分密码分析和线性密码分析等各种攻击威胁,安全性受到严重威胁。DES算法的半公开性,该算法被广大密码学机构质疑。1998年后,实用化DES算法破译机的出现,DES算法已经不具备安全性。
然后DESede算法出现了,在一定程度上提升了算法安全强度,由于DESede算法的低效加密实现和较慢速度仍然不能满足我们对安全的要求。AES算法正是基于这些原因而诞生了。AES算法因**建立时间短、灵敏性好、内存要求低等优点,AES算法成为DES算法的替代者。
非对称加密
非对称加密算法有别于对称加密算法,将**一分为二,公钥
公开,私钥
保密。公钥通过非安全通道发放,私钥则由发放者保留。公钥于私钥相对应,成对出现。公钥加密的数据,只能使用私钥对其解密。反之,私钥加密数据,公钥对其解密。
非对称加密算法和对称加密算法相比,**管理问题不复存在,在安全性上有着无法逾越的高度,但是无法避免加密/解密效率低
这一问题。因此,非对称加密算法往往应用在一些安全性要求相当高的领域,如B2B、B2C等电子商务平台。
针对非对称加密算法的效率低问题,各密码学机构主张将对称加密算法与非对称加密算法相结合,使用对称加密算法
为数据加密/解密,使用非对称加密算法
的公钥
和私钥
为对称加密算法的**
加密/解密。利用对称加密算法的高效性,加之非对称加密算法的**管理,提升整体加密系统的安全性。
在算法设计上,非对称加密算法对加密数据长度有着极为苛刻的要求。例如,RSA算法要求待加密数据不得大于53个字节。
非对称加密算法主要用于交换对称加密算法的秘***,而非数据交换。
常见的非对称加密算法有:RSA、ECC、Diffie-Hellman、El Gamal、DSA(数字签名用)
上面对对称加密算法
和非对称加密算法
的介绍主要来自《Java加密与解密的艺术》,这本书对加密与解密有着详细、系统的介绍,有兴趣的读者可以去看看。
四、Https的交互过程
关于Https的交互过程,下面一张图非常清楚的描述了该过程:
下面对流程图用文字的形式解释一遍:
1)客户端发起一个https的请求,把自身支持的一系列Cipher Suite(**算法套件,简称Cipher)发送给服务端
2)服务端接收到客户端所有的Cipher后与自身支持的对比,如果不支持则连接断开,反之则会从中选出一种加密算法和HASH算法,以证书的形式返回给客户端。
3)客户端收到服务端响应的证书后
第一步、校验证书的是否有效。关于客户端校验证书的是否有效已经做了详细的介绍,这里就不赘述了。
第二步、生成随机密码。如果证书验证通过,或者用户接受了不授信的证书,此时浏览器会生成一串随机密码,然后用证书中的公钥加密。
第三步、用最开始约定好的HASH方式,把握手消息取HASH值,把用 `随机数密码`加密 “握手消息+握手消息HASH值(签名)”和用公钥加密的随机密码 一起发送给服务端。
把握手消息做一个签名,用于验证握手消息在传输过程中没有被篡改过。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
4)服务端拿到客户端传来的密文,用自己的私钥来解密,获取随机密码,再用随机数密码 解密 握手消息与HASH值,并与传过来的HASH值做对比确认是否一致。然后用随机密码加密一段握手消息(握手消息+握手消息的HASH值 )给客户端。(此时服务器端已经获取到了客户端生成的随机密码
了)
5)客户端用随机密码解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束。
之后所有的通信数据将由之前浏览器生成的随机密码
作为对称加密算法
的**对数据进行加密或解密。
其实上面的整个流程可以用一句话来概括:使用非对称加密算法来交换对称加密算法的**,使用这个对称加密算法的这个**来加密或解密数据。就像介绍加密这块内容的时候说的:非对称加密算法主要用于交换对称加密算法的秘***,而非数据交换。