关于HTTPS一篇文章就够了

欢迎转载,转载请标明出处:

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

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

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

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

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

时间: 2024-10-10 21:43:10

关于HTTPS一篇文章就够了的相关文章

面试题-关于Java线程池一篇文章就够了

在Java面试中,线程池相关知识,虽不能说是必问提,但出现的频次也是非常高的.同时又鉴于公众号"程序新视界"的读者后台留言让写一篇关于Java线程池的文章,于是就有本篇内容,本篇将基于Java线程池的原理.实现以及相关源码进行讲解等. 什么是线程池 线程池是一种多线程处理形式,处理过程中将任务提交到线程池,任务的执行交由线程池来管理. 为了充分利用CPU多核资源,应用都会采用多线程并行/并发计算,最大限度的利用多核提升应用程序性能. 试想一下,如果每个请求都执行一遍创建线程.执行任务.

(转) TensorFlow深度学习,一篇文章就够了

TensorFlow深度学习,一篇文章就够了 2016/09/22 · IT技术 · TensorFlow, 深度学习 分享到:6 原文出处: 我爱计算机 (@tobe迪豪 ) 作者: 陈迪豪,就职小米科技,深度学习工程师,TensorFlow代码提交者. TensorFlow深度学习框架 Google不仅是大数据和云计算的领导者,在机器学习和深度学习上也有很好的实践和积累,在2015年年底开源了内部使用的深度学习框架TensorFlow. 与Caffe.Theano.Torch.MXNet等框

Android:学习AIDL,这一篇文章就够了(上)

前言 在决定用这个标题之前甚是忐忑,主要是担心自己对AIDL的理解不够深入,到时候大家看了之后说--你这是什么玩意儿,就这么点东西就敢说够了?简直是坐井观天不知所谓--那样就很尴尬了.不过又转念一想,我辈年轻人自当有一种一往无前的锐气,标题大气一点岂不更好?并且大家都是文明人,总归更多的是理解与补充而不是侮辱与谩骂?所以最终还是厚颜用了这么一个不怎么有耻的标题. 好了,接下来进入正题,谈谈我对AIDL的理解和认识. 正文 1,概述 AIDL是一个缩写,全称是Android Interface D

如何进行云主机迁移?看这一篇文章就够了!

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云计算产品团队发表于云+社区专栏 主机迁移概述 在云计算时代,不管是从IDC上云还是多云直接的迁移,都已经是常见的事宜.而在上云/迁移的方案中,也是有多种的方式能够将主机迁移到腾讯云中. 然而,不同的方式会有不同的利弊. 目前,腾讯云可以提供导入镜像和服务迁移(冷迁移)的工具,而这两种方式均涉及到镜像制作.故本文将分享镜像制作的操作步骤,仅供参考. 1.在制作镜像之前需要了解符合导入腾讯云的镜像文件要求,详情可参考导入镜像概述

彻底理解Netty,这一篇文章就够了

Netty到底是什么 从HTTP说起 有了Netty,你可以实现自己的HTTP服务器,FTP服务器,UDP服务器,RPC服务器,WebSocket服务器,Redis的Proxy服务器,MySQL的Proxy服务器等等. 我们回顾一下传统的HTTP服务器的原理 1.创建一个ServerSocket,监听并绑定一个端口 2.一系列客户端来请求这个端口 3.服务器使用Accept,获得一个来自客户端的Socket连接对象 4.启动一个新线程处理连接 4.1.读Socket,得到字节流 4.2.解码协议

maven一篇文章就够了(上)

一:maven的发展历程 在maven发展之前,传统的jar包管理我们一般会用ant+lvy来管理jar包,它有显而易见的两个缺点, 缺点一:需要我们来手动的来打jar包(build as),然后把打过得包放到我们规定的目录下(虽然可以进行特殊的处理引用本地的应用,不需要打包,但是前提条件就是你的有这个应用的源码). 缺点二:每一个应用都需要有相同的配置,重复的工作不停的在做,这样的话相当月重复造轮子,这也不太符合编程语言的原则. 基于这两点:我们从农业社会开始向工业社会转型,开始步入maven

Activity、View、Window的理解一篇文章就够了

作者:细卷子 博客:http://www.jianshu.com/u/511ccb5a2012 要了解这三者之间的关系,我们带着问题通过分析源码一步一步来揭开它们的神秘面纱! 文章有点长,首先要理解Activity.View.Window,我提出了一些问题,这篇文章可以解答如下问题: 1.为什么要设计Activity.View.Window? 2.Activity工作过程是什么样的?(理解Activity) 3.Window是什么?它的职能是什么? 4.View跟Window有什么联系? 5.A

Dart入门?一篇文章就够了!

近期公司准备启动新项目,经过技术团队一番调研,决定采用 Flutter 来开发第一版App,故作此文,常来回顾温习.由于项目采用敏捷开发模式,故本文主要总结和记录 Dart 常用语法,更多高级和生僻用法将在后面开发过程中不定期更新. First of all 在我们正式接触 Dart 语法之前,需要铭记以下内容,这将会对后续 Dart 语法的学习.理解和应用有很大帮助: 万物皆对象, 每个对象都是一个类的实例.在 Dart 中,甚至连数字.方法和 null 都是对象,并且所有的对象都继承于 Ob

100JAVA设计模式看着一篇文章就够了!

学JAVA设计模式,会遇到一下几个难题: 1.记不住 a.记不住7大原则,23种设计模式! b.不能复述设计模式代码,UML图! 2.看不懂 a.看不懂代码演示! b.看不懂高手代码! c,看不懂框架代码! 3.不会用 业务逻辑处理怎么用? 业务变更怎么用? 业务扩展怎么用? 4.带你看懂Spring源码中各种设计模式,充分理解架构设计中大师如何构建高扩展系统! 原文地址:https://www.cnblogs.com/gcq243627152qq/p/12003808.html