码迷,mamicode.com
首页 > Web开发 > 详细

关于HTTPS一篇文章就够了

时间:2017-01-27 16:39:19      阅读:407      评论:0      收藏:0      [点我收藏+]

标签:自治区   out   gen   微软   生成随机密码   比较   tls   ide   服务器端   

欢迎转载,转载请标明出处:
http://blog.csdn.net/johnny901114/article/details/54754921
本文出自:【余志强的博客】

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" />

然后我们启动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)

说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> 的密钥口令
        (如果和密钥库口令相同, 按回车):

密码我设置为 123456。在C盘用户目录下就有一个.keystore文件,在Tomcat目录下新建一个keystore文件夹,将文件拷贝到该目录下,然后修改server.xml中我们取消注释的那段配置加两个属性keystoreFilekeystorePass。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" />

然后往浏览器框里输入: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的认可,成为微软等大厂商支持的标准,目前VerisignEntrustIdentrust等国际上的大型CA机构以及发达国家和地区的认证机构大多数都获得了Webtrust认证。

香港、台湾、澳门等也各有一家CA获得了这一认证。

通过认证后,意味着CA机构的运营管理和服务水平符合国际标准,并且有能力、有资质提供全球化认证服务,是可靠电子认证服务的有效证明。

主流的浏览器厂商,例如微软IE浏览器、 Mozilla火狐浏览器、苹果Safari浏览器以及谷歌Chrome浏览器在根证书植入项目中,一个基本的要求就是要通过Webtrust认证,实现浏览器与数字证书的无缝嵌入。

关于上面WebTrust的科普来自此处

证书链和根证书

有时一个被信任的证书机构可能授权另一个证书机构颁发证书,也就是说会出现多个认证层级,这样就出现了证书链。如下图所示:

技术分享

上图的证书C就是根证书。除了根证书,其它证书都要依靠上一级的证书,来证明自己。

根证书是一份特殊的证书,它的签发者是它本身,下载根证书就表明您对该根证书以下所签发的证书都表示信任,而技术上则是建立起一个验证证书信息的链条,证书的验证追溯至根证书即为结束。所以说用户在使用某个数字证书之前必须先下载其根证书。

证书有多种格式

X.509 证书通常用于包含一个公钥
PKCS12 证书通常用来包含一个私钥,PKCS12需要密码才能打开。

创建和导入自签名证书

在上面的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> 中的证书

在用户目录生成了两个文件(.keystoretomcat.cer):

技术分享

接下来就是要让系统信任我们的证书了(我用的是Chrome浏览器,当然也可以使用IE):

1)打开Google Chrome浏览器设置界面,滑倒最底部:

技术分享

2)点击 管理证书

技术分享

3)点击受信任的根证书颁发机构

技术分享

后面就是傻瓜式的下一步了,最后系统可能会弹出一个警告,直接确定就可以了。

我们操作的其实是系统的信任的证书,虽然我们设置了Chrome浏览器,在IE也是生效的。我们在Windows命令框里输入 certmgr.msc,可以看到我们刚刚设置的受信任的根证书

技术分享

最后,我们看看浏览器访问的结果,记得输入的不是localhost,而是你本地的IP:

Chrome浏览器:

技术分享

IE浏览器:

技术分享

至此,我们在宏观上对证书有了一个比较全面的了解。当我们访问 https://192.168.0.103:8443 的时候,浏览器又是怎么对证书进行校验的呢?

客户端验证证书

浏览器校验证书的时候,主要校验以下条件:

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值(签名)”和用公钥加密的随机密码 一起发送给服务端。
把握手消息做一个签名,用于验证握手消息在传输过程中没有被篡改过。

4)服务端拿到客户端传来的密文,用自己的私钥来解密,获取随机密码,再用随机数密码 解密 握手消息与HASH值,并与传过来的HASH值做对比确认是否一致。然后用随机密码加密一段握手消息(握手消息+握手消息的HASH值 )给客户端。(此时服务器端已经获取到了客户端生成的随机密码了)

5)客户端用随机密码解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束。
之后所有的通信数据将由之前浏览器生成的随机密码作为对称加密算法的密钥对数据进行加密或解密。

其实上面的整个流程可以用一句话来概括:使用非对称加密算法来交换对称加密算法的密钥,使用这个对称加密算法的这个密钥来加密或解密数据。就像介绍加密这块内容的时候说的:非对称加密算法主要用于交换对称加密算法的秘密密钥,而非数据交换。

写在后面的话

写这篇博客大概花了4-5天的时间,期间断断续续的。

白天没有怎么写,主要还是晚上在写,在写的过程中也是在不断的学习。

以前对Https也是似懂非懂的感觉。现在发现通过博客的形式来推动技术的研究也是挺好的,我是边研究边写的,查阅了很多资料。阅读了一些资料,然后不断地自己给自己提出问题,然后自己找资料来解答自己的疑问。

随着自己提出的问题越多,解决的越多,那么你对该技术的理解也就越深入。

所以在研究技术的时候要不断的给自己提出问题,而不是看了几篇博客就感觉自己懂了。有句话老话说得好,检验这门技术是否真正的掌握,是去教别人,然后解决他的一些提问。

在一个就是多动手,俗话说纸上得来终觉浅嘛。有的时候别人说的不一定正确,只有自己试过才知道。

最后一句话:多归纳,多总结,多提问,多动手!

关于HTTPS一篇文章就够了

标签:自治区   out   gen   微软   生成随机密码   比较   tls   ide   服务器端   

原文地址:http://blog.csdn.net/johnny901114/article/details/54754921

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!