(加餐)信息安全 | 互联网时代,如何建立信任?

接正篇:信息安全 | 互联网时代,如何建立信任?

——加餐开始——

相关技术

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呢?因为它存在很大的安全漏洞,所以根本没有被公开发布。

参考:


关于TLS握手的过程,我们简单看下下面这张图(左边是单向认证过程,右边是双向认证过程):

可以看到:

  1. TLS握手是在建立了TCP连接之后;

  2. 双向认证过程中,客户端也会发送自己的证书给服务端;

  3. 在ChangeCipherSpec后,信息就是加密传输的了;

整个TLS握手过程主要涉及传递证书、密钥交换等步骤,具体的原理,我这里推荐一些不错的资料~

可以带着2个问题去看下面的资料:1)ClientHello只是简单的说“Hello”吗?2)加密传输信息所用的密钥是怎么来的?(在后面的「实践部分 > WireShark」会公布答案,大大推荐通过网络包分析工具WireShark加深对TLS握手过程的理解。)

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. 客户端没有上传公钥:服务端会给客户端一个公钥,客户端使用该公钥加密用户信息(如密码),传给服务端,服务端校验通过后,连接建立成功。

a. 客户端没有上传公钥的情况

b. 客户端提前上传了公钥到服务端:服务端会利用该公钥加密一个随机数发给客户端,客户端使用对应的私钥解密,再传给服务端,服务端校验通过后,连接建立成功。

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}
...

参考:

WireShark

WireShark是一个开源的网络包分析工具,用它来深入理解各种网络协议准没错~


下面,我们先回顾一下「相关技术 > SSL/TLS」那一节提出的问题:

1)ClientHello只是简单的说“Hello”吗?

2)加密传输信息所用的密钥是怎么来的?


接下来,打开WireShark,对获取的网络包简单做一下过滤,如ip.addr == 115.236.119.85 && tls

可以看到,ClientHello里传递的信息还不少,关键信息包括TLS版本、随机数(密钥交换算法用)、支持的21种加密套件(可供服务端选择的密钥交换算法)等。这也就解答了上面的第1个问题。

继续分析后面的每一条信息,我们还会发现在ServerHello里,服务端选择了一种密钥交换算法,最终通过该算法生成了加密传输信息所用的密钥。这也就解答了上面的第2个问题。

更多的细节,等着你安装WireShark去探索~


——加餐结束——