随着互联网的发展,越来越多的数据需要在网络中进行传输。为了保证数据的安全性,在进行网络传输时,需要对数据进行加密操作,使得数据在传输过程中不被窃取或篡改。AES(Advanced Encryption Standard)就是一种经典的加密算法。
AES 算法源于比利时密码学家 Joan Daemen 和 Vincent Rijmen,它是一种对称加密算法
,通过使用相同的密钥对数据进行加密和解密操作
。AES 算法中,加密和解密操作是相反的过程,因此需要使用相同的密钥作为加密和解密的关键参数。
AES 算法使用分组密码体制,将明文按照固定大小进行分组,然后对每一分组进行加密。在加密过程中,AES 算法采用了多轮加密的方式,每一轮加密都包含了四种操作:SubBytes、ShiftRows、MixColumns 和 AddRoundKey。通过这些操作,AES 算法可以更加安全高效地对数据进行加密。
AES是一种对称加密
,所谓对称加密就是加密与解密使用的秘钥是一个。
pip install pycryptodome
AES 加密最常用的模式就是 ECB模式
和 CBC模式
,当然还有很多其它模式,他们都属于AES加密。ECB模式
和CBC模式
俩者区别就是 ECB 不需要 iv偏移量
,而CBC需要
。
"""
# 参数 作用及数据类型
1. 秘钥 :加密的时候用秘钥,解密的时候需要同样的秘钥才能解出来; 数据类型为bytes
2. 明文 :需要加密的参数; 数据类型为bytes
3. 模式 :aes 加密常用的有 ECB 和 CBC 模式(为主)(我只用了这两个模式,还有其他模式);数据类型为aes类内部的枚举量
iv 偏移量 :这个参数在 ECB 模式下不需要,在 CBC 模式下需要;数据类型为bytes
AES - CBC - 128 用得最多
长度
16: *AES-128*
24: *AES-192*
32: *AES-256*
MODE 加密模式:
常见的ECB, CBC
ECB:是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。
CBC:是一种循环模式,前一个分组的密文和当前分组的明文异或或操作后再加密,这样做的目的是增强破解难度。
"""
先加密 - 编码 - 解码 - 解密
from Crypto.Cipher import AES
import base64
# AES-128模式:key:16; iv:16位; 明文:是16的倍数;
# 明文
data = "Alex is ugly!" # 需要加密的内容
data = '{"name":"alex","msg":"ugly"}'
print(len(data)) # 13 位
while len(data) % 16 != 0: # 如果data不足16位的倍数就用空格补足为16位
data += "\0"
print(data, len(data)) # Alex is ugly! 16位
# 密钥
key = "1234567890123456".encode() # 保证16位数
# 偏移量
iv = "aaaabbbbccccdddd".encode() # 偏移量--必须16字节
# (1) 加密
# 创建一个aes对象
aes = AES.new(key, AES.MODE_CBC, iv) # 参数:密钥,MODE_CBC模式,偏移量
encrypt_data = aes.encrypt(data.encode()) # 加密明文
print(f"aes加密数据::::{encrypt_data}") # b'\x93\x1e\xdca\xbd\x08\xb1\xed\xef\xdbc\xc0\xa31\xaco'
# (2) base64编码
base64_encrypt_data = base64.b64encode(encrypt_data).decode() # 将返回的字节型数据转进行base64编码
print("base64_encrypt_data:", base64_encrypt_data) # kx7cYb0Ise3v22PAozGsbw==
# (3) base64解码
base64_encrypt_data = "kx7cYb0Ise3v22PAozGsbw=="
base64_encrypt_data = "ipmd89j3VlVClCk6EuFQFVxIeag1OwY0FrEKRTz2c9Y="
encrypt_data = base64.b64decode(base64_encrypt_data)
print(encrypt_data)
# (4) 解密,发生在服务端
# 密钥
key = "1234567890123456".encode()
# 偏移量
iv = "aaaabbbbccccdddd".encode()
# 解密
# 构建aes算法对象
aes = AES.new(key, AES.MODE_CBC, iv)
source_data = aes.decrypt(encrypt_data).decode()
print("source_data::::", source_data) # source_data:::: Alex is ugly!
import json
data_dict = json.loads(source_data.rstrip("\0"))
print("name:", data_dict.get("name"))
print("msg:", data_dict.get("msg"))
- 在Python中进行AES加密解密时,
所传入的密文、明文、秘钥、iv偏移量、都需要是bytes(字节型)数据
。python 在构建aes对象时也只能接受bytes类型数据。- 当
秘钥,iv偏移量,待加密的明文,字节长度不够16字节或者16字节倍数的时候需要进行补全。
- CBC模式需要重新生成AES对象,为了防止这类错误,无论是什么模式都重新生成AES对象就可以了。
非对称加密,加密和解密的秘钥不是同一个秘钥,这里需要两把钥匙,一个公钥, 一个私钥, 公钥发送给客户端。发送端用公钥对数据进行加密,再发送给接收端,接收端使用私钥来对数据解密。由于私钥只存放在接受端这边,所以即使数据被截获了,也是无法进行解密的。
常见的非对称加密算法:
RSA,DSA等等, 我们就介绍一个. RSA加密
, 也是最常见的一种加密方案。
数字签名是什么?
鲍勃有两把钥匙,一把是公钥,另一把是私钥
。
鲍勃把公钥送给他的朋友们----帕蒂、道格、苏珊----每人一把。
苏珊要给鲍勃写一封保密的信。她写完后用鲍勃的公钥加密,就可以达到保密的效果。
鲍勃收信后,用私钥解密,就看到了信件内容。这里要强调的是,只要鲍勃的私钥不泄露,这封信就是安全的,即使落在别人手里,也无法解密。
鲍勃给苏珊回信,决定采用"数字签名"。他写完后先用Hash函数
,生成信件的摘要(digest)。
然后,鲍勃使用私钥,对这个摘要加密,生成"数字签名"(signature)。
鲍勃将这个签名,附在信件下面,一起发给苏珊。
苏珊收信后,取下数字签名,用鲍勃的公钥解密,得到信件的摘要。由此证明,这封信确实是鲍勃发出的。
苏珊再对信件本身使用Hash函数,将得到的结果,与上一步得到的摘要进行对比。如果两者一致,就证明这封信未被修改过。
复杂的情况出现了。道格想欺骗苏珊,他偷偷使用了苏珊的电脑,用自己的公钥换走了鲍勃的公钥。此时,苏珊实际拥有的是道格的公钥,但是还以为这是鲍勃的公钥。因此,道格就可以冒充鲍勃,用自己的私钥做成"数字签名",写信给苏珊,让苏珊用假的鲍勃公钥进行解密。
后来,苏珊感觉不对劲,发现自己无法确定公钥是否真的属于鲍勃。她想到了一个办法,要求鲍勃去找"证书中心"(certificate authority,简称CA),为公钥做认证。证书中心用自己的私钥,对鲍勃的公钥和一些相关信息一起加密,生成"数字证书"(Digital Certificate)。
鲍勃拿到数字证书以后,就可以放心了。以后再给苏珊写信,只要在签名的同时,再附上数字证书就行了。
苏珊收信后,用CA的公钥解开数字证书,就可以拿到鲍勃真实的公钥了,然后就能证明"数字签名"是否真的是鲍勃签的。
from Crypto.PublicKey import RSA
# 生成秘钥
rsakey = RSA.generate(1024)
with open("rsa.public.pem", mode="wb") as f:
f.write(rsakey.publickey().exportKey()) # 公钥
with open("rsa.private.pem", mode="wb") as f:
f.write(rsakey.exportKey()) # 私钥
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64
# 明文数据
data = "I like you"
# 读取公钥
with open("rsa.public.pem", "r") as f:
public_key = f.read()
print("公钥 - public_key::::", public_key)
# (1)基于公钥做加密
rsa_pk = RSA.importKey(public_key)
rsa = PKCS1_v1_5.new(rsa_pk)
encrypt_data = rsa.encrypt(data.encode())
print("加密数据 - encrypt_data::::", encrypt_data)
# (2)base64编码 - 处理成b64方便传输
b64_encrypt_data = base64.b64encode(encrypt_data).decode()
print("b 64_加密数据 - b64_encrypt_data::::", b64_encrypt_data)
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64
b64_encrypt_data = "XA7rH4aYoZ+mrQddsCt+zGOG4uB+oqU2BOoo6rxaYJAj3y/4wR2a/hId5tsgisxZoVw1j2mlSYOZzFIpKSwv53JrI/SYtWl7qH4QCXimaTB4a4qZ+Vf//h7KoI51vlXu9o1GQYMm9ijrb0MmUZc9BX85UdLf0/+p46s5tBcC1IU="
# (3)base64解码
encrypt_data = base64.b64decode(b64_encrypt_data)
print("encrypt_data:", encrypt_data)
# (4)基于私钥解密
with open("rsa.private.pem", "r") as f: # 读取私钥
private_key = f.read()
rsa_pk = RSA.importKey(private_key)
rsa = PKCS1_v1_5.new(rsa_pk)
data = rsa.decrypt(encrypt_data,None)
print("data:", data.decode())