Python实现中英文通用的AES加密算法

一、前言

AES是一种对称加密,所谓对称加密就是加密与解密使用的秘钥是一个。在日常的开发中,无论是实现前后端的接口数据加密,还是数据传输安全性,都使用了AES加密,本文章将从python的角度去实现AES的加密和解密

二、环境安装

AES的加密方式有很多种,例如ECB、CBC、CTR、OFB、CFB,最常用的是ECB和CBC,本文章侧重从CBC模式来实现加密和解密:

#AES加密环境
import base64
from Crypto.Cipher import  AES

这是需要用到的库,如果报错的情况下

#AES加密环境
#先卸载这些包,防止一些环境问题
pip uninstall crypto
pip uninstall pycryptodome
#在安装
pip install pycryptodome

三、加密

在加密的过程中,我们会经常碰到一个问题,当一串JSON里面有中文又有英文的时候,我们做加密的时候经常会报这样的错
ValueError: Data must be padded to 16 byte boundary in CBC mode
这里面就牵扯到中文和文字符的长度问题,在utf-8编码:一个中文包含繁体字等于三个字节,一个英文字符等于一个字节。gbk编码:一个中文包含繁体字等于二个字节,一个英文字符等于一个字节,不多说,直接上代码

iv='shzxsjicommunity' #偏移量
key='shzxsjicommunity' #密钥
#补足字节方法
def pad(value):
    BLOCK_SIZE = 16  # 设定字节长度
    count=len(value)
    if(count%BLOCK_SIZE !=0):
        add=BLOCK_SIZE-(count%BLOCK_SIZE)
    else:
        add=0
    text=value+("\0".encode()*add) # 这里的"\0"必须编码成bytes,不然无法和text拼接
    return text

# 将明文用AES加密
def AES_en(data):
    # 将长度不足16字节的字符串补齐
    data=pad(data.encode())#注意在这个地方要把传过来的数据编码成bytes,不然还是会报上面说的那个错
    # 创建加密对象
    AES_obj = AES.new(key.encode("utf-8"), AES.MODE_CBC, iv.encode("utf-8"))
    # 完成加密
    AES_en_str = AES_obj.encrypt(data)
    # 用base64编码一下
    AES_en_str = base64.b64encode(AES_en_str)
    # 最后将密文转化成字符串
    AES_en_str = AES_en_str.decode("utf-8")
    return AES_en_str
    
data="{'test':'我是一个小小的程序员!'}" #测试数据
b=AES_en(data1)
print(f"加密为:{b}") #此写法python3.6以上才支持

输出结果

加密为:6kJuZxX6EUUp9QgeBbDUuHiQznKMQz87GaQxKaVPlVIhwODIKCBcdz70ZhB9PFbp

四、解密

直接上代码
输出结果

def AES_de(data):
    # 解密过程逆着加密过程写
    # 将密文字符串重新编码成二进制形式
    data = data.encode("utf-8")
    # 将base64的编码解开
    data = base64.decodebytes(data)
    # 创建解密对象
    AES_de_obj = AES.new(key.encode("utf-8"), AES.MODE_CBC, iv.encode("utf-8"))
    # 完成解密
    AES_de_str = AES_de_obj.decrypt(data)
    # 去掉补上的空格
    AES_de_str =AES_de_str.strip()
    # 对明文解码
    AES_de_str = AES_de_str.decode("utf-8")
    return AES_de_str.strip(b'\x00'.decode()) #去除特定的空格

我们把加密上面的结果放到解密来,输出结果

data='6kJuZxX6EUUp9QgeBbDUuHiQznKMQz87GaQxKaVPlVIhwODIKCBcdz70ZhB9PFbp'
a=AES_de(data)
print(f"解密为:{a}")

输出结果

解密为:{'name':'我是一个小小的程序员!'}

五、完整代码

# -*- coding: utf-8 -*-
#AES加密
import base64
from Crypto.Cipher import  AES


iv='shzxsjicommunity'#偏移量
key='shzxsjicommunity'#密钥
#补足字节方法
def pad(value):
    BLOCK_SIZE = 16  # 设定字节长度
    count=len(value)
    if(count%BLOCK_SIZE !=0):
        add=BLOCK_SIZE-(count%BLOCK_SIZE)
    else:
        add=0
    text=value+("\0".encode()*add) # 这里的"\0"必须编码成bytes,不然无法和text拼接
    return text
# 将明文用AES加密
def AES_en(data):
    # 将长度不足16字节的字符串补齐
    data=pad(data.encode())
    # 创建加密对象
    AES_obj = AES.new(key.encode("utf-8"), AES.MODE_CBC, iv.encode("utf-8"))
    # 完成加密
    AES_en_str = AES_obj.encrypt(data)
    # 用base64编码一下
    AES_en_str = base64.b64encode(AES_en_str)
    # 最后将密文转化成字符串
    AES_en_str = AES_en_str.decode("utf-8")
    return AES_en_str

def AES_de(data):
    # 解密过程逆着加密过程写
    # 将密文字符串重新编码成二进制形式
    data = data.encode("utf-8")
    # 将base64的编码解开
    data = base64.decodebytes(data)
    # 创建解密对象
    AES_de_obj = AES.new(key.encode("utf-8"), AES.MODE_CBC, iv.encode("utf-8"))
    # 完成解密
    AES_de_str = AES_de_obj.decrypt(data)
    # 去掉补上的空格
    AES_de_str =AES_de_str.strip()
    # 对明文解码
    AES_de_str = AES_de_str.decode("utf-8")
    return AES_de_str.strip(b'\x00'.decode())

if __name__=='__main__':
    data="{'test':'我是一个小小的程序员!'}"
    b=AES_en(data)
    print(f"加密为:{b}")#python3.6以上的写法
    a=AES_de(b)
    print(f"解密为:{a}")

我们可以通过该网站看自己的加密和解密是否正确:验证.
希望与大家一起学习交流!!!有什么python和go的问题可以私信我

物联沃分享整理
物联沃-IOTWORD物联网 » Python实现中英文通用的AES加密算法

发表评论