https证书的验证过程与生成方法
1.简洁的解释:
1.服务器 用RSA生成公钥和私钥
2.把公钥放在证书里发送给客户端,私钥自己保存
3.客户端首先向一个权威的服务器检查证书的合法性,如果证书合法,客户端产生一段随机数,这个随机数就作为通信的密钥,我们称之为对称密钥,用公钥加密这段随机数,然后发送到服务器
4.服务器用密钥解密获取对称密钥,然后,双方就已对称密钥进行加密解密通信了
PS:非对称的RSA加密性能是非常低的,原因在于寻找大素数、大数计算、数据分割需要耗费很多的CPU周期,所以一般的HTTPS连接只在第一次握手时使用非对称加密,通过握手交换对称加密密钥,在之后的通信走对称加密。
2.详细的:
1.浏览器将自己支持的一套加密规则发送给网站。 
2.网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。 
3.浏览器获得网站证书之后浏览器要做以下工作: 
a) 验证证书的合法性(颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致等),如果证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示。 
b) 如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。 
c) 使用约定好的HASH算法计算握手消息,并使用生成的随机数对消息进行加密,最后将之前生成的所有信息发送给网站。 
4.网站接收浏览器发来的数据之后要做以下的操作: 
a) 使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。 
b) 使用密码加密一段握手消息,发送给浏览器。 
5.浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。
3.实现:
生成密钥、证书
第一步,为服务器端和客户端准备公钥、私钥
- # 生成服务器端私钥
 - openssl genrsa -out server.key 1024
 - # 生成服务器端公钥
 - openssl rsa -in server.key -pubout -out server.pem
 - # 生成客户端私钥
 - openssl genrsa -out client.key 1024
 - # 生成客户端公钥
 - openssl rsa -in client.key -pubout -out client.pem
 
第二步,生成 CA 证书
- # 生成 CA 私钥
 - openssl genrsa -out ca.key 1024
 - # X.509 Certificate Signing Request (CSR) Management.
 - openssl req -new -key ca.key -out ca.csr
 - # X.509 Certificate Data Management.
 - openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
 
在执行第二步时会出现:
- ➜ keys openssl req -new -key ca.key -out ca.csr
 - You are about to be asked to enter information that will be incorporated
 - into your certificate request.
 - What you are about to enter is what is called a Distinguished Name or a DN.
 - There are quite a few fields but you can leave some blank
 - For some fields there will be a default value,
 - If you enter '.', the field will be left blank.
 - -----
 - Country Name (2 letter code) [AU]:CN
 - State or Province Name (full name) [Some-State]:Zhejiang
 - Locality Name (eg, city) []:Hangzhou
 - Organization Name (eg, company) [Internet Widgits Pty Ltd]:My CA
 - Organizational Unit Name (eg, section) []:
 - Common Name (e.g. server FQDN or YOUR name) []:localhost
 - Email Address []:
 
注意,这里的 Organization Name (eg, company) [Internet Widgits Pty Ltd]: 后面生成客户端和服务器端证书的时候也需要填写,不要写成一样的!!!可以随意写如:My CA, My Server, My Client。
然后 Common Name (e.g. server FQDN or YOUR name) []: 这一项,是最后可以访问的域名,我这里为了方便测试,写成 localhost ,如果是为了给我的网站生成证书,需要写成 barretlee.com 。
第三步,生成服务器端证书和客户端证书
- # 服务器端需要向 CA 机构申请签名证书,在申请签名证书之前依然是创建自己的 CSR 文件
 - openssl req -new -key server.key -out server.csr
 - # 向自己的 CA 机构申请证书,签名过程需要 CA 的证书和私钥参与,最终颁发一个带有 CA 签名的证书
 - openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt
 - # client 端
 - openssl req -new -key client.key -out client.csr
 - # client 端到 CA 签名
 - openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crt
 
此时,我们的 keys 文件夹下已经有如下内容了:
- .
 - ├── https-client.js
 - ├── https-server.js
 - └── keys
 - ├── ca.crt
 - ├── ca.csr
 - ├── ca.key
 - ├── ca.pem
 - ├── ca.srl
 - ├── client.crt
 - ├── client.csr
 - ├── client.key
 - ├── client.pem
 - ├── server.crt
 - ├── server.csr
 - ├── server.key
 - └── server.pem
 
看到上面两个 js 文件了么,我们来跑几个demo。
HTTPS本地测试
服务器代码:
- // file http-server.js
 - var https = require('https');
 - var fs = require('fs');
 - var options = {
 - key: fs.readFileSync('./keys/server.key'),
 - cert: fs.readFileSync('./keys/server.crt')
 - };
 - https.createServer(options, function(req, res) {
 - res.writeHead(200);
 - res.end('hello world');
 - }).listen(8000);
 
短短几行代码就构建了一个简单的 https 服务器,options 将私钥和证书带上。然后利用 curl 测试:
- ➜ https curl https://localhost:8000
 - curl: (60) SSL certificate problem: Invalid certificate chain
 - More details here: http://curl.haxx.se/docs/sslcerts.html
 - curl performs SSL certificate verification by default, using a "bundle"
 - of Certificate Authority (CA) public keys (CA certs). If the default
 - bundle file isn't adequate, you can specify an alternate file
 - using the --cacert option.
 - If this HTTPS server uses a certificate signed by a CA represented in
 - the bundle, the certificate verification probably failed due to a
 - problem with the certificate (it might be expired, or the name might
 - not match the domain name in the URL).
 - If you'd like to turn off curl's verification of the certificate, use
 - the -k (or --insecure) option.
 
当我们直接访问时, curl https://localhost:8000
一堆提示,原因是没有经过 CA 认证,添加 -k 参数能够解决这个问题:
- ➜ https curl -k https://localhost:8000
 - hello world%
 
这样的方式是不安全的,存在我们上面提到的中间人攻击问题。可以搞一个客户端带上 CA 证书试试:
- // file http-client.js
 - var https = require('https');
 - var fs = require('fs');
 - var options = {
 - hostname: "localhost",
 - port: 8000,
 - path: '/',
 - methed: 'GET',
 - key: fs.readFileSync('./keys/client.key'),
 - cert: fs.readFileSync('./keys/client.crt'),
 - ca: [fs.readFileSync('./keys/ca.crt')]
 - };
 - options.agent = new https.Agent(options);
 - var req = https.request(options, function(res) {
 - res.setEncoding('utf-8');
 - res.on('data', function(d) {
 - console.log(d);
 - });
 - });
 - req.end();
 - req.on('error', function(e) {
 - console.log(e);
 - });
 
先打开服务器 node http-server.js ,然后执行
- ➜ https node https-client.js
 - hello world
 
如果你的代码没有输出
hello world ,说明证书生成的时候存在问题。也可以通过浏览器访问:

提示错误:
此服务器无法证明它是localhost;您计算机的操作系统不信任其安全证书。出现此问题的原因可能是配置有误或您的连接被拦截了。
原因是浏览器没有 CA 证书,只有 CA 证书,服务器才能够确定,这个用户就是真实的来自 localhost 的访问请求(比如不是代理过来的)。
你可以点击 继续前往localhost(不安全) 这个链接,相当于执行 curl -k https://localhost:8000 。如果我们的证书不是自己颁发,而是去靠谱的机构去申请的,那就不会出现这样的问题,因为靠谱机构的证书会放到浏览器中,浏览器会帮我们做很多事情。初次尝试的同学可以去 startssl.com 申请一个免费的证书。
参考链接:https://blog.csdn.net/abcd1101/article/details/71512809
https证书的验证过程与生成方法的更多相关文章
- APP中https证书有效性验证引发安全问题(例Fiddler可抓https包)
		
原文: https://blog.csdn.net/woddle/article/details/71175140 在实际项目代码审计中发现,目前很多手机银行虽然使用了https通信方式,但是只是简单 ...
 - 转载:HTTPS证书的产生过程详解
		
1.RSA身份验证的隐患 身份验证和密钥协商是TLS的基础功能,要求的前提是合法的服务器掌握着对应的私钥.但RSA算法无法确保服务器身份的合法性,因为公钥并不包含服务器的信息,存在安全隐患: 客 ...
 - 【腾讯Bugly干货分享】iOS 中 HTTPS 证书验证浅析
		
本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/-fLLTtip509K6pNOTkflPQ 导语 本 ...
 - linux自建https证书
		
一.生成单向认证的https证书 建立服务器私钥,生成RSA秘钥. 会有两次要求输入密码, 然后获得了一个server.key文件. 以后使用此文件(通过openssl提供的命令或API)可能经常回要 ...
 - TLS/HTTPS 证书生成与验证
		
最近在研究基于ssl的传输加密,涉及到了key和证书相关的话题,走了不少弯路,现在总结一下做个备忘 科普:TLS.SSL.HTTPS以及证书 不少人可能听过其中的超过3个名词,但它们究竟有什么关联呢? ...
 - [转]在 .NET 中远程请求 https 内容时,发生错误:根据验证过程,远程证书无效
		
该文原网址:http://www.cnblogs.com/xwgli/p/5487930.html 在 .NET 中远程请求 https 内容时,发生错误:根据验证过程,远程证书无效. 当访问 h ...
 - XmlDocument.Load(url)  url是https远程时,报错" 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。"   "根据验证过程,远程证书无效。"
		
XmlDocument.Load(url) url是https远程时,报错" 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系." "根据验证过程, ...
 - https  证书传递、验证和数据加密、解密过程解析
		
我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取.所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议. HTTPS简介 HTTPS其实是有两部分组成:HTTP + SSL ...
 - 免费生成https证书以及配置
		
http升级到https需要在nginx的配置中加入证书信息,查询资料后确定生成证书两种方案 第一种:自签名证书,然后开启 CloudFlare 的 CDN 服务 //确定是否安装openss ...
 
随机推荐
- UBUNTU 安装教程
			
玩过linux,只是博主觉得现在的很多服务器都是linux系统的,而自己属于那种前端也搞,后台也搞,对框架搭建也感兴趣,但是很多生产上的框架和工具都是安装在服务器上的,而且有不少大公司都要求熟悉在li ...
 - 使用distillery&&docker 部署phoenix 应用
			
distillery 发布了2.0 了,有好多的新的功能 config prodiver 进行环境变量的配置 appup tansforms 插件系统,方便在release 构建的时候进行修改 m ...
 - 01c++学习
			
#include"iostream" using namespace std; void main01() { //printf("hello_world\n" ...
 - c++简单的ATL COM开发和调用实例
			
1.打开VS2010.新建ATL COM 项目.步骤:"文件" -->"新建" -->"项目",选择"Visual C ...
 - linux之 awk
			
简介awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进 ...
 - [c/c++]可变参数的使用
			
一.可变参数简介 当一个函数需要传递未知个数的参数时,就需要用到可变参数, 比如常见的printf()函数,输出多个变量: printf("print para1:%d ,para2 :%d ...
 - itertools.groupby()/itertools.compress() 笔记
			
关于itertools.groupby() itertools.groupby()就是将相邻的并且相同的键值划分为同一组,相似功能可以看https://docs.python.org/3/librar ...
 - 使用Vivado进行行为级仿真
			
使用Vivado进行行为级仿真 1.编写设计文件 module test( input in, output out ); assign out = ~in; endmodule 2.编写testbe ...
 - ionic popup 做法及样式修改
			
ionic popup的做法很简单,一共有三种:show.confirm和alert,官网上讲得很详细. 一.confirm: js:var confirmPopup = $ionicPopup.co ...
 - apache配置https协议
			
安装openssl有两种方式,第一种直接下载安装包,装上就可运行:第二种可以自己下载源码,自己编译.下面对两种方式均进行详细描述. 一.下载和安装openss 方法一:直接使用openssl安装包 W ...