AES、DES和3DES
所谓对称加密就是加密和解密用的是同一个秘钥. 就好比. 我要给你邮寄一个箱子. 上面怼上锁. 提前我把钥匙给了你一把, 我一把. 那么我在邮寄之前就可以把箱子锁上. 然后快递到你那里. 你用相同的钥匙就可以打开这个箱子.
条件: 加密和解密用的是同一个秘钥. 那么两边就必须同时拥有钥匙才可以.
常见的对称加密: AES, DES, 3DES。
AES
AES.new 三个参数:
<1>.key: 可以有三种长度,分别是: *AES-128*: 16 ; *AES-192*: 24 ; *AES-256*: 32
百分之90以上网站AES-128,所以通常是16位的字节。
那怎么确定是用16位、24位还是32位呢,一般就直接给16位,如果不行,再换其他的。
如果在逆向过程中看到的是只给我们20个字节,要考虑把20个字节怎么变成16个字节,所以要砍掉一些,只留前面16个。
如果在网页上看到十六进制字符串,如果是32位的,那么基本上用的都是16位的字节。转换关系:每两个字符串对于一个字节,使用: binascii.b2a_hex() 和 binascii.a2b_hex() 。
<2>.mode: CBC(需要iv), ECB(不需要iv)
<3>.iv: CBC模式下是16位的字节
# 导入AES, 请注意, 大小写问题.
import binascii
from Crypto.Cipher import AES, DES, DES3
from Crypto.Util.Padding import pad, unpad # 填充
import base64
# 创建一个aes加密器
aes = AES.new(key=b'1234567890123456', IV=b'1234567890123456', mode=AES.MODE_CBC)
ming = "威海龙王和东海龙王谁更猛!!!!!" #这是明文,需要对明文加密
ming = ming.encode("utf-8") # 第一件事必须处理成字节。注意:加密或者解密, 处理的都是字节。
# 如果不给填充16个字节,就会报错:Data must be padded to 16 byte boundary in CBC mode
ming = pad(ming, 16)
mi = aes.encrypt(ming)
print(mi)
# 输出:b'\x97\x99\xf5\x8a\xc4\xe6\xce\xe1*\r\xfc\x8e\xbb\xe4\xc9C\xc5\x9bN\x9fYZF\xcf\xf3\xd5*\x18\xd7\x04\xeb\xa38\xe7\xec\xfb\xe2\xb0\xe0Cf\xd4P\xe3\xef\x87o\x80'
# 能不能用utf8或者binascii处理这些加密的内容? print(mi.decode("utf-8")) 加密之后的内容是杂乱无章的字节,没有任何规律的字节,没那么容易处理这些加密内容。
# 所以utf8是不能处理这些内容的,还是得用 base64 来处理。
s = base64.b64encode(mi).decode()
print(s)
# 输出结果: l5n1isTmzuEqDfyOu+TJQ8WbTp9ZWkbP89UqGNcE66M45+z74rDgQ2bUUOPvh2+A
# 解密
mi = 'l5n1isTmzuEqDfyOu+TJQ8WbTp9ZWkbP89UqGNcE66M45+z74rDgQ2bUUOPvh2+A'
# 解密逻辑 (对称加密里)加密和解密逻辑几乎一样..
aes = AES.new(key=b'1234567890123456', IV=b'1234567890123456', mode=AES.MODE_CBC)
mi = base64.b64decode(mi)
ming = aes.decrypt(mi)
ming = unpad(ming, 16) # 干掉填充即可
print(ming.decode("utf-8"))
DES
from Crypto.Cipher import DES
from Crypto.Util.Padding import pad, unpad # 填充
import base64
# 加密
# 需要加密的数据必须是16的倍数
# 填充规则: 缺少数据量的个数 * chr(缺少数据量个数)
s = "我爱吃鱼"
ming = s.encode("utf-8")
# key: 8个字节
des = DES.new(key=b'12345678', iv=b'12345678', mode=DES.MODE_CBC)
ming = pad(ming, 8) # 填充到8位
mi = des.encrypt(ming)
mi_s = base64.b64encode(mi).decode()
print(mi_s)
# 解密
mi_s = "bXZ8WcOzh/SW0yuFPTTZog=="
des = DES.new(key=b'12345678', iv=b'12345678', mode=DES.MODE_CBC)
ming = des.decrypt(base64.b64decode(mi_s))
ming = unpad(ming, 8)
print(ming.decode("utf-8"))
3DES
下面的代码会报错: ValueError: Triple DES key degenerates to single DES
由于3DES要求key的前半部分(12345678)和后半部分(12345678)不能一致。
from Crypto.Cipher import AES, DES, DES3
from Crypto.Util.Padding import pad, unpad
import base64
s = "我爱吃鱼"
ming = s.encode("utf-8")
des = DES3.new(key=b'1234567812345678', iv=b'12345678', mode=DES.MODE_CBC)
ming = pad(ming, 8) # 填充到8位
mi = des.encrypt(ming)
mi_s = base64.b64encode(mi).decode()
print(mi_s)
改成 key=b'1234567812345670' 前半部分(12345678)和后半部分(12345670)不能一致即可
from Crypto.Cipher import AES, DES, DES3
from Crypto.Util.Padding import pad, unpad
import base64
s = "我爱吃鱼"
ming = s.encode("utf-8")
des = DES3.new(key=b'1234567812345670', iv=b'12345678', mode=DES.MODE_CBC)
ming = pad(ming, 8) # 填充到8位
mi = des.encrypt(ming)
mi_s = base64.b64encode(mi).decode()
print(mi_s)
一般的网站key来源的做法是先提供一个值,计算它的md5(或者sha1、sha256),然后这个是32位的,取其中的一半就可以了。
浙公网安备 33010602011771号