鱼C论坛

 找回密码
 立即注册
查看: 263|回复: 0

[技术交流] python AES CBC加密

[复制链接]
发表于 2021-8-20 09:30:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 大马强 于 2021-8-25 21:28 编辑

密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准
CBC是其加密模式之一,python中需要用到 Crypto 库,导入格式为 from Crypto.Cipher import AES
一、加密
    1.建一个加密器 aes = AES.new( key, iv, mode), 其中 key为密钥,iv为偏移量,mode为加密模式(AES.MODE_CBC)
    2.进行加密 result = aes.encrypt(text),其中 text为加密文本
二、解密
    1.建一个解密器 aes = AES.new( key, iv, mode), 其中 key为密钥,iv为偏移量,mode为加密模式(AES.MODE_CBC)
    2.进行解密result = aes.decrypt(text)
三、注意事项
    1.类型要求:text,iv,key,都要bytes类型
    2.长度要求:iv必须16个字节, key 可以是{16,24,32},text必须为16直接的倍数,所以加密前要进行补齐,解密后进行去余
    3.加密后的结果虽然是 byter 但不能直接解码,想要变为 str 要借助base64模块,解密后却可以直接解码
    4.加密和解密不能公用一个 加/解密器, 要分别去定义一个

四、案例代码
1.初始准备 - 导入相关的库
import json
from Crypto.Cipher import AES
from base64 import b64encode, decodebytes
2.对数据准备和处理
# 数据声明定义以及处理
data = {
    'cursor': "-1",
    "offset": "0",
    "orderType": "1",
    "pageNo": "1",
    "pageSize": "20",
    "rid": "R_SO_4_1855995767",
    "threadId": "R_SO_4_1855995767"
}

iv = "0102030405060708"
key = "0CoJUm6Qyw8W8jud"

# 处理数据
iv, key = iv.encode("utf-8"), key.encode("utf-8")
text = json.dumps(data)   # json处理字典类型,将其转化为str类型
相关报错
iv -> Incorrect IV length (it must be 16 bytes long) -> 长度不合法,必须限定为16字节长度
key ->  Incorrect AES key length (xx long) -> 长度不合法,xx表示当前长度
text -> Data must be padded to 16 byte boundary in CBC mode -> 长度不合法,补齐到16字节的倍数

3.补位
def pad(text):
    pad = 16 - len(text) % 16
    text += chr(pad) * pad
    return text.encode("utf-8")
4.加密
def encrypt(text):
    print("原text的类型%s和长度%s" % (type(text), len(text)))
    text = pad(text)
    print("当前text的类型%s和长度%s" % (type(text), len(text)))
    aes = AES.new(key=key, iv=iv, mode=AES.MODE_CBC)
    result = aes.encrypt(text)
    # 不能直接解码
    # result.decode("utf-8") 报错 'utf-8' codec can't decode byte 0x8c in position 0: invalid start byte
    print("加密后未处理的result类型%s\n内容:%s" % (type(result), result))
    result = b64encode(result)
    print("加密后b64处理后的result类型%s\n内容:%s" % (type(result), result))
    print("得到最终的密文类型%s\n内容:%s" %
          (type(result.decode("utf-8")), result.decode("utf-8")))
    return result.decode("utf-8")
输出
原text的类型<class 'str'>和长度143
当前text的类型<class 'bytes'>和长度144
加密后未处理的result类型<class 'bytes'>
内容:b'\x8cr2\t\x7f\xb4h\x0cp\xb7@\xc0\xe7\xdbf\x03!Z\xf4\x99\x01\xe6d%fP\xfb\xdb\xce\x08<\xab~\xf4\xfd\x1d?\xfd\x7f?\xe5\x065\xc6\x18^\x81+] \x1f\xe7MO\x9d\xe49\xac\xd3\xd35\xfe\xdd\x1f\xf1\xad[F\xa9\x1f\xa0\xa0\xe6\xc4\xa0\x17\xfc\xdf\xaa-o`}\x9d\xf5\x81\x8b\x9e\xed\x17\xb0\xe9q\x1fw1\xbbK,\x96E$\xdd8\x93\xf7\x90\xb5A\xc2\x81\x83\xbe\r\x9cHh!n\x7fc\xd3\xc8\xe8\x8a@jR{9\xc9\x9a>3\x88\xa9\xach5(\xf1\xef\x1a\xaa'
加密后b64处理后的result类型<class 'bytes'>
内容:b'jHIyCX+0aAxwt0DA59tmAyFa9JkB5mQlZlD7284IPKt+9P0dP/1/P+UGNcYYXoErXSAf501PneQ5rNPTNf7dH/GtW0apH6Cg5sSgF/zfqi1vYH2d9YGLnu0XsOlxH3cxu0sslkUk3TiT95C1QcKBg74NnEhoIW5/Y9PI6IpAalJ7OcmaPjOIqaxoNSjx7xqq'
得到最终的密文类型<class 'str'>
内容:jHIyCX+0aAxwt0DA59tmAyFa9JkB5mQlZlD7284IPKt+9P0dP/1/P+UGNcYYXoErXSAf501PneQ5rNPTNf7dH/GtW0apH6Cg5sSgF/zfqi1vYH2d9YGLnu0XsOlxH3cxu0sslkUk3TiT95C1QcKBg74NnEhoIW5/Y9PI6IpAalJ7OcmaPjOIqaxoNSjx7xqq

五。解密
def decrypt(text):
    text = text.encode("utf-8")
    text = decodebytes(text)
    print("decodebytes处理后text类型:%s\n内容:%s" % (type(text), text))
    aes = AES.new(key=key, iv=iv, mode=AES.MODE_CBC)
    result = aes.decrypt(text)
    print("解密后未处理的result类型:%s\n内容:%s" % (type(result), result))
    result = unpad(result.decode("utf-8"))
    print("解密后去余的result类型:%s\n内容:%s" % (type(result), result))
    result = json.loads(result)
    print("解密后最终还原的result类型:%s\n内容:%s" % (type(result), result))
    return result
输出
decodebytes处理后text类型:<class 'bytes'>
内容:b'\x8cr2\t\x7f\xb4h\x0cp\xb7@\xc0\xe7\xdbf\x03!Z\xf4\x99\x01\xe6d%fP\xfb\xdb\xce\x08<\xab~\xf4\xfd\x1d?\xfd\x7f?\xe5\x065\xc6\x18^\x81+] \x1f\xe7MO\x9d\xe49\xac\xd3\xd35\xfe\xdd\x1f\xf1\xad[F\xa9\x1f\xa0\xa0\xe6\xc4\xa0\x17\xfc\xdf\xaa-o`}\x9d\xf5\x81\x8b\x9e\xed\x17\xb0\xe9q\x1fw1\xbbK,\x96E$\xdd8\x93\xf7\x90\xb5A\xc2\x81\x83\xbe\r\x9cHh!n\x7fc\xd3\xc8\xe8\x8a@jR{9\xc9\x9a>3\x88\xa9\xach5(\xf1\xef\x1a\xaa'
解密后未处理的result类型:<class 'bytes'>
内容:b'{"cursor": "-1", "offset": "0", "orderType": "1", "pageNo": "1", "pageSize": "20", "rid": "R_SO_4_1855995767", "threadId": "R_SO_4_1855995767"}\x01'   
解密后去余的result类型:<class 'str'>
内容:{"cursor": "-1", "offset": "0", "orderType": "1", "pageNo": "1", "pageSize": "20", "rid": "R_SO_4_1855995767", "threadId": "R_SO_4_1855995767"}
解密后最终还原的result类型:<class 'dict'>
内容:{'cursor': '-1', 'offset': '0', 'orderType': '1', 'pageNo': '1', 'pageSize': '20', 'rid': 'R_SO_4_1855995767', 'threadId': 'R_SO_4_1855995767'}

6.去余
def unpad(s):
    return s[:-ord(s[len(s) - 1:])]
7.其他
if __name__ == "__main__":
    encrypt_text = encrypt(text)
    decrypt_text = decrypt(encrypt_text)
    if decrypt_text == data:
        print("解密成功!")


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-13 13:50

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表