AES简介以及配合Base64实现加密解密
一、对称加密
1、什么是对称加密
对称加密就是指加密和解密使用同一个密钥的加密方式。
2、对称加密的工作过程
发送方使用密钥将明文数据进行加密成密文,发送给接收方,接收方收到密文后,使用同一个密钥将密文解密成明文。
3、对称加密的优点
加密计算量小,速度快,适合对大量数据进行加密的场景。
4、对称加密的两大不足
- 密钥传输问题:由于对称加密的加密和解密用的是同一个密钥,所以对称加密的安全性就不仅仅取决于加密算法本身的强度,更取决于密钥是否被安全保管,因此加密者如何将密钥安全传递到解密者手里,就成了对称加密面临的关键问题。
- 密钥管理问题:随着密钥数量增多,密钥管理问题会逐渐显现出来。
二、AES加密算法
AES
加密算法是众多对成绩密算法中的一种,它的英文全称是Advanced Encryption Standard,翻译过来就是高级加密标准。
AES
加密算法采用分组密码体制,每个分组数据的长度为128位16个字节,密钥长度可以是128位16个字节,192位或256位,一共有五种加密模式,我们通常采用需要初始向量IV的CBC模式,初始向量也是128位16个字节。
1、AES的加密流程
(1)五个关键词
-
分组密码体制:将明文切成一段一段的来进行加密,然后把一段一段的密文拼接起来形成最终密文的加密方式。AES采用分组密码体制,即AES加密会首先把明文切成一段一段的,而且每段数据的长度要求必须是128位16个字节,如果最后一段不够16个字节,就需要用Padding来把这段数据填充满16个字节,然后分别对每段数据进行加密,最后再把每段加密数据拼接起来形成最终密文、
-
Padding
:Padding
就是用来把不满16个字节的分组数据填充为16个字节用的,它有三种模式:PKCS5
、PKCS7
、NOPADDING
。PKCS5
是指分组数据缺少几个字节,就在数据的末尾填充几个字节的几。比如缺少5个字节,就在末尾填充5个字节的5。PKCS7
是指分组数据缺少几个字节,就在数据的末尾填充几个字节的0,比如缺少7个字节,就在末尾填充7个字节的0。No Padding
是指不需要填充,也就是说数据的发送方肯定会保证最后一段数据也正好是16个字节。那如果在PKCS5
模式下,最后一段数据的内容刚好就是16个16怎么办?那解密端就不知道这一段数据到底是有效数据还是填充数据,PKCS5
模式会自动帮我们在最后一段数据后再添加16个字节的数据,而且填充的数据也是16个16,这样解密端就能知道谁是有效数据谁是填充数据了。PKCS7
最后一段数据的内容的内容是16个0,也是同样的道理。解密端需要使用和加密端同样的Padding模式,才能准确的十倍有效数据和填充数据。我们开发通常采用PKCS7
模式。 -
初始向量IV:初始向量IV的作用是使加密更加安全可靠,我们使用
AES
加密时需要主动提供初始向量,而且只需要提供一个初始向量就够了,后面每段数据的加密向量都是前面一段的密文。初始向量IV的长度规定为128位16个字节,初始向量的来源为随机生成。 -
密钥:
AES
要求密钥的长度可以是128位16个字节,192位或256位,位数越高,加密强度自然越大,但是加密的效率自然会低一些,因此要做好衡量,我们开发通常采用128位16个字节的密钥,我们使用AES
加密时需要主动提供密钥,而且只需要提供一个密钥就够了,每段数据加密使用的都是这一个密钥,密钥来源为随机生成。 -
五种加密模式:
AES
一共有五种加密模式,分别是ECB
(电码本模式),CBC
(密码分组链接模式),CTR
(计算器模式),CFB
(密码反馈模式),OFB
(输出反馈模式)-
ECB
最基本的加密模式,即仅仅使用明文和密钥来加密数据,相同的明文块会被加密成相同的密文块,这样明文和密文的结构将是完全一样的,就会更容易被破解,相对来说不是那么安全,因此很少使用。
-
CBC
CBC
模式比EBC
模式对了一个初始向量IV,加密的时候,第一个明文块首先会和IV做异或操作,然后在经过密钥加密,然后第一个密文块又会被作为第二个明文块的加密向量来异或,依次类推下去,相同的明文块经过加密后得到的密文块是不同的,明文接口和密文结构也不同,因此更加安全。
-
CTR
计算器模式不常见,在CTR模式中, 有一个自增的算子,这个算子用密钥加密之后的输出和明文异或的结果得到密文,相当于一次一密。这种加密方式简单快速,安全可靠,而且可以并行加密,但是在计算器不能维持很长的情况下,密钥只能使用一次。
-
CFB
和OFB
略
-
(2)AES加密流程(主要针对CBC模式)
> 1、首先`AES`加密会把明文按128位16个字节进行切分,如果数据的最后一段不够16个字节,会用Padding来填充。
>
> 2、把明文块0与初始向量IV做异或操作,再用密钥加密,得到密文块0,同时也会将密文块0用作明文块1的加密向量。
>
> 3、明文块1与密文块0进行异或操作,再用密钥加密,得到密文块1,以此类推。
>
> 4、最后把密文块拼接起来得到最终的密文。
(3)、AES的加密原理
我们探讨AES
的加密原理,起始就是探讨加密器里做了什么,加密器里做了四个重要的操作,分别是:密钥扩展,初始轮,重复轮,最终轮。
-
密钥扩展:根据初始密钥生成后面10轮密钥的操作。
AES
内部一共会执行11轮加密,AES
会通过一个简单快速的混合操作,根据初始密钥依次生成后面10轮的密钥,每一轮的密钥都是通过上一轮生成的,所以每一轮的密钥都是不同的。 -
初始轮:初始轮就是将128位的明文数据与128位的初始密钥进行异或操作
-
重复轮:所谓重复轮,就是指把字节混淆,行移位,列混乱,加轮密钥这四个操作重复好几轮。
重复轮重复的论述取决于密钥的长度,128位16位字节的密钥重复轮推荐重复执行9次,192位密钥重复轮推荐重复执行11次,256位密钥重复轮推荐执行13次。
-
最终轮:最终轮其实和重复轮的操作差不多,知识在最终轮我们丢弃了列混乱这个操作。
三、Python代码实现(配合Base64)
import base64
import json
from Crypto.Cipher import AES
class Aes_cbc(object):
def __init__(self, key):
self.key = key.encode("utf-8") # 密钥
self.vi = "0102030405060708".encode("utf-8") # 偏移量
self.mode = AES.MODE_CBC # 加密模式
def encryption(self, data): # 加密
pad = lambda s: s + (16 - len(s) % 16) * chr(16 - len(s) % 16) # 对字符串进行补位
data = pad(json.dumps(data)).encode("utf-8")
cipher = AES.new(self.key, self.mode, self.vi)
encryptedbytes = cipher.encrypt(data)
# 使用Base64进行编码,返回byte字符串
encodestrs = base64.b64encode(encryptedbytes)
# 对byte字符串按照utf-8进行解码,并返回
return encodestrs.decode("utf-8")
def decrypt(self, data): # 解密
encodebytes = base64.decodebytes(data.encode("utf-8")) # 将加密的数据转换为bytes数据类型
cipher = AES.new(self.key, self.mode, self.vi)
text_decrypted = cipher.decrypt(encodebytes)
unpad = lambda s: s[0:-s[-1]]
return unpad(text_decrypted).decode("utf-8")
if __name__ == '__main__':
a = Aes_cbc("0CoJUm6Qyw8W8jud")
r_code ={
"code": {
"code": "0000",
"msgId": "Success",
"msg": "成功",
},
"bo": {
"applyId": "REQX10000001423",
"openStatus": "1"
},
"other": {
"syncType": "2"
}
}
print(a.encryption(r_code))
print(json.loads(a.decrypt(a.encryption(r_code))))