对称加密和非对称加密
对称加密
-
概念:加密秘钥和解密秘钥使用相同的秘钥(即加密和解密都必须使用同一个秘钥)
-
特点:一对一的双向保密通信(每一方既可用该秘钥加密,也可用该秘钥解密,非对称加密是多对一的单向保密通信)
-
常用算法:
- DES:秘钥长度为64位
- 3DES:即三重DES,DES的加强版,是DES向AES过渡的加密算法
- AES:目前基本已经取代DES,是使用最广泛的加密算法
-
优点:速度快,对称性加密通常在消息发送方需要加密大量数据时使用,算法公开、计算量小、加密速度快、加密效率高。
-
缺点:秘钥传输容易泄露,管理秘钥很麻烦。
-
应用场景举例:
假设用户A和服务器之间通讯,为了防止敏感数据被黑客截获,所以双方采用对称加密后的数据进行通讯,即使黑客截获通讯数据,由于黑客没有秘钥,所以无法解密该数据。但是这时有个问题需要考虑,就是用户A和服务器必须事先协商好秘钥,否则他们也不知道对方用的什么秘钥加密数据的,所以,用户A和服务器需要事先通过网络约定一个秘钥才能进行加密传输,但是在约定秘钥的时候,这个秘钥是明文传输的,所以黑客同样能截获这个秘钥,从而达不到保密的效果。另一个问题是,假设同时又有用户B和服务器通讯,那么用户B和服务器之间同样需要维护一个独立的秘钥,当服务器的用户量大的时候,服务器管理秘钥是比较麻烦的。所以单纯使用对称加密是达不到理想的加密效果的。
-
python3实现aes算法的简单示例,参考自这篇博文
# coding: utf8
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
class Prpcrypt:
def __init__(self):
self.mode = AES.MODE_CBC # 采用CBC模式加密
def encrypt(self, text, key): # 加密函数,被加密内容text长度必须为16的倍数,否则需补足
cryptor = AES.new(key, self.mode, key)
length = 16
count = len(text)
if count % length != 0:
add = length - (count % length)
else:
add = 0
text = text + (' ' * add) # 若text长度不为16倍数,则在后面用" "补足
ciphertext = cryptor.encrypt(text)
# 因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
# 所以这里统一把加密后的字符串转化为16进制字符串
return b2a_hex(ciphertext)
def decrypt(self, text, key): # 解密函数,用strip()把补足的空格去掉以还原原内容
cryptor = AES.new(key, self.mode, key)
plain_text = cryptor.decrypt(a2b_hex(text))
return plain_text.rstrip(b' ')
if __name__ == '__main__':
pc = Prpcrypt()
key1 = "keyskeyskeyskeys" # 秘钥必须是16位或24位或32位
key2 = "aaaaaaaabbbbbbbb"
encrypted = pc.encrypt("hello lucy, i am lily", key1) # 用key1加密
decrypted = pc.decrypt(encrypted, key1) # 必须用key1解密,才能得到原文本内容
print("加密后的内容:", encrypted)
print("解密后的内容:", decrypted)
print("*"*30)
encrypted = pc.encrypt("hello lucy, i am lily", key1) # 用key1加密
decrypted = pc.decrypt(encrypted, key2) # 用key2解密,则解密后不是原文本内容
print("加密后的内容:", encrypted)
print("解密后的内容:", decrypted)
输出结果:
非对称加密
-
概念:加密秘钥和解密秘钥是不同的秘钥。使用非对称加密需要通过算法生成一个秘钥对,即一个公钥(public key)和一个私钥(private key),用公钥加密的文件只能用对应的私钥解密,用私钥加密的文件只能用对应的公钥解密,并且人们无法通过公钥推算出私钥,或通过私钥推算出公钥。私钥需要由一方妥善保存,不能泄露,公钥可以随意传播
-
特点:多对一的单向保密通信(可多人持有公钥进行加密,只能一人持有私钥解密,反过来如果用唯一的私钥加密,公钥解密的话就失去加密的意义了)
-
常用算法:RSA(使用最广泛)、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等
-
优点:安全
-
缺点:计算量大,加解密速度慢,效率低
-
应用场景举例:
假设用户A和服务器使用非对称加密方式传输数据。首先服务器端生成公钥和私钥,公钥是公开的,所有人都可以拿到,私钥只要服务器知道,不能泄露。此时用户A用公钥加密一段数据传给服务器,中途被黑客截取,由于黑客没有相应的私钥,所以无法解密数据(公钥加密的数据只能被相应的私钥解密)。这种单向保密通讯比较常见,比如用户需要向服务器发送加密后的银行卡的账号和密码数据。
上面理解了对称加密和非对称加密大概是怎么一回事,下面将阐述这两种加密方式的具体应用
数字签名
数字签名可以作为非对称加密的一个应用实例。
什么是数字签名?
就像写出差的报销单,你需要报销500元,这报销单需要找领导签了字盖了章,财务才能确认其真实性,从而给你发放报销款。同样的道理,在计算机网络中传送的电子报文也需要“签字盖章”以保证其真实性,给电子报文的“签字盖章”就是数字签名。
数字签名要实现什么样的功能?
- 接收者能够确信该报文的确是发送者发送的。类比到上面例子中,即财务部需要确认是你的领导签的字(比如可以通过字迹确认,或者个人印章确认,可以把领导理解为发送者)
- 接收者确信所收到的数据和发送者发送的完全一样而没有被篡改。如财务部收到报销单后如何确认就是500元,而不是在领导签字之后被人在后面添加了个0(即本来只报销50元,等领导签完字后在50后面加个0变成500)?这其实可以通过把报销金额改为“ ¥50元”来解决这个问题。
- 发送者事后不能抵赖对报文的签名。假设领导喝多了,这时有人趁机写个50w元的报销单,让他签了字盖了章,财务部查出财务异常时,领导没法抵赖,白纸黑字清清楚楚。
数字签名的实现原理
上面通过报销单的例子理解了数字签名需要具备的三个功能是个什么意思,下面就具体描述真实的数字签名过程是怎么实现的。
假设A公司和B公司需要签订一个电子合同,A把合同拟好后得到一个1M大小的文件(明文a),为了让B确信这份合同确实是由A发送的(实现上述所说的功能1),中途没有被外人篡改(功能2)并且B确认合同内容后A不能抵赖(功能3),A可以按如下方式执行:
- A采用非对称加密方式生成一个密钥对,并用A的私钥对明文a进行加密,生成密文b,A把密文b以及A的公钥一起打包发送给B
- B打开A发来的文件包,拿到A的公钥,用公钥解开密文b即可得到正常的合同文件
注意,上面第1步中A用私钥加密合同得到密文b并不是出于保密内容的目的,而是为了证明合同确实是由A发出的,因为用A的私钥加密的文件,只能由A的公钥解密,如果B用A的公钥解开密文b后无法得到正常的明文a,则说明要么文件不是由A发出,要么文件中途被人篡改。由于A的私钥只有A有,所以只要B能用A的公钥正常解密合同,则说明文件确实来自A,A也无法抵赖,这也就说明了该方案是实现了上述所说的三个功能的。
但是,上面说过非对称加密的缺点之一就是效率低,1M的文件使用非对称加密对计算机会造成很大的负担,加密时间也会比较长,要是文件更大一点,这种不利影响会更大。所以通常使用以下的方案:
- A使用密码散列函数对合同文件明文a进行运算,得到一个固定长度的结果,称为摘要,取名S1,A用私钥对S1进行加密得到的结果称为数字签名,A把明文a、数字签名、A的公钥一起打包发送给B。
- B打开A发来的文件包,拿到A的公钥,用公钥去解开数字签名,如果能正常解开得到摘要S1,则说明该文件确实来自A。同时,B用和A同样的密码散列函数对文件包中的合同明文进行运算得到摘要S2,如果S1和S2是一样的,说明合同中途没有被篡改。这样同样能实现上述所说的三个功能。
- 整个流程图示如下:
由于密码散列函数的运算效率比非对称加密的效率高,所以避免了第一种方案的弊端。注意的是,上面两种方案都无法确保合同内容是保密传输的。
以上论述都是基于传输过程中A的公钥没有被伪造的前提的,假设在传输过程中C截获了文件包,并且把合同内容篡改后用自己的私钥生成假的数字签名,同时用自己的公钥冒充A的公钥,再传输给B,这样B也无法察觉,因为B无法确定接收到的文件包中A的公钥的真假性,为了解决这个问题,数字证书就应运而生了。
数字证书
数字证书是指由证书中心(certificate authority,简称CA)发行的一种电子文档,是一串能够表明网络用户身份信息的数字,提供了一种在计算机网络上验证网络用户身份的方式。为了便于理解证书中心和数字证书的作用,可以把证书中心类比为公安局,而数字证书类比为身份证,比如我们过安检需要出示身份证以证明我们的身份,工作人员为什么看到身份证就确定是我,而不是张三李四冒充的我呢?原因就是身份证是由公安局颁发的,工作人员虽然不信任我,但是他们信任公安局,身份证就是公安局颁发给我的身份凭证。同样,在上面合同的例子中,假如A的公钥经由CA认证了,那么B就可以很放心地使用A的公钥了,因为证书中心(CA)具有权威性。
下面具体论述:
A为了让B信任自己的身份,去找CA为自己的公钥做认证,证书中心用自己的私钥,为A的公钥以及A的一些相关信息(比如该认证的到期时间)一起加密,生成了A的数字证书,这时候A向B传输的文件包就变成了这样:
B收到A传来的文件包后,并不急着验证A的数字签名,而是先用CA的公钥解密A的数字证书(A的数字证书是由CA私钥加密的),然后拿到A的公钥,再用A的公钥去解密A的数字签名,这样,由于A的公钥被CA的私钥加密,即使中途被C截获,C也无法篡改A的公钥,因为C没有CA的私钥,这样传输过程中就保证了A的公钥的真实性。
https协议
说完了对称加密和非对称加密,以及作为非对称加密具体应用的数字签名和数字证书的实现,现在终于可以引出https主题了,就像了解数字签名和数字证书需要用到加密的知识,学习https则需要用到上面所有几个主题的知识。
什么是https协议?
HTTPS即超文本传输安全协议,是以安全为目标的HTTP通道,简单讲就是HTTP的安全版。
HTTPS协议 = HTTP协议 + SSL/TLS协议。SSL和TLS是在传输层对网络连接进行加密的协议(SSL和TLS具体是怎么一回事本文不讨论,只需要知道他们是负责数据传输安全的)。
简单理解就是http协议负责数据传输,SSL/TLS协议负责数据安全。
https实现过程
下面我们通过下图中的8个步骤来梳理一下https的数据传输过程:
-
浏览器向一个采用https协议的服务器发出请求,如https://www.baidu.com
-
服务器端保存了它的公钥A和私钥A,并且服务器的公钥A取得了CA颁发的数字证书(所以客户端可以信任公钥A),即图中所示的SSL数字证书
-
服务器响应浏览器的请求,并且携带自己的数字证书
-
客户端收到服务器的数字证书,用CA的公钥解开数字证书,拿到A的公钥,然后验证A的公钥是否有效(比如是否到期。这一步就是上文中数字签名的实现原理那一节的内容),如果无效,则浏览器发出一个警告,如果有效,则浏览器会生成一个随机码,作为对称加密的秘钥,接下来用A的公钥把这个随机码加密。
这里需要解释一下这个随机码的作用,还记得上文中说的对称加密和非对称加密的优缺点吗?如果双方采用非对称加密方式加密数据,则对两方的计算机来说计算开销是十分大的,速度也会变慢很多,而对称加密的优点就是加密速度快,但是秘钥在网络上的传输是不安全的,如果把这两种方式的优点结合一下,想必是极好的了。所以,这里使用服务器的公钥A对这个随机码(即对称加密的秘钥)加密然后再传给服务器,就避免了这个随机码中途被窃取的问题(因为只有服务器的私钥A能解开,中途被截获也没用)。双方有了对称加密的秘钥后就可以happy地通过对称加密的方式传输数据了。
-
把加密的随机码传递给服务器
-
服务器用私钥A解密得到随机码
-
通过对称加密方式传输数据
-
通过对称加密方式解密数据
综上,可以看到https通讯其实就是把对称加密和非对称加密的优点结合的结果,浏览器拿到服务器的公钥A,然后通过公钥A加密对称加密的秘钥,以保证该秘钥不被窃取,之后即通过对称加密的方式传递数据,至于SSL数字证书,那就是用来给服务器的公钥A做身份认证的洛,不然浏览器也无法确定它收到的公钥A有没有被冒充。
本文参考
- 视频教程地址1:https://www.bilibili.com/video/av53593472/?p=4
- 视频教程地址2:https://www.bilibili.com/video/av23124815/?p=136
- 谢希仁《计算机网络》第七版