——加餐开始——
相关技术
SSL/TLS
为了解决HTTP明文传输信息的安全问题,HTTPS在HTTP的基础上引入了 SSL/TLS (Secure Sockets Layer / Transport Layer Security) 安全协议,使得信息能够加密传输。
我们先来看一下SSL/TLS的发展历史:
其实,SSL是TLS的前生。
SSL是网景公司设计的,在SSL 3.0后,网景公司将SSL交给了IETF(互联网工程任务组),IETF将SSL标准化,推出TLS 1.0(= SSL 3.1),并将其录入RFC(记录互联网规范、协议、过程等的标准文件)。经过更新迭代,
目前(2022年5月)使用的TLS版本只剩下1.2和1.3。
PS:图里为什么没有看到SSL 1.0呢?因为它存在很大的安全漏洞,所以根本没有被公开发布。
参考:
-
SSL/TLS 历史与前沿导览——Blog
-
SSL/TLS协议各版本间的差异——安信证书
关于TLS握手的过程,我们简单看下下面这张图(左边是单向认证过程,右边是双向认证过程):
可以看到:
-
TLS握手是在建立了TCP连接之后;
-
双向认证过程中,客户端也会发送自己的证书给服务端;
-
在ChangeCipherSpec后,信息就是加密传输的了;
整个TLS握手过程主要涉及传递证书、密钥交换等步骤,具体的原理,我这里推荐一些不错的资料~
可以带着2个问题去看下面的资料:1)ClientHello只是简单的说“Hello”吗?2)加密传输信息所用的密钥是怎么来的?(在后面的「实践部分 > WireShark」会公布答案,大大推荐通过网络包分析工具WireShark加深对TLS握手过程的理解。)
-
视频:SSL/TLS握手过程——bilibili
-
文章
-
SSL/TLS协议运行机制的概述——阮一峰
-
HTTPS - 揭秘 TLS 1.2 协议完整握手过程——51CTO
-
HTTPS RSA 握手解析——小林Coding
-
HTTPS ECDHE 握手解析——小林Coding
-
Tips:从小林Coding的文章可以发现,上图里的流程不是绝对的,因为不同的密钥交换算法(RSA、ECDHE...),对应的流程会有差异,比如基于RSA的密钥交换算法的流程中,没有ServerKeyExchange消息。
SSH
SSH(Secure Shell)也是一种网络安全协议,也是由IETF制定的。但它是基于TLS之上的应用层协议(TLS作用于运输层与应用层之间),通过加密和认证机制实现安全的访问和文件传输等业务。如果你经常用云主机或者Github,那你对它一定不陌生~
SSH连接的建立过程可以分为3步:
1)客户端验证服务器
你在首次SSH连接云主机的时候,应该见过下面这张图:
客户端收到了云主机的一些信息,关键是这里的“指纹”(即ECDSA签名算法中公钥的SHA-256值),我们可以通过ssh-keyscan -t ECDSA -p 22 [host] > key.pub
获取服务器的真实公钥,然后通过ssh-keygen -E sha256 -lf key.pub
计算其SHA256值,与图中的“指纹”比对。如果一致,再决定连接。
由此可见,这里的验证过程是由客户端控制的,客户端可以不做任何比对,直接信任连接,但这样存在风险。
2)生成信息加密传输的密钥(通过密钥交换算法),之后的通信均加密
3)服务器验证客户端(2种方式)
a. 客户端没有上传公钥:服务端会给客户端一个公钥,客户端使用该公钥加密用户信息(如密码),传给服务端,服务端校验通过后,连接建立成功。
b. 客户端提前上传了公钥到服务端:服务端会利用该公钥加密一个随机数发给客户端,客户端使用对应的私钥解密,再传给服务端,服务端校验通过后,连接建立成功。
参考:SSH免密登录原理与实现——掘金
iOS签名
从图可以看出,iOS签名其实是一个很复杂的过程,一段文字可能无法详细描述。
这里只需要知道iOS签名中2个必不可少的重要文件即可:
1).mobileprovision文件:又叫PP文件(图中为Provisioning Profile),可以把它理解为证书的升级版,里面不仅有1个以上的iOS开发者证书,还有各种其它信息。
2).p12文件:由开发者证书和对应私钥组成,与图中的关键步骤2和4相关。Xcode打包时需要搜索Keychain里属于PP文件中证书集合的证书,取出里面的私钥对App进行签名。
详细的讲解可以看我之前的文章:iOS | 图解iOS签名背后的原理,这也是本文的源头。
记住,如果你遇到iOS签名打包相关的问题,就先从上面的2个文件里入手吧~
一些实践
最后,介绍两个不错的实践工具,来巩固今天的内容。
OpenSSL
OpenSSL是一个开源的密码学工具包,我们可以尝试用下面的脚本,复习一下今天学习的算法。
# Generate private key (RSA)
openssl genrsa -out private.pem
# Generate public key from private key
openssl rsa -in private.pem -pubout -out pubkey.pem
echo "hello, world" > test.txt
# Encrypt
openssl rsautl -encrypt -pubin -inkey pubkey.pem -in test.txt -out test.enc
# Decrypt
openssl rsautl -decrypt -inkey private.pem -in test.enc -out test.dec
# Signature (hash:SHA-256)
## Generate
openssl dgst -sign private.pem -sha256 -out test.sig test.txt
## Verify
openssl dgst -verify pubkey.pem -sha256 -signature test.sig test.txt
# View Key as text
## Private key
openssl rsa -in private.pem -noout -text
## Public key
openssl rsa -pubin -in pubkey.pem -noout -text
# Generate a self-signed certificate
# {Creating a Self-Signed Certificate With OpenSSL——Baeldung}
...
参考:
-
openssl——Linux命令大全
WireShark
WireShark是一个开源的网络包分析工具,用它来深入理解各种网络协议准没错~
下面,我们先回顾一下「相关技术 > SSL/TLS」那一节提出的问题:
1)ClientHello只是简单的说“Hello”吗?
2)加密传输信息所用的密钥是怎么来的?
接下来,打开WireShark,对获取的网络包简单做一下过滤,如ip.addr == 115.236.119.85 && tls
。
可以看到,ClientHello里传递的信息还不少,关键信息包括TLS版本、随机数(密钥交换算法用)、支持的21种加密套件(可供服务端选择的密钥交换算法)等。这也就解答了上面的第1个问题。
继续分析后面的每一条信息,我们还会发现在ServerHello里,服务端选择了一种密钥交换算法,最终通过该算法生成了加密传输信息所用的密钥。这也就解答了上面的第2个问题。
更多的细节,等着你安装WireShark去探索~
——加餐结束——