一、网络攻击的类型
网络攻击分为两大类:被动攻击和主动攻击。
截获:从网络上窃听他人的通信内容,但不干扰原报文在源端和目的端的传送。
篡改:捕获报文并篡改报文后再发送给目的站。
恶意程序:计算机病毒。
拒绝服务 DoS:指攻击者向互联网上的某个服务器不停地发送大量分组,该服务器的网络资源耗尽而无法向其他正常客户端主机提供服务。若从互联网上的成百上千的网站集中攻击一个网站,则称为分布式拒绝服务 DDoS 。 有时也把这种攻击称为网络带宽攻击。
对付被动攻击:采用加密技术(让截获者读不懂报文内容)
对付主动攻击:采用加密技术 + 鉴别技术(指鉴别对方身份)
二、密钥密码体制
安全的计算机网络应达到以下目标
保密性:只有信息的发送方和接收方才能懂得所发送信息的内容。
端点鉴别(身份鉴别):鉴别信息的发送方和接收方的真实身份。
信息的完整性:确保信息的内容未被篡改过。
可以通过密钥加密来做到以上3点。下面是数据加密模型:
通信双方:A 和 B。
A 和 B 分别持有密钥 K(E) 和 K(D),这可以是一对对称密钥或者一对非对称密钥。
A 和 B 分别持有一对加密算法 E 和 D。
A将明文X通过密钥K(e) 和 算法E进行加密得到密文Y,可以把E看做是一个函数,密钥 K(e)和明文X作为这个函数的参数,返回值是Y。
传输给B后,用D(K(d), Y)解密得到X。
需要注意:
0、密钥 K本质是一串字符串。
1、D 和 E 都既可以是加密算法,也可以是解密算法,其本质都是将传入的字符串数据变为另一个字符串,所以我更倾向于说成是 D运算和E运算,而不是说 加密算法 和 解密算法。
2、D 和 E算法 是一对算法,即不论密钥K(e)和K(d)是对称密钥(即 K(e) = K(d))还是非对称密钥(即 K(e) ≠ K(d))都有: D运算是E运算的逆运算,E运算也是D运算的逆运算。
E(K(e), X) = Y
D(K(d), Y) = X
所以:
D(K(d), E(K(e), X)) = X
3、使用密钥和加密算法来加密或解密一串数据时,所花费的时间和数据本身的长度成正比。
4、加密算法 E 和解密算法 D 是公开的。而密钥 K(e) 和 K(d)如果是对称密钥,则这两个密钥是保密的,如果密钥 K(e) 和 K(d)如果是非对称密钥则公钥公开,私钥保密。
下面介绍两种密码体制:对称密钥密码体制 和 非对称密钥密码体制
1、对称密钥密码体制
该体制是 加密密钥与解密密钥都使用相同密钥 的密码体制。对称密钥又称为共享密钥。
加密过程如下:
E(K, X) = Y
D(K, Y) = X
所以:
D(K, E(K, X)) = X
2、公钥密码体制 (非对称密钥密码体制)
通信双方持有一对密钥分别是对外公开的公钥PK 和 只有自己知道的私钥SK。例如通信双方 A 和 B,A有一对密钥 PK(a) 和 SK(a),B也有一对密钥 PK(b) 和 SK(b)。
当A作为发送方向B发送数据时,A要用B的公钥 PK(b) 对明文X加密得到Y,B用私钥 SK(b) 对Y解密得到X。当B作为发送方向A发送数据时,则和上述过程一样要用A的一对密钥加解密。
目前最流行的公钥密码体制是RSA体制。
公钥算法的特点:
(1) 密钥对产生器产生出接收者 B 的一对密钥:
加密密钥 PKB 和 解密密钥 SKB 。
加密密钥 PKB 就是接收者 B 的公钥,向公众公开。
解密密钥 SKB 就是接收者 B 的私钥,对其他任何人都保密。
(2) 发送者 A 用 B 的公钥 PKB 对明文 X 加密(E 运算),然后发送给 B。 接收者 B 用自己的私钥 SKB 解密(D 运算),即可恢复出明文:
D(SK(b), E(PK(b), X)) = X
(3) 从已知的 PKB 实际上不可能推导出 SKB。
(4) 加密密钥是公开的,但不能用来解密:D(PK(b), E(PK(b), X)) ≠ X
对称密钥和公开密钥的区别:
使用对称密钥: 在通信信道上可以进行一对一的双向保密通信。即拥有公钥的只有一个客户端和一个服务端。
使用公开密钥: 在通信信道上可以是多对一的单向保密通信。 即拥有公钥的客户端可以有多个,这些客户端都可以和有私钥的服务端通信,单向是指 一对密钥只能用在一个方向的通信(A->B用B的一对密钥),另一个方向的通信要用另一对密钥才行。
公钥加密算法的开销(运算量)较大(是对称密钥算法的3倍)。因此现实中都是使用对称密钥进行加密。
使用密钥进行加密满足了保密性的要求,但还没有满足实体鉴别和完整性鉴别的要求。不过密钥不仅可以用来加密,还可以用来签名,密钥用来签名可以做到实体鉴别。
三、报文鉴别
报文鉴别需要做到两点:验证通信的对方是否是自己要通信的对象而不是篡改者 和 验证报文内容是否被篡改。
报文鉴别通过数字签名实现。
1、数字签名原理
例如 A 发送报文X给 B,B要鉴别发送者是A:
1、首先,A 用其私钥 SKA 对报文 X 进行 D 运算得到的密文,这个过程就是签名。
2、B 为了核实签名,用 A 的公钥 PKA 对密文Y进行 E 运算,还原出明文 X
为什么这样可以做到实体鉴别?
因为SKA只有A才有,B如果能用PKA解密成功(得到的明文是可读的),就说明对方是A。如果B解密出来的明文是不可读的,这段不可读报文也不会对B产生危害。
签名的本质是什么?
签名的本质是在报文中加一些只有发送方才有的特殊信息,接收方看到报文中的这个特殊信息就知道一定是A发过来的,例如上面对报文用A的私钥进行D运算,A的私钥就是A独有的东西。
所以具体来说,签名就是用自己的私钥给 待签名的对象 进行签名运算。
核实签名的本质是对签名运算的逆运算(即图中的E运算)。
这样做达到了实体鉴别的目的,但没有做到保密性,因为任何一个接收方收到报文都可以用A的公钥(公钥是公开的)解密得到明文。假如有中间者截获,依旧可以直到报文的内容。
为了同时做到实体鉴别和保密,应该使用A的私钥进行数字签名,用B的公钥进行内容加密,这么一来只有B才能用B的私钥解密。这里A的私钥和B的公钥的作用是不同的。
这里我们无需深究使用的是D运算还是E运算,只要知道签名和核实签名使用的是互逆的运算,加密和解密用的也是互逆的运算即可。
综上总结:签名用发送者的私钥,加密用接收者的公钥。
这种方式的很少用,因为需要对报文进行两次 D 运算和两次 E 运算,运算量太大,花费非常多的 CPU 时间。
现实应用中,普遍使用开销小得多的对称密钥实现报文加密,使用非对称密钥实现数字签名,而且一定要设法减小公钥密码算法的开销。
2、报文鉴别码
现在我们遇到的问题是:签名需要用发送者的私钥对整个明文进行签名运算(为了避免签名和加密混淆,所以这里说成是签名运算而不是加密运算),因而会消耗很多时间。
为了减小签名的开销,可以使用散列函数H()代替签名算法(签名函数)对明文X进行散列处理(如MD5、SHA-1、SHA-2x)。
散列函数的特点如下(和D、E这样的签名/加密运算对比):
返回值的长度较短和固定 (签名运算返回值的长度和输入值的长度成正比,输入值越长,返回值越长)。
不同的输入产生相同的输出的可能性极低 (签名运算不会有重复,因为其返回值是什么样的和它输入值是什么样的直接相关)。
单向运算,不能逆向变换,因此严格来说,散列函数不能算一个加密函数 (签名运算可逆运算,可以根据密文还原成原文)。
仅改动输入的一个比特,输出也会相差极大。
为什么散列函数可能出现重复值?
原因很简单,散列函数的输入值可以是无限多的任意取值,而返回值是固定位数,例如MD5的返回值是 128位,产生的值的范围在 0~2^128-1,以无限多的输入值得到有限个数的返回值,那么肯定会发生2个不同的输入值对应同一个返回值的重复现象。
下面我们可以简单看看MD5加密的原理:
1、附加:把任意长的报文按模 2^64 计算其余数(余数的长度64位),追加在报文的后面。
2、 填充:在报文和余数之间填充 1~512 位,使得填充后的总长度是 512 的整数倍。填充的首位是 1,后面都是 0。
3、分组:把追加和填充后的报文分割为多个 512 位的数据块,每个 512 位的报文数据再分成 4 个 128 位的数据块。
4、计算:将 4 个 128 位的数据块依次送到不同的散列函数进行 4 轮计算。每一轮都按 32 位的小数据块进行复杂的位运算,而且一轮运算的结果会作为下一轮运算的参数。一直到最后计算出 MD5 结果(128 位)。
散列函数的开销相比于签名函数的开销可以忽略不计。
回到之前的问题,如何借助散列函数进行报文鉴别?
1、A对X使用散列函数处理得到一个散列值 H(X)。
2、A对 H(x)用A的私钥经过D签名运算得到报文鉴别码MAC,这是一个经过签名的鉴别码。
3、将 报文X + MAC 拼接起来,经过B的公钥对整个扩展报文加密(图中没有画出来)并发送。
4、B用B的私钥对扩展报文解密,将MAC和X分开,用A的公钥对MAC逆运算得到 H(X0)。
5、B用 H()散列运算对报文X进行计算得到 H(X1) ,如果H(X1) == H(X2),就既能证明报文没有被篡改,又能证明对方是A。
需要注意:第二步没有对报文进行加密(D运算),而是对很短的散列 H(X) 进行 D 运算,因为 H(X)很短,所以D(H(X))的开销和耗时很小,这样就解决了之前开销大的问题。
上图是非对称密钥的签名过程,下图是对称密钥的签名过程:
对称密钥的签名方式就不是使用 D 运算,而是直接 把对称密钥K 拼在报文 X 之后,直接进行散列运算。图中也是省略了加密这一步,其实也应该要加密。
TLS会话阶段就是用的对称密钥对报文签名的。
四、实体鉴别
实体鉴别与报文鉴别不同。
报文鉴别:对每一个收到的报文都要鉴别报文的发送者和完整性。
实体鉴别:在通信开始前,对和自己通信的对方实体只需验证一次。
最简单的实体鉴别就是使用共享的对称密钥 K(AB),因为这个密钥只有A和B才有,因此B如果能用K(AB)这个密钥解密成功,就知道对方肯定只能是A。
该方法存在明显漏洞:不能抵抗重放攻击。
重放攻击 :原理是把以前窃听到的数据原封不动地重新发送给接收方。入侵者 C 捕获到报文后不需要破译报文,而是在之后攻击者想攻击的时候直接把由 A 加密的报文发送给 B,使 B 误认为 C 就是 A。B 就会向伪装成 A 的 C 发送许多本来应当发给 A 的报文。
回到上图,C不用拥有K(AB)这个密钥,C只需截获这个报文,之后想攻击的时候,就发送这个报文给B就让B以为C拥有K(AB)。从而让B以为C是A。
为了防御重放攻击,可以使用不重数(即不重复使用的大随机数)。
如下图所示:
1、A发送明文随机数Ra,并且Ra保存在A的内存中。
2、B用私钥SKb对Ra进行签名(是签名不是加密,这样A就知道对方是B)并加上自己的随机数Rb(Rb也会存在B的内存)。A会验证B发过来的签名了的随机数是不是A上次所发的Ra。
3、A发送用SKa签名的Rb,B就知道对方是A。B再验证Rb是否就是上次B发出去的Rb,如果验证成功就在内存中删除存储的Rb。
4、A和B开始通信。
如果C要使用重放攻击,C就要捕获第三次报文,这是因为C没有A的私钥,B就知道C不是A,而第三次报文是用 A 的私钥签名过的,因此C必须捕获第三次报文。下次重放这个报文B用A的公钥核实签名成功,就以为C是A。但即使如此,B核实完签名又发现里面的随机数Rb是自己不认识的数(因为Rb已经过期和失效),因此知道有内鬼,终止交易。
此外,还有一种更难防御的“中间人攻击”。即使使用不重数也无法防御:
1、C 冒充是 A,发送报文给 B,说:“我是 A”。
2、 B 选择一个不重数 RB,发送给 A,但被 C 截获了。 C 用自己的私钥 SKC 冒充是 A 的私钥,对 RB 签名,并发送给 B。此时B还无法核实签名,因为B没有C的公钥。
3、 B 向 A 发送报文,要求对方把解密(不应该是解密,应该是核实签名)用的公钥发送过来,但这报文也被 C 截获了。 C 把自己的公钥 PKC 冒充是 A 的公钥发送给 B。 B 用收到的公钥 PKC 对收到的加密的 RB 进行解密,其结果当然正确。
4、于是 B 相信通信的对方是 A,接着就向 A 发送许多敏感数据,但都被 C 截获了。
五、公钥的分配
我们知道 发送者A 发送消息 给接收者B的时候,要用B的公钥对报文加密(在TLS传输中,对数据传输阶段的数据加密不使用不对称密钥,而是使用对称密钥,因此通信前需要传输对称密钥。为了安全传输对称密钥,需要用B的公钥对要传输的对称密钥进行加密),那么A怎么得到B的公钥呢?
有一个权威第三方机构:认证中心 CA。它负责为拥有公钥的实体(人或者机器)提供数字证书,数字证书 = 实体的公钥 + 实体的信息(如主机名,实体的IP地址,实体人姓名等),数字证书(又称公钥证书)实际上是对公钥和对应实体的绑定。
这是一个数字证书的样子:
数字整数是公开的(因为里面放的是公钥,公钥本来就是公开的),无需加密,但是数字整数需要签名,CA用自己的私钥K(ca)对数字证书签名,目的是让大家知道这个证书是CA出品的,是正规的证书。
数字证书的制作过程如下:
1、CA对B的未签名证书散列运算得到 H(X)
2、CA用自己的私钥K(ca)对H(X)进行签名(D运算)。
3、把签名追加到明文证书的后面,得到签名后的证书。
核实:A 拿到 B 的数字证书后,使用数字证书上给出的 CA 的公钥,对数字证书中 CA 的数字签名进行 E 运算,得出一个数值。再对 B 的数字证书 (CA 数字签名除外的部分) 进行散列运算,又得出一个H(X)。比较这两个H(X)。若一致,则数字证书是真的。
六、TLS 运输层安全协议(敲黑板,重点)
TLS协议是SSL协议(安全套接字层协议)的改进,现在我们所说的SSL是 SSL/TLS的统称,实际上用的是TLS协议,真正的SSL协议在多年前已经被废弃。
TLS 安全运输层位于应用层和运输层之间,作用是为应用层提供保密性、数据完整性和鉴别功能安全传输服务(安全会话)。TLS层具体要做的是:在发送方,TLS 接收应用层的数据,对数据进行加密,然后把加密后的数据送往 TCP 套接字。
不要搞混可靠传输服务和安全服务,前者是指数据传输的有序、不丢失和无差错,后者指保密性、数据完整性和鉴别通信双方。
应用层使用 TLS 最多的就是 HTTP(即HTTPS)。TLS 可用于任何应用层协议。TCP 的 HTTPS 端口号是 443,而不是平时使用的端口号 80。
TLS 具有双向鉴别的功能,但实际应用中只会用到单向鉴别:客户端(浏览器)需要鉴别服务器(即安全服务的第三点),具体来说客户端要对方证明他就是 http://www.baidu.com这个站点的服务。这就需要服务端提供CA证书,CA 证书是运输层安全协议 TLS 的基石。
TLS如何建立安全会话?
建立安全会话两个阶段:
握手阶段:使用握手协议,这个阶段需要做三件事:协商加密算法、鉴别接收方的CA证书和生成用于加密的对称密钥。
会话阶段:使用记录协议。
1、握手阶段
1、协商加密算法
浏览器 A 向服务器 B 发送浏览器的 TLS 版本号和一些可选的加密算法(是在TCP第三次握手的ACK报文段中顺带传输这些信息的),以及A的不重数Ra。
B 从中选定自己所支持的加密算法(如 RSA)和生成主密钥的算法,并告知 A,同时把自己的 CA 数字证书、B的不重数Rb 和 用B私钥加密(应该说是签名)的SKB(Ra) 发送给 A。
2、服务器鉴别。客户 A 用数字证书中 CA 的公钥对数字证书进行验证鉴别(校验过程请参考上文)。鉴别成功后,A就从证书中得到了B的公钥PKB。
3、客户 A生成了预主密钥PMS,并且根据预主密钥 PMS 、Ra 和 Rb生成主密钥MS。A再用 B 的公钥 PKB 对PMS 加密,得出加密的预主密钥 PKB(PMS),发送给服务器 B。
4、服务器 B 用自己的私钥SKB把预主密钥PMS解密出来 。这样,客户 A 和服务器 B 都有了PMS,将预主密钥 PMS 、Ra 和 Rb通过双方已商定的密钥生成算法,生成为后面数据传输用的对称主密钥 MS。
5、这一步时图中没有画出来的,服务端B最后发送一个加密的"Finished"消息,表示握手阶段结束。A和B使用对称密钥MS进行加密传输,而不是用非对称密钥加密,这是因为用对称密钥加密的开销和时间远小于非对称加密。
6、为了使双方的通信更加安全,客户 A 和服务器 B 最好使用不同的密钥。主密钥被分割成 4 个不同的密钥。
每一方都拥有这样 4 个密钥(注意:这些都是对称密钥):
客户 A 发送数据时使用的会话密钥 KA (用于A对数据加密)
客户 A 发送数据时使用的 MAC 密钥MA(用于A对数据签名)
服务器 B 发送数据时使用的会话密钥 KB (用于B对数据加密)
服务器 B 发送数据时使用的 MAC 密钥 MB (用于B对数据签名)
也就是说数据收发阶段,每个报文都要加密和签名这两步。
最后总结:使用了TLS安全传输的会比传统的TCP三次握手多出三次握手(对于客户端多出2个RTT时延, 对于服务端多出1个RTT)才能开始数据发送阶段。如下图绿色部分:
TLS 的浏览器端和服务端都会保存之前的TLS会话参数(包括协商好的加密算法和主密钥等等),以及这些参数的会话ID(会话ID - 会话参数的映射)。下次浏览器再访问同一个服务器时,直接发送会话ID就能够通知服务端使用上一次的密钥和加密算法进行通信,节省了一个RTT时间和生成主密钥的时间:
2、会话阶段
即数据报文传输阶段。以A发送数据给B这一个传输方向为例:
1、把长的数据划分为较小的数据块(TCP把一个应用层消息分隔为多个报文段),叫做记录。
对每一个记录进行鉴别运算(用密钥MA)和加密运算(用密钥KA)。
2、记录协议对每一个记录按发送顺序赋予序号,第一个记录作为 0。发送下一个记录时序号就加 1,序号最大值不得超过 264 – 1,且不允许序号绕回。
序号未写在记录之中,而是在进行散列运算时,把序号包含进去。客户 A 向服务器 B 发送一个记录前,对 密钥 MA 、记录的当前序号和明文记录进行散列运算得到数字签名MAC,MAC在拼到明文记录后面,附有签名的数据记录就生成好了。
使用会话密钥 KA 对附有签名的数据记录进行加解密。
上面过程,在握手阶段使用了实体鉴别,在会话阶段使用了报文鉴别。
关闭 TLS 连接:
关闭 TLS 连接之前,A 或 B 应当先发送关闭 TLS 的记录,以防止截断攻击 。
截断攻击:在 A 和 B 正在进行会话时,入侵者突然发送 TCP 的 FIN 报文段来关闭 TCP 连接。
如果 A 或 B 没有发送一个要关闭 TLS 的记录的情况下收到了 TCP 的 FIN 报文段时,就知道这是入侵者的截断攻击了。因为入侵者无法伪造关闭 TLS 的记录。