秒懂Https之CA证书与自签名证书漫谈

【版权申明】非商业目的注明出处可自由转载
博文地址: http://shusheng007.top/2020/07/25/1-3/
出自:shusheng007

相关文章:
数字签名的原理及其应

概述

最近抽时间让APP支持了https的功能,所以总结一下相关的知识,以飨读者。

预备知识:必须对https有基本的理解

Https

HTTPS: Hypertext Transfer Protocol Secure 超文本安全传输协议,太普遍了,列出关键点,不做过多解释。

  1. 客户端与服务端使用非对称加密将一个秘钥传递给对方。
  2. 双方使用此秘钥通过对称加密通信。

证书

我们知道非对称加密需要一对秘钥:公钥和私钥。当一方拥有了此秘钥对后,最头疼的事情就是如何将公钥安全的传递给对方。因为通讯过程是不安全的,我们不知道公钥在传递过程中会发生什么(中间人攻击)。此时CA就粉墨登场了,其存在的意义就是确保通信的一方可以安全的获取到对方的公钥。

我们先介绍几个相关名词,然后简单谈一谈CA是如何赚这份钱的。

CA: certificate authority , 负责颁发CA证书的机构和组织,都是一些欧美邪恶组织,轻易不让别人加入。
CA证书:CA机构颁发给其他人的证书。主要包含如下信息

  • 申请者公钥
  • 申请者的信息
  • 颁发者(CA)的信息
  • 以上信息的数字签名
    数字签名生成规则:先使用摘要算法,例如SHA256,将以上信息生成摘要,然后CA使用自己的私钥对此摘要加密

    那CA到底是如何赚这份钱的呢? 简单来说就是CA帮你做担保,担保那个公钥确实是和你通信的那一方的。那他是怎做到的呢?且听我娓娓道来

第一步: CA ,就是那些欧美邪恶组织,先找操作系统厂商以及浏览器厂商,例如微软、Google、Apple等私通苟且,大家关起门来讨价还价一番,最后让这些厂商在自己的操作系统或者浏览器中内置CA的根证书(以及二级证书)。大家约定好,只有能通过这些证书验证的其他证书才是合法的,否则都他娘的不许放行,或者吓唬用户:“系统检测到你访问的地址是不安全的,继续访问有可能被爆菊花…”。

通过这一步就达到了如下效果:你先信任了A,然后通过A去校验未知的B、C、D…

第二步:CA通过这一顿骚操作,就逼得用户需要向CA申请证书了。因为要使用HTTPS就需要公钥私钥对,但是如果你自己产生一对的话,当用户使用浏览器访问你的服务器时,你把公钥传给浏览器,那些内置的CA根证书就去校验你这个公钥,然后大惊失色的告诉用户:“不好!你访问的网站可能是个恶意网站,你有可能被爆菊花…” 经此一吓,大部分用户也就不用你的服务了,长此以往,公司就的解散,到时候下海去做鸭,就真的要被爆菊花了…那首歌怎么唱来着:“一步踏错终身错,下海伴舞为了生活…”

有的同学又要反驳了:你又瞎哔哔,我上12306官网去买火车票时,浏览器就会提示我有可能被爆菊花,但是也没见人家倒闭啊… 你是12306吗?你家卖火车票吗?过年回家的时候别说提示你爆菊花,就是提示你有可能吃屎,你也得点进去抢票啊… 这就是垄断的力量!话说强如12306,最近好像也申请了CA证书了。

王二狗不想去下海,所以鼓动其公司《圣女果科技》向CA申请CA证书,其需要如下步骤
a: 向CA提供公司的公钥,公司信息,域名等信息
b: CA调查并确认这些信息都是真实的
c: 圣女果交钱给CA
d: CA向圣女果颁发证书

让我们看一下这些CA根证书的样子吧:

在Chrome中的某个CA证书
在这里插入图片描述
Android中的CA证书列表
在这里插入图片描述

有了CA证书,公司就可以正常开展业务了。下面看一下当一个用户访问《圣女果科技》官网时证书的验证流程

第三步: 验证证书流程
设客户端为:C,服务端为:S

  • C以https方式访问S
  • S返回其证书SngCer给C
  • C使用内置CA根证书验证SngCer。 验证过程如下:

    SngCer中明文信息使用相同摘要算法生成摘要得到 digest1;
    使用CA根证书中的CA的公钥SngCer中的数字签名解密得到digest2;
    对比digest1与digest2,如果相同则说明SngCer没有被篡改过,而且是CA颁发出去的,可以放心使用其明文信息。

  • 验证 SngCer中的那些明文信息,例如证书是否过期,域名是否正确,证书是否被吊销等

通过以上介绍我们发现最开始困扰我们如何传递公钥的问题就这样被解决了:用户无条件信任一个预先安装的公钥

理解了CA证书,自签名证书就比较好理解了。就是我们自己生成一对公钥私钥,自己用。如果是浏览器访问,就要忍受其安全提示。如果是运行在Android或者IOS设备中的App呢,访问就会失败。

那如何才能不失败呢?浏览器就比较尴尬了,因为浏览器都是别人开发的,你总不能把你的自签名证书导入我电脑上的浏览器中吧。但是在我们自己开发的App中还是可以使用的,写程序完成证书验证过程就好了。

自签名证书

要处理HTTPS相关的问题可以使用大名鼎鼎的 OpenSSL,但是我没怎么用过。其实JDK自带了一个工具keytool也可以完成。

如果你配置了java的环境变量,可以直接在命令行窗口输入如下命令查看此工具的信息

keytool --help
密钥和证书管理工具

命令:

 -certreq            生成证书请求
 -changealias        更改条目的别名
 -delete             删除条目
 -exportcert         导出证书
 -genkeypair         生成密钥对
 -genseckey          生成密钥
 -gencert            根据证书请求生成证书
 -importcert         导入证书或证书链
 -importpass         导入口令
 -importkeystore     从其他密钥库导入一个或所有条目
 -keypasswd          更改条目的密钥口令
 -list               列出密钥库中的条目
 -printcert          打印证书内容
 -printcertreq       打印证书请求的内容
 -printcrl           打印 CRL 文件的内容
 -storepasswd        更改密钥库的存储口令

使用 "keytool -command_name -help" 获取 command_name 的用法

使用keytool可以生成keystore, 其是存放 “加密密钥、X.509证书链和受信任证书” 等的数据库。其有多种格式,我们这里使用行业标准格式PKCS12

生成PKCS12格式的KeyStore

keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650 -ext san=ip:192.168.xx.xx -storepass password
  • genkeypair: 产生一个密钥对;
  • alias: 产生的keystore的别名;
  • keyalg: 密钥对使用的加密算法(alg是algorithm 的缩写);
  • keysize: 秘钥长度,此处为2048 bits, 如果需要更安全可以使用 4096 bits;
  • storetype: keystore的类型,此处为PKCS12;
  • keystore: keystore文件名称;
  • validity: 有效期天数,3650表示有效期为10年;
  • storepass: keystore的密码.
  • -ext 额外信息,此处添加了Subject Alternate Name (SAN) san=ip:192.168.31.25 san后面是你的主机名,域名或者IP。
    例如要同时添加域名与IP使用下面的配置:

    san=dns:shusheng007.top,ip:192.168.10.xxx

    如果证书中不把域名或者IP放进去的话,客户端请求的时候需要设置不验证主机名,否则证书验证不过。

执行上面命令后需要你提供一些信息:

您的名字与姓氏是什么?
  [Unknown]:  shusheng007
您的组织单位名称是什么?
  [Unknown]:  sng
您的组织名称是什么?
  [Unknown]:  sng
您所在的城市或区域名称是什么?
  [Unknown]:  tianjin
您所在的省/市/自治区名称是什么?
  [Unknown]:  jinan
该单位的双字母国家/地区代码是什么?
  [Unknown]:  cn
CN=shusheng007, OU=sng, O=sng, L=tianjin, ST=jinan, C=cn是否正确?
  [否]:  y

输入y后回车,就会在你的目录下生成一个keystore.p12文件,这个文件就是我们的keystore

查看keystore中的信息

keystore.p12文件所在目录执行如下命令:

keytool -list -v -storetype pkcs12 -keystore keystore.p12

出现如下信息,输入生成时候的密码,我们这里是shusheng007,回车即可

输入密钥库口令:

密钥库类型: PKCS12
密钥库提供方: SunJSSE

您的密钥库包含 1 个条目

别名: sng
创建日期: 2020-7-23
条目类型: PrivateKeyEntry
证书链长度: 1
证书[1]:
所有者: CN=shusheng007, OU=sng, O=sng, L=tianjin, ST=jinan, C=cn
发布者: CN=shusheng007, OU=sng, O=sng, L=tianjin, ST=jinan, C=cn
序列号: 1990d91e
有效期开始日期: Thu Jul 23 21:52:40 CST 2020, 截止日期: Sun Jul 21 21:52:40 CST 2030
证书指纹:
         MD5: 68:D8:C0:E4:32:35:D0:17:7C:0D:8E:AC:0E:BD:40:3E
         SHA1: 84:3A:10:7E:16:66:E3:FB:94:5B:16:2A:FD:3C:34:B2:1E:8A:8E:DE
         SHA256: FA:29:C9:66:F0:78:8B:3B:17:1A:B1:40:51:C4:32:AB:4A:D5:FC:B3:98:75:D9:51:5E:EB:7E:40:6D:2E:7F:C0
         签名算法名称: SHA256withRSA
         版本: 3

扩展:

#1: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
  IPAddress: 192.168.31.158
]

#2: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 05 3E 67 C8 B8 D8 04 82   FB 71 F0 35 90 F7 E6 F2  .>g......q.5....
0010: 06 E8 78 1C                                        ..x.
]
]
*******************************************
*******************************************

从keystore到出ssl证书

当我们要在客户端,例如Android,中使用时需要从keystore中导出ssl证书myCertificate.crt

keytool -export -keystore keystore.p12 -alias sng -file myCertificate.crt

输入密码后生成ssl证书

输入密钥库口令:
存储在文件 <myCertificate.crt> 中的证书

在这里插入图片描述
只要导出了ssl证书,我们就可以在Android中或者浏览器中使用了,如何使用有机会再说。

将现有ssl 证书导入到keystore中

我们前面说过,keystore就是一个容器或者说数据库,所以我们是可以把现有的ssl证书导入其中的。

keytool -import -alias sng -file myCertificate.crt -keystore keystore.p12 -storepass shusheng007

我们尝试将刚生成的ssl证书导入keystore.p12中,结果失败了,因为库中已经有一个一模一样的了。

keytool 错误: java.lang.Exception: 证书回复与密钥库中的证书是相同的

总结

行文到此又该结束了,本文讲述了CA证书的工作原理,以及如何生成自签名证书,相信你又get到不少新技能,注意点赞收藏,用时回看。

等有时间我会将如何在前(Android)后端(SpringBoot2)中使用自签名证书总结出来,让其他小伙伴少走弯路,点赞超过50就开写,敬请期待!

参考文章:
https://www.cnblogs.com/handsomeBoys/p/6556336.html
https://www.jianshu.com/p/29e0ba31fb8d

About the Author: shusheng007

发表评论

邮箱地址不会被公开。