python AES加密解密

2022年1月11日21:25:44 发表评论 460 views

可算搞成一半了,经核对,加解密后哈希值相等,可以正常使用

# 二进制加密解密测试完成
import base64
import hashlib
import os

from Crypto.Cipher import AES
from Crypto import Random
"""
神坑:
将crypto的包文件夹改成大写即可, 或者安装pycryptodome
在 Windows 中,不管是 Python2 和 Python3 ,都不能用 crypto 和 pycrypto ,可以用 pycryptodome 。
在 Linux 中,不管是 Python2 和 Python3 ,都不能用 crypto ,可以用 pycrypto 和 pycryptodome 。
还要安装cipher
"""
with open(file='C:/log2.txt',mode='r',encoding='utf-8') as f:
    secret = f.read()
    print(secret)

class AESCipher:
    def __init__(self):
        '''
        CBC加密需要一个十六位的key(密钥)和一个十六位iv(偏移量)
        '''
        self.key = self.check_key(secret)
        # 数据块的大小  16位
        self.BS = 16
        # CBC模式 相对安全 因为有偏移向量 iv 也是16位字节的
        self.mode = AES.MODE_CBC
        # 填充函数 因为AES加密是一段一段加密的  每段都是BS位字节,不够的话是需要自己填充的
        self.pad = lambda s: s + ((self.BS - len(s) % self.BS)*chr(self.BS - len(s) % self.BS)).encode()
        # 将填充的数据剔除
        self.unpad = lambda s: s[:-ord(s[len(s) - 1:])]

    def check_key(self, key):
        '''
        检测key的长度是否为16,24或者32bytes的长度
        '''
        try:
            if isinstance(key, bytes):
                assert len(key) in [16, 24, 32]
                return key
            elif isinstance(key, str):
                assert len(key.encode()) in [16, 24, 32]
                return key.encode()
            else:
                pass
                # raise Exception(f'密钥必须为str或bytes,不能为{type(key)}')
        except AssertionError:
            print('输入的长度不正确')

    def check_data(self, data):
        '''
        检测加密的数据类型
        '''
        if isinstance(data, int):
            data = str(data)
        elif isinstance(data, bytes):
            # data = data.decode()
            data = data # 改字节加解密不需要这个
        elif isinstance(data, str):
            pass
        else:
            pass
            # raise Exception(f'加密的数据必须为str或bytes,不能为{type(data)}')
        return data

    def encrypt(self, raw):
        raw = self.check_data(raw)
        print('lenchecked raw',len(raw))
        raw = self.pad(raw)   #改字节加密,注释此句
        print('len pad rawlen',len(raw))
        # 随机获取iv
        iv = Random.new().read(AES.block_size)
        # 定义初始化
        cipher = AES.new(self.key, self.mode, iv)
        # 此处是将密文和iv一起 base64 解密的时候就可以根据这个iv来解密
        encdata = iv + cipher.encrypt(raw)
        print('len enc data',len(encdata))
        return encdata

    def decrypt(self, enc):
        # 先将密文进行base64解码
        # enc = base64.b64decode(enc)   #加密不存base64了, 后面直接用二进制 可节省空间30%
        # 取出iv值
        iv = enc[:self.BS]
        # 初始化自定义
        cipher = AES.new(self.key, self.mode, iv)
        # 返回utf8格式的数据
        return self.unpad(cipher.decrypt(enc[self.BS:]))  #删除decode()保留二进制写入



# from random import randint

if __name__ == "__main__":
    encpython = r'C:\Users\Administrator\Desktop\加密'
    files = os.walk(encpython)
    for path,dirlist,filelist in files:
        for file in filelist:
            if not file.startswith('enc777'):
                file_path = os.path.join(path, file)
                with open(file=os.path.join(path,file),mode='rb') as f:
                    file_content = f.read()
                content_hash = hashlib.md5(file_content).hexdigest()
                aes = AESCipher()
                enc_content = aes.encrypt(file_content)
                dec_contnet = aes.decrypt(enc_content)
                content_hashdec = hashlib.md5(dec_contnet).hexdigest()
                print(content_hash==content_hashdec,'ddddd')

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: