一个AES对称加密文件的使用举例

#! /usr/bin/env python
# -*- coding: utf-8 -*-
from Crypto.Cipher import AES
import getopt
import sys
import getpass

ARGS_DICT = {}


class AESUtil:
    __BLOCK_SIZE_16 = BLOCK_SIZE_16 = AES.block_size

    @staticmethod
    def encrypt(source, destination, **kwargs):
        src_bytes = b''

        key = kwargs.get('key')
        while not key:
            key = getpass.getpass('请输入口令:')
        key = bytes(key.ljust(16, ' '), encoding='utf8')

        with open(source, 'br') as fd:
            src_bytes = fd.read()
        x = AESUtil.__BLOCK_SIZE_16 - (len(src_bytes) % AESUtil.__BLOCK_SIZE_16)
        if x != 0:
            src_bytes = src_bytes + b' ' * \
                (x - 1) + bytes(f'{hex(x)[-1]}', encoding='utf-8')
        else:
            src_bytes = src_bytes + b' ' * 15 + b'f'

        cipher = AES.new(key, AES.MODE_ECB)
        msg = cipher.encrypt(src_bytes)
        with open(destination, 'bw') as fd:
            fd.write(msg)
        print(f'加密,源文件:{source},输出文件:{destination}')

    @staticmethod
    def decrypt(source, destination, **kwargs):
        src_bytes = ''

        key = kwargs.get('key')
        while not key:
            key = getpass.getpass('请输入口令:')
        key = bytes(key.ljust(16, ' '), encoding='utf8')       
        with open(source, 'br') as fd:
            src_bytes = fd.read()

        cipher = AES.new(key, AES.MODE_ECB)
        msg = cipher.decrypt(src_bytes)
        fill_len = 0 - int(chr(msg[-1]), base=16)
        msg = msg[0:fill_len]
        with open(destination, 'bw') as fd:
            fd.write(msg)
        print(f'解密,源文件:{source},输出文件:{destination}')


class Option(object):
    def __init__(self, arg_type, arg_short, arg_long,
                 arg_intro, ar_priority, arg_must, arg_deal=None, **kwargs):
        self.arg_type, self.arg_short, self.arg_long = arg_type, arg_short, arg_long
        self.arg_intro, self.arg_priority, self.arg_must = arg_intro, ar_priority, arg_must
        self.arg_deal = arg_deal

    def show_help_tex(self):
        arg_must = '必选参数' if self.arg_must == '1' else '可选参数'
        arg_type = '传参项' if self.arg_type == '1' else '开关项'
        return f'\t-{self.arg_short}\t--{self.arg_long}\t{arg_type}\t{arg_must}\t{self.arg_intro}'


OPTION_LIST = [
    Option('1', 's', 'source', '指定输入文件。', '1', '1'),
    Option('1', 'd', 'destination', '指定输出文件。', '1', '1'),
    Option('1', 'k', 'key', '指定加密口令。', '1', '0'),
    Option('0', 'e', 'encrypt', '开关选项,打开加密,关闭解密。', '1', '0')
]


def help_tex(option_list, **kwargs):
    tex_l = [f'Usage: python {__file__} -k xxx -s xxx -d xxx [-e]',]
    for option in option_list:
        tex_l.append(option.show_help_tex())
    print('\n'.join(tex_l))


OPTION_LIST.append(Option('0', 'h', 'help', '显示使用方法说明', '0', '0', help_tex))
ARGS_DICT['option_list'] = OPTION_LIST


def form_sign():
    short_str = ''
    long_list = []
    for option in OPTION_LIST:
        short_str += f'{option.arg_short}'
        if option.arg_type == '1':
            short_str += ':'
            long_list.append(f'{option.arg_long}=')
    return short_str, long_list


def get_conf(conf_dict, argv):
    try:
        opts, args = getopt.getopt(argv, *form_sign())
        args_d = dict((item[0].replace('-', ''), item[1]) for item in opts)
        conf_dict.update(args_d)
    except getopt.GetoptError as e:
        print(e)
    except Exception as e:
        print(e)


def deal_zero_priority():
    code = 0
    zero_options = filter(lambda x: x.arg_priority == '0', OPTION_LIST)
    for option in zero_options:
        if option.arg_short in ARGS_DICT or option.arg_long in ARGS_DICT:
            code = 1
            if option.arg_deal:
                option.arg_deal(**ARGS_DICT)
    if code:
        exit(code)


def deal_must_args():
    code = 0
    must_options = filter(lambda x: x.arg_must == '1', OPTION_LIST)
    for option in must_options:
        if option.arg_short in ARGS_DICT or option.arg_long in ARGS_DICT:
            continue
        else:
            code = 1
            print(option.show_help_tex())
    if code:
        exit(code)


all_args = {}
def form_all_args():
    for option in OPTION_LIST:
        if option.arg_short in ARGS_DICT or option.arg_short in ARGS_DICT:
            all_args[option.arg_long] = ARGS_DICT.get(option.arg_short) or\
                 ARGS_DICT.get(option.arg_long)


if __name__ == "__main__":
    get_conf(ARGS_DICT, sys.argv[1:])
    deal_zero_priority()
    deal_must_args()
    form_all_args()
    if 'encrypt' in all_args:
        AESUtil.encrypt(**all_args)
    else:
        AESUtil.decrypt(**all_args)

版权声明:除特别注明外,本站所有文章均为王晨曦个人站点原创

转载请注明:出处来自王晨曦个人站点 » 一个AES对称加密文件的使用举例

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注

  1. 王晨曦 说道:

    1、应该尝试使用getpass输入密钥; 2、应该添加getopt --help 相关提示; 3、可以尝试拓展其他的对称加密方法; 4、完善加解密特大文件的使用体验。