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.实现:

生成密钥、证书

第一步,为服务器端和客户端准备公钥、私钥

  1. # 生成服务器端私钥
  2. openssl genrsa -out server.key 1024
  3. # 生成服务器端公钥
  4. openssl rsa -in server.key -pubout -out server.pem
  5. # 生成客户端私钥
  6. openssl genrsa -out client.key 1024
  7. # 生成客户端公钥
  8. openssl rsa -in client.key -pubout -out client.pem

第二步,生成 CA 证书

  1. # 生成 CA 私钥
  2. openssl genrsa -out ca.key 1024
  3. # X.509 Certificate Signing Request (CSR) Management.
  4. openssl req -new -key ca.key -out ca.csr
  5. # X.509 Certificate Data Management.
  6. openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt

在执行第二步时会出现:

  1. ➜  keys  openssl req -new -key ca.key -out ca.csr
  2. You are about to be asked to enter information that will be incorporated
  3. into your certificate request.
  4. What you are about to enter is what is called a Distinguished Name or a DN.
  5. There are quite a few fields but you can leave some blank
  6. For some fields there will be a default value,
  7. If you enter '.', the field will be left blank.
  8. -----
  9. Country Name (2 letter code) [AU]:CN
  10. State or Province Name (full name) [Some-State]:Zhejiang
  11. Locality Name (eg, city) []:Hangzhou
  12. Organization Name (eg, company) [Internet Widgits Pty Ltd]:My CA
  13. Organizational Unit Name (eg, section) []:
  14. Common Name (e.g. server FQDN or YOUR name) []:localhost
  15. 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 。

第三步,生成服务器端证书和客户端证书

  1. # 服务器端需要向 CA 机构申请签名证书,在申请签名证书之前依然是创建自己的 CSR 文件
  2. openssl req -new -key server.key -out server.csr
  3. # 向自己的 CA 机构申请证书,签名过程需要 CA 的证书和私钥参与,最终颁发一个带有 CA 签名的证书
  4. openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt
  5. # client 端
  6. openssl req -new -key client.key -out client.csr
  7. # client 端到 CA 签名
  8. openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crt

此时,我们的 keys 文件夹下已经有如下内容了:

  1. .
  2. ├── https-client.js
  3. ├── https-server.js
  4. └── keys
  5. ├── ca.crt
  6. ├── ca.csr
  7. ├── ca.key
  8. ├── ca.pem
  9. ├── ca.srl
  10. ├── client.crt
  11. ├── client.csr
  12. ├── client.key
  13. ├── client.pem
  14. ├── server.crt
  15. ├── server.csr
  16. ├── server.key
  17. └── server.pem

看到上面两个 js 文件了么,我们来跑几个demo。

HTTPS本地测试

服务器代码:

  1. // file http-server.js
  2. var https = require('https');
  3. var fs = require('fs');
  4. var options = {
  5. key: fs.readFileSync('./keys/server.key'),
  6. cert: fs.readFileSync('./keys/server.crt')
  7. };
  8. https.createServer(options, function(req, res) {
  9. res.writeHead(200);
  10. res.end('hello world');
  11. }).listen(8000);

短短几行代码就构建了一个简单的 https 服务器,options 将私钥和证书带上。然后利用 curl 测试:

  1. ➜  https  curl https://localhost:8000
  2. curl: (60) SSL certificate problem: Invalid certificate chain
  3. More details here: http://curl.haxx.se/docs/sslcerts.html
  4. curl performs SSL certificate verification by default, using a "bundle"
  5. of Certificate Authority (CA) public keys (CA certs). If the default
  6. bundle file isn't adequate, you can specify an alternate file
  7. using the --cacert option.
  8. If this HTTPS server uses a certificate signed by a CA represented in
  9. the bundle, the certificate verification probably failed due to a
  10. problem with the certificate (it might be expired, or the name might
  11. not match the domain name in the URL).
  12. If you'd like to turn off curl's verification of the certificate, use
  13. the -k (or --insecure) option.

当我们直接访问时, curl https://localhost:8000

一堆提示,原因是没有经过 CA 认证,添加 -k 参数能够解决这个问题:

  1. ➜  https  curl -k https://localhost:8000
  2. hello world%

这样的方式是不安全的,存在我们上面提到的中间人攻击问题。可以搞一个客户端带上 CA 证书试试:

  1. // file http-client.js
  2. var https = require('https');
  3. var fs = require('fs');
  4. var options = {
  5. hostname: "localhost",
  6. port: 8000,
  7. path: '/',
  8. methed: 'GET',
  9. key: fs.readFileSync('./keys/client.key'),
  10. cert: fs.readFileSync('./keys/client.crt'),
  11. ca: [fs.readFileSync('./keys/ca.crt')]
  12. };
  13. options.agent = new https.Agent(options);
  14. var req = https.request(options, function(res) {
  15. res.setEncoding('utf-8');
  16. res.on('data', function(d) {
  17. console.log(d);
  18. });
  19. });
  20. req.end();
  21. req.on('error', function(e) {
  22. console.log(e);
  23. });

先打开服务器 node http-server.js ,然后执行

  1. ➜  https  node https-client.js
  2. 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证书的验证过程与生成方法的更多相关文章

  1. APP中https证书有效性验证引发安全问题(例Fiddler可抓https包)

    原文: https://blog.csdn.net/woddle/article/details/71175140 在实际项目代码审计中发现,目前很多手机银行虽然使用了https通信方式,但是只是简单 ...

  2. 转载:HTTPS证书的产生过程详解

    1.RSA身份验证的隐患 身份验证和密钥协商是TLS的基础功能,要求的前提是合法的服务器掌握着对应的私钥.但RSA算法无法确保服务器身份的合法性,因为公钥并不包含服务器的信息,存在安全隐患:    客 ...

  3. 【腾讯Bugly干货分享】iOS 中 HTTPS 证书验证浅析

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/-fLLTtip509K6pNOTkflPQ 导语 本 ...

  4. linux自建https证书

    一.生成单向认证的https证书 建立服务器私钥,生成RSA秘钥. 会有两次要求输入密码, 然后获得了一个server.key文件. 以后使用此文件(通过openssl提供的命令或API)可能经常回要 ...

  5. TLS/HTTPS 证书生成与验证

    最近在研究基于ssl的传输加密,涉及到了key和证书相关的话题,走了不少弯路,现在总结一下做个备忘 科普:TLS.SSL.HTTPS以及证书 不少人可能听过其中的超过3个名词,但它们究竟有什么关联呢? ...

  6. [转]在 .NET 中远程请求 https 内容时,发生错误:根据验证过程,远程证书无效

    该文原网址:http://www.cnblogs.com/xwgli/p/5487930.html 在 .NET 中远程请求 https 内容时,发生错误:根据验证过程,远程证书无效.   当访问 h ...

  7. XmlDocument.Load(url) url是https远程时,报错" 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。" "根据验证过程,远程证书无效。"

    XmlDocument.Load(url)  url是https远程时,报错" 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系."   "根据验证过程, ...

  8. https 证书传递、验证和数据加密、解密过程解析

    我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取.所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议. HTTPS简介 HTTPS其实是有两部分组成:HTTP + SSL ...

  9. 免费生成https证书以及配置

    http升级到https需要在nginx的配置中加入证书信息,查询资料后确定生成证书两种方案   第一种:自签名证书,然后开启 CloudFlare 的 CDN 服务   //确定是否安装openss ...

随机推荐

  1. 【java编程】运算符

    一.位移运算 java中有三种移位运算符 <<      :     左移运算符,num << 1,相当于num乘以2 >>      :     右移运算符,nu ...

  2. Eclipse使用Maven时出现:Index downloads are disabled, search results may be incomplete.问题解决

    https://www.cnblogs.com/EasonJim/p/6674099.html 1.全局设置 [Windows]->[Preferences]->[Maven]->勾 ...

  3. rpm使用

    查找某个rpm包是否安装 rpm -qa|grep 包名 #我们再次安装是会提示和那个包冲突,直接复制那个报名过来就可 安装rpm包 rpm -ivh 报名

  4. NSNull floatValue intValue 找不到指定方法解决方式

    最近遇到一个问题:         因为后台人员对于接口数据没有做空值处理.导致client接收到的有些数据为空(NSNull),而针对此类数据恰好client的存储结构为int和float类型.类型 ...

  5. python 简明教程 【转】

    转自:https://learnxinyminutes.com/docs/python/ # Single line comments start with a number symbol. &quo ...

  6. 计算元素个数(count和count_if)

    count 计算first和last之间与value相等于元素个数 template <class InputIterator,class EqualityComparable> type ...

  7. 详解Linux查看实时网卡流量的几种方式(转)

    转自https://www.jb51.net/article/112965.htm 假如Keepalived有10个VIP,怎么查看每个VIP的流量呢? 这里就可以使用sar命令查看网卡流量了.前提是 ...

  8. 打造mac上最好用的Terminal

    出处:https://blog.csdn.net/kebing1011/article/details/46934533?utm_source=blogxgwz0

  9. struts2+dojo实现datagrid动态刷新

    实现一个普通的数据库查询功能,参考了这个帖子:http://stackoverflow.com/questions/5499453/how-to-refresh-datagrid 需要注意的是动态创建 ...

  10. 三种方法获取Class对象的区别

    有关反射的内容见 java反射 得到某个类的Class对象有三种方法: 使用“类名.class”取得 Class.forName(String className) 通过该类实例对象的getClass ...