windows中使用Python进行AES加密解密-文本文件加密工具

之前的文章http://blog.csdn.net/u013578500/article/details/77905924

简单介绍了一下使用PyCrypto模块实现对字符串的加密解密,里面有提到我利用这个模块写了一个对文本文件进行加密解密的小脚本,这里和大家分享一下。

1.脚本运行流程

脚本非首次运行时,当前目录下存在且仅密文Pwencrypt,脚本首先会读取密文文件,执行解密并将结果写入PW.txt,随后调用系统接口打开PW.txt。此时脚本将被挂起,当PW.txt被关闭后,脚本继续运行,读取PW.txt并加密,写入Pwencrypt,最后删除PW.txt。
如果是第一次运行脚本,则脚本目录下应不存在密文文件Pwencrypt,且存在PW.txt,此时脚本直接读取PW.txt并执行加密流程。 

脚本运行流程如下图。


其中PWencrypt文件为加密后的密文文件,结构为:{密文+‘,’+MD5校验码},PW.txt文件为明文文件。 

2.输入密码

打开脚本首先需要输入密码,可以使用Python自带的getpass模块,代码如下:
import getpass
…
# 输入密码
key = getpass.getpass("Password Please:")

3.计算MD5值

PyCrypto同样可以进行MD5值的计算,这里我通过对明文的MD5码进行校验,来确认输入的密码是否正确。MD5计算模块的用法如下:
from Crypto.Hash import MD5

MD5hash = MD5.new()
MD5hash.update('Hello')
print MD5hash.hexdigest()
关于PyCrypto的用法,可以参考下面这个链接:
https://pythonhosted.org/pycrypto/Crypto-module.html

4.编写基本的加密解密函数

直接使用之前文章中的代码即可,这里使用CBC加密模式。
from Crypto.Cipher import AES
from binascii import a2b_hex,b2a_hex


# 补全字符
def align(str, isKey=False):
    # 如果接受的字符串是密码,需要确保其长度为16
    if isKey:
        if len(str) > 16:
            return str[0:16]
        else:
            return align(str)
    # 如果接受的字符串是明文或长度不足的密码,则确保其长度为16的整数倍
    else:
        zerocount = 16-len(str) % 16
        for i in range(0, zerocount):
            str = str + '\0'
        return str


# CBC模式加密
def encrypt_CBC(str, key):
    # 补全字符串
    str = align(str)
    key = align(key, True)
    # 初始化AES,引入初始向量
    AESCipher = AES.new(key, AES.MODE_CBC, '1234567890123456')
    # 加密
    cipher = AESCipher.encrypt(str)
    return b2a_hex(cipher)




# CBC模式解密
def decrypt_CBC(str, key):
    # 补全字符串
    key = align(key, True)
    # 初始化AES
    AESCipher = AES.new(key, AES.MODE_CBC, '1234567890123456')
    # 解密
    paint = AESCipher.decrypt(a2b_hex(str))
    return paint

5.解密流程

读取密文文件并用密码解密,首先以只读方式打开Pwencrypt,如果文件不存在,则触发异常直接进入加密流程。
Pwencrypt文件分两部分,前半部分为文件密文,后半部分为明文的哈希值,用符号‘,’分隔。
解密完成并校验后,会将密码写入明文文件PW.txt中,之后调用系统接口使用notepad打开该文件。
import os
os.system("notepad PW.txt")
打开文件后脚本进程将被暂时挂起,直到PW.txt文件被关闭。
解密流程具体代码如下:
# 尝试读取密文文件,如果密文文件不存在,则不进行解密直接进入加密流程
try:
    fcipher = open("PWencrypt", "r")
    fpaint = open("PW.txt", "w+")
    # 读取密文文件
    fcipherText = fcipher.read()
    # 读取密文和校验哈希值
    cipherText = fcipherText.split(',')[0]
    painhash = fcipherText.split(',')[1]
    # 用密码解密
    painText = decrypt_CBC(cipherText, key)
    # 去除/0
    painText = painText.rstrip('\0')
    # 校验密码
    # 计算本次解密后明文的哈希值
    MD5hash = MD5.new()
    MD5hash.update(painText)
    # 比对哈希值判断密码是否正确
    if painhash != MD5hash.hexdigest():
        print ('wrong password!!')
    else:
        fpaint.write(painText)
        fpaint.close()
        fcipher.close()
        print ("Don't Close!!!")
        os.system("notepad PW.txt")
except:
    print("error!")

6.加密流程

首先以只读方式打开PW.txt,当解密失败或其他异常发生导致文件内容为空,则跳过加密流程直接结束。
# 加密,加密明文文件,写入密文文件并删除明文文件
try:
    fpaint = open("PW.txt", "r")
    # 读取明文文件
    painText = fpaint.read()
    # 如果明文为空,则不执行加密
    if len(painText) > 0:
        fcipher = open("PWencrypt", "w")
        # 加密
        cipherText = encrypt_CBC(painText, key)
        # 计算明文哈希值
        MD5hash = MD5.new()
        MD5hash.update(painText)
        # 将密文和校验码写入密文文件
        cipherText = cipherText + ',' + MD5hash.hexdigest()
        fcipher.write(cipherText)
        fcipher.close()
    fpaint.close()
    # 删除明文文件
    os.remove("PW.txt")
except:
    print("Something wrong when Encrypt!!")

7.完整代码

# -*- coding: UTF-8 -*-


from Crypto.Cipher import AES
from Crypto.Hash import MD5
from binascii import a2b_hex,b2a_hex
import getpass
import os
import time


# 补全字符
def align(str, isKey=False):
    # 如果接受的字符串是密码,需要确保其长度为16
    if isKey:
        if len(str) > 16:
            return str[0:16]
        else:
            return align(str)
    # 如果接受的字符串是明文或长度不足的密码,则确保其长度为16的整数倍
    else:
        zerocount = 16-len(str) % 16
        for i in range(0, zerocount):
            str = str + '\0'
        return str


# CBC模式加密
def encrypt_CBC(str, key):
    # 补全字符串
    str = align(str)
    key = align(key, True)
    # 初始化AES,引入初始向量
    AESCipher = AES.new(key, AES.MODE_CBC, '1234567890123456')
    # 加密
    cipher = AESCipher.encrypt(str)
    return b2a_hex(cipher)




# CBC模式解密
def decrypt_CBC(str, key):
    # 补全字符串
    key = align(key, True)
    # 初始化AES
    AESCipher = AES.new(key, AES.MODE_CBC, '1234567890123456')
    # 解密
    paint = AESCipher.decrypt(a2b_hex(str))
    return paint


# 输入密码
key = getpass.getpass("Password Please:")


# 尝试读取密文文件,如果密文文件不存在,则不进行解密直接进入加密流程
try:
    fcipher = open("PWencrypt", "r")
    fpaint = open("PW.txt", "w+")
    # 读取密文文件
    fcipherText = fcipher.read()
    # 读取密文和校验哈希值
    cipherText = fcipherText.split(',')[0]
    painhash = fcipherText.split(',')[1]
    # 用密码解密
    painText = decrypt_CBC(cipherText, key)
    # 去除/0
    painText = painText.rstrip('\0')
    # 校验密码
    # 计算本次解密后明文的哈希值
    MD5hash = MD5.new()
    MD5hash.update(painText)
    # 比对哈希值判断密码是否正确
    if painhash != MD5hash.hexdigest():
        print ('wrong password!!')
    else:
        fpaint.write(painText)
        fpaint.close()
        fcipher.close()
        # 打开PW.txt后脚本会被挂起
        print ("Don't Close!!!")
        os.system("notepad PW.txt")
except:
    print("Something wrong when Decrypt!")


# 加密,加密明文文件,写入密文文件并删除明文文件
try:
    fpaint = open("PW.txt", "r")
    # 读取明文文件
    painText = fpaint.read()
    # 如果明文为空,则不执行加密
    if len(painText) > 0:
        fcipher = open("PWencrypt", "w")
        # 加密
        cipherText = encrypt_CBC(painText, key)
        # 计算明文哈希值
        MD5hash = MD5.new()
        MD5hash.update(painText)
        # 将密文和校验码写入密文文件
        cipherText = cipherText + ',' + MD5hash.hexdigest()
        fcipher.write(cipherText)
        fcipher.close()
    fpaint.close()
    # 删除明文文件
    os.remove("PW.txt")
except:
    print("Something wrong when Encrypt!!")


# 延时,方便看控制台的输出
print ("Quit after 3S")
time.sleep(3)


你可以使用python的cryptography库来实现AES加密解密,以及使用zeropadding进行填充。 首先,你需要安装cryptography库。可以使用以下命令来安装: ``` pip install cryptography ``` 接下来,你可以使用以下代码示例来实现AES加密解密,并使用zeropadding进行填充: ```python from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives import padding from cryptography.hazmat.backends import default_backend import os def aes_encrypt(plain_text, key): # 生成一个随机的初始化向量 iv = os.urandom(16) # 使用zeropadding进行填充 padder = padding.ZeroPadding(128).padder() padded_data = padder.update(plain_text) + padder.finalize() # 创建AES加密器对象 cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) encryptor = cipher.encryptor() # 执行加密操作 cipher_text = encryptor.update(padded_data) + encryptor.finalize() return iv + cipher_text def aes_decrypt(cipher_text, key): # 提取初始化向量和密文 iv = cipher_text[:16] cipher_text = cipher_text[16:] # 创建AES解密器对象 cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) decryptor = cipher.decryptor() # 执行解密操作 padded_data = decryptor.update(cipher_text) + decryptor.finalize() # 使用zeropadding进行取消填充 unpadder = padding.ZeroPadding(128).unpadder() plain_text = unpadder.update(padded_data) + unpadder.finalize() return plain_text # 测试代码 key = os.urandom(32) # 生成一个随机密钥 plain_text = b"Hello, AES!" # 原始文本 # 加密 cipher_text = aes_encrypt(plain_text, key) print("Cipher Text: ", cipher_text) # 解密 decrypted_text = aes_decrypt(cipher_text, key) print("Decrypted Text: ", decrypted_text) ``` 这段代码,我们使用AES加密算法和CBC模式来加密解密数据。同时,我们使用了zeropadding进行填充,确保数据长度满足加密算法的要求。需要注意的是,密钥的长度必须符合AES算法的要求(16、24、或32字节)。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值