非对称密钥加密
一、数字加密算法:
对称加密(Symmetric-key algorithm)
使用相同的密匙对同一密码进行加密和解密。
* 密文 = E(明文+密钥+算法)
明文 = D(密文+密钥+算法)
* 流密码算法(stream ciphers)、块密码算法(block ciphers)
非对称加密(asymmetric cryptography)
使用不同的密钥对同一密码进行加密和解密。
* 公钥和私钥中的任一个均可用作加密,但此时只能用另一个解密。
* 公钥无法推导出私钥。
* 实现算法:RSA算法、椭圆曲线算法ECC
二、HTTPS的加密原理中的非对称加密:
-
对称加密缺点:如果通信双方都各自持有同一个密钥,且没有别人知道,这两方的通信安全当然是可以被保证的。但是最大的问题就是这个密钥怎么让传输的双方知晓,同时不被别人知道。
-
非对称加密缺点:耗时长。
-
非对称加密+对称加密:既然非对称加密耗时,所以尽量减少非对称加密的次数。
请看一下这个过程,非对称加密、解密各只需用一次即可:
- 某网站拥有用于非对称加密的公钥A、私钥A’。
- 浏览器向网站服务器请求,服务器把公钥A明文给传输浏览器。
- 浏览器随机生成一个用于对称加密的密钥X,用公钥A加密后传给服务器。
- 服务器拿到后用私钥A’解密得到密钥X。
- 这样双方就都拥有密钥X了,且别人无法知道它。之后双方所有数据都通过密钥X加密解密即可。
中间人(man-in-the-middle)攻击
- 某网站有用于非对称加密的公钥A、私钥A’。
- 浏览器向网站服务器请求,服务器把公钥A明文给传输浏览器。
- 中间人劫持到公钥A,保存下来,把数据包中的公钥A替换成自己伪造的公钥B(它4当然也拥有公钥B对应的私钥B’)
- 浏览器生成一个用于对称加密的密钥X,用公钥B(浏览器无法得知公钥被替换了)加密后传给服务器。
- 中间人劫持后用私钥B’解密得到密钥X,再用公钥A加密后传给服务器。
- 服务器拿到后用私钥A’解密得到密钥X。
解决方法:证明浏览器收到的公钥一定是该网站的公钥。
数字证书
- 网站在使用HTTPS前,需要向CA机构申领一份数字证书。数字证书里含有证书持有者信息、公钥信息等。
- 服务器把证书传输给浏览器,浏览器从证书里获取公钥就行了。证书就如身份证,证明“该公钥对应该网站”。
Q:“证书本身的传输过程中,如何防止被篡改”?
把证书原本的内容生成一份“签名”,比对证书内容和签名是否一致就能判别是否被篡改。
这就是数字证书的“防伪技术”,这里的“签名”就叫“数字签名”。
- 信息摘要算法/签名算法:MD5、HMAC、SHA
数字签名的制作过程:
- CA机构拥有非对称加密的私钥和公钥。
- CA机构对证书明文数据T进行hash。
- 对hash后的值用私钥加密,得到数字签名S 。 S = key(hash(T))
浏览器验证过程:
- 拿到证书,得到明文T,签名S。
- 用CA机构的公钥对S解密(由于是浏览器信任的机构,所以浏览器保有它的公钥。详情见下文),得到S’。S’=unkey(key(hash(T)))
- 用证书里指明的hash算法对明文T进行hash得到T’。 T’=hash(T)
- 显然通过以上步骤,T’应当等于S‘,除非明文或签名被篡改。所以此时比较S’是否等于T’,等于则表明证书可信。T’ == S’ ? 可信:不可信
Q: 中间人有可能篡改该证书吗?
假设中间人篡改了证书的原文,由于他没有CA机构的私钥,所以无法得到此时加密后签名,无法相应地篡改签名。
浏览器收到该证书后会发现原文和签名解密后的值不一致,则说明证书已被篡改,证书不可信,从而终止向服务器传输信息,防止信息泄露给中间人。
Q:中间人有可能把证书掉包吗?
不会发生,因为证书里包含了网站A的信息,包括域名,浏览器把证书里的域名与自己请求的域名比对一下就知道有没有被掉包了。
Q:为什么制作数字签名时需要hash一次?
性能问题:非对称加密效率较差,证书信息一般较长,比较耗时。而hash后得到的是固定长度的信息(比如md5算法得到固定的128位值,变长输入,定长输出),这样加解密就快很多。
安全问题:
Q:怎么证明CA机构的公钥是可信的?
操作系统、浏览器本身会预装一些它们信任的根证书,如果其中会有CA机构的根证书,这样就可以拿到它对应的可信公钥了。
Q:每次进行HTTPS请求时都必须在SSL/TLS层进行握手传输密钥吗?
服务器会为每个浏览器(或客户端软件)维护一个session ID,在TSL握手阶段传给浏览器。
浏览器生成好密钥传给服务器后,服务器会把该密钥存到相应的session ID下。
之后浏览器每次请求都会携带session ID,服务器会根据session ID找到相应的密钥并进行解密加密操作,这样就不必要每次重新制作、传输密钥了!
三、信息摘要算法/签名算法
摘要/散列值/指纹 = hash(消息)
hash缺点:hash算法只可以验证数据的完整性,但是无法保证数据防篡改(中间人攻击)。
密码学hash算法的特性:
- 无论消息是有多长,摘要值的长度是固定的
- 高效:hash算法都可以快速计算出对应的摘要值
- 单向性、不可逆:无法通过摘要值推导计算出原始消息内容(暴力攻击、彩虹表、字典攻击)
- 唯一性:不同的消息(哪怕只是细微的不一致)不可能产生一致的摘要值
常见的散列函数:MD5、HMAC、SHA
MAC(消息验证码)算法
MAC值 = mac(消息+密钥)
MAC特点:
- 跟hash算法一样,可以验证数据的完整性。
- 可以验证数据确实是由原始发送方发出的。
分类:
- CBC-MAC算法:
- HMAC(Hash-based Message Authentication Code)算法:HTTP中应用最多
Encrypt-and-MAC (E&M)
MAC-then-Encrypt (MtE)
Encrypt-then-MAC (EtM)
RSA
RSA使用场景:
-
单步加密:
- 客户端可以使用公钥加密一些敏感数据发生到密钥生成方,接受方收到后,通过私钥解密,获取消息内容,而无需回应。
- 服务器端无法发送密文,如果服务器端用私钥加密数据,然后发送给客户端,由于公钥是公开的,任何人都能解密,所以这个过程是不成立的。
-
双向加密:两个RSA密钥对,利用相互的单步加密,实现双向加密。
数据结构的散列函数
特点:
* 确定性:散列值不相同,输入一定不相同
* 散列冲突(collision):如果两个散列值相同,两个输入值,可能相同或不同
* 不可逆性:一个哈希值对应无数个明文,理论上你并不知道哪个是。
* 混淆特性:部分改变输入值,一个具有强混淆特性的散列函数会产生一个完全不同的散列值。
冲突:
不管采用哪种探测方法,只要当散列表中空闲位置不多的时候,散列冲突的概率就会大大提高。
一般情况下,需要尽可能保证散列表中有一定比例的空闲槽位。
加载因子(load factor): 来表示空位的多少。载因子越大,则填满的元素越多。
如何解决散列冲突问题呢?
-
开放寻址法(open addressing)
定义:将散列函数扩展定义成探查序列,即每个关键字有一个探查序列h(k,0)、h(k,1)、…、h(k,m-1),这个探查序列一定是0….m-1的一个排列(一定要包含散列表全部的下标,不然可能会发生虽然散列表没满,但是元素不能插入的情况),如果给定一个关键字k,首先会看h(k,0)是否为空,如果为空,则插入;如果不为空,则看h(k,1)是否为空,以此类推。
-
线性探测方法(Linear Probing)
弊端:当散列表中插入的数据越来越多时,散列冲突发生的可能性就会越来越大,空闲位置会越来越少,线性探测的时间就会越来越久,最坏情况下的时间复杂度为 O(n)。 -
二次探测(Quadratic probing)
二次探测进行探测的步长变成了原来的“二次方” -
双重散列(Double hashing)
使用一组散列函数。依次使用散列函数,直到找到空闲的存储位置。
-
-
链表法、拉链法(chaining)
散列表中,每个位置对应一条链表,所有散列值相同的元素都放到相同位置对应的链表中。
[1] 彻底搞懂HTTPS的加密原理
[2] 非对称加密概述
[3] 基础密码学入门
[4] 散列