053. 编写一个函数,实现简单的文件加密和解密功能

以下是一个简单的Python函数,用于实现文件的加密和解密功能。这里使用了对称加密算法(如AES),因为它是实现文件加密的常用方法之一。我们将使用cryptography库来完成这个任务。

安装依赖

首先,确保安装了cryptography库。如果尚未安装,可以通过以下命令安装:

pip install cryptography

文件加密和解密代码

以下代码提供了一个简单的文件加密和解密功能:

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
import os

def generate_key(password: str, salt: bytes) -> bytes:
    """
    使用密码和盐值生成密钥
    :param password: 用户提供的密码
    :param salt: 盐值
    :return: 生成的密钥
    """
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        length=32,  # AES-256需要32字节的密钥
        salt=salt,
        iterations=100000,
        backend=default_backend()
    )
    return kdf.derive(password.encode())

def encrypt_file(input_file: str, output_file: str, password: str):
    """
    加密文件
    :param input_file: 输入文件路径
    :param output_file: 输出文件路径
    :param password: 加密密码
    """
    # 生成随机盐值
    salt = os.urandom(16)
    # 生成密钥
    key = generate_key(password, salt)
    # 生成随机IV(初始化向量)
    iv = os.urandom(16)

    # 创建AES加密器
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
    encryptor = cipher.encryptor()

    # 读取输入文件
    with open(input_file, "rb") as f:
        data = f.read()

    # 对数据进行填充
    padder = padding.PKCS7(algorithms.AES.block_size).padder()
    padded_data = padder.update(data) + padder.finalize()

    # 加密数据
    encrypted_data = encryptor.update(padded_data) + encryptor.finalize()

    # 将盐值、IV和加密数据写入输出文件
    with open(output_file, "wb") as f:
        f.write(salt)
        f.write(iv)
        f.write(encrypted_data)

    print(f"文件已加密并保存到 {output_file}")

def decrypt_file(input_file: str, output_file: str, password: str):
    """
    解密文件
    :param input_file: 输入文件路径
    :param output_file: 输出文件路径
    :param password: 解密密码
    """
    # 读取输入文件
    with open(input_file, "rb") as f:
        salt = f.read(16)  # 读取盐值
        iv = f.read(16)    # 读取IV
        encrypted_data = f.read()  # 读取加密数据

    # 生成密钥
    key = generate_key(password, salt)

    # 创建AES解密器
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
    decryptor = cipher.decryptor()

    # 解密数据
    decrypted_padded_data = decryptor.update(encrypted_data) + decryptor.finalize()

    # 移除填充
    unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
    data = unpadder.update(decrypted_padded_data) + unpadder.finalize()

    # 将解密数据写入输出文件
    with open(output_file, "wb") as f:
        f.write(data)

    print(f"文件已解密并保存到 {output_file}")

# 示例用法
if __name__ == "__main__":
    password = "my_secure_password"
    encrypt_file("example.txt", "example.encrypted", password)
    decrypt_file("example.encrypted", "example_decrypted.txt", password)

代码说明:

密钥生成

  • 使用PBKDF2HMAC算法从用户提供的密码和随机生成的盐值中派生出密钥。

  • 盐值用于增加密码的安全性,防止彩虹表攻击。

加密过程

  • 使用AES算法(CBC模式)进行加密。

  • 数据在加密前需要进行填充(使用PKCS7填充),以确保数据长度符合AES块大小的要求。

  • 加密后的文件包含盐值、IV和加密数据。

解密过程

  • 从加密文件中读取盐值和IV,重新生成密钥。

  • 解密数据后,移除填充,恢复原始数据。

文件操作

  • 输入文件被加密后保存为一个新的文件。

  • 加密文件可以被解密并保存为另一个文件。

示例运行:

假设有一个文件example.txt,内容为Hello, World!。运行代码后:

  • example.encrypted将包含加密后的数据。

  • example_decrypted.txt将包含解密后的原始数据。

注意事项:

  • 请确保密码足够复杂,以保证加密的安全性。

  • 由于加密文件中包含盐值和IV,因此加密文件的大小会比原始文件稍大。

  • 如果密码错误,解密过程可能会失败或产生错误的数据。

视频讲解

BiliBili: 视睿网络-哔哩哔哩视频 (bilibili.com)