Python cryptography.fernet 实现文件加密与解密教程


本教程详细介绍了如何使用 python 的 cryptography 库中的 fernet 模块实现文件的加密与解密操作。文章将涵盖 fernet 密钥的生成、管理与重用,以及如何在文件中安全地执行加密和解密过程,并强调密钥安全存储的重要性,确保数据机密性。

1. 引言:cryptography.fernet 简介

在信息安全日益重要的今天,对敏感数据进行加密是保护其机密性的基本手段。Python 的 cryptography 库提供了一套强大且易于使用的加密工具,其中 fernet 模块是实现对称加密的理想选择。Fernet 是一种基于 AES 算法的对称加密方案,它确保了消息的认证性、完整性和机密性,并且易于集成到应用程序中。

Fernet 的核心原理在于使用一个共享的密钥进行数据的加密和解密。这意味着,加密数据所使用的密钥必须与解密数据所使用的密钥完全一致。如果密钥丢失或泄露,数据将无法恢复或面临被未授权访问的风险。

2. 核心概念:密钥生成与 Fernet 实例

在使用 Fernet 进行文件加密和解密之前,我们需要理解其两个关键概念:密钥生成和 Fernet 实例的创建。

2.1 密钥生成

Fernet 密钥是一个32字节的 URL 安全的 Base64 编码字符串。它是对称加密的基础,必须严格保密。通过 Fernet.generate_key() 方法可以生成一个全新的密钥。

from cryptography.fernet import Fernet

# 生成一个 Fernet 密钥
key = Fernet.generate_key()
print(f"生成的 Fernet 密钥 (Base64编码): {key.decode()}")

重要提示: 每次调用 Fernet.generate_key() 都会生成一个全新且不同的密钥。对于需要持久化加密的数据,您必须将生成的密钥保存下来并在后续的解密操作中重用它。

2.2 Fernet 实例创建

拥有密钥后,您可以使用它来创建一个 Fernet 实例。这个实例将用于执行实际的加密和解密操作。

# 使用生成的密钥创建 Fernet 实例
cipher = Fernet(key)

3. 文件加密与解密操作

Fernet 实例提供了 encrypt() 和 decrypt() 方法来处理字节数据。对于文件操作,我们通常需要以二进制模式读取文件内容,进行加密或解密,然后再将处理后的内容写入文件。

3.1 原地加密与解密实现

以下代码示例展示了如何在一个函数中实现文件的原地(in-place)加密和解密。这意味着文件内容会被直接替换为加密或解密后的数据。

import os
from cryptography.fernet import Fernet
from cryptography.fernet import InvalidToken # 用于处理解密失败异常

def process_file_in_place(filename: str, cipher: Fernet, action: str, debug: bool = False):
    """
    对文件内容进行原地加密或解密。

    Args:
        filename (str): 要处理的文件路径。
        cipher (Fernet): Fernet 加密实例。
        action (str): 操作类型,可以是 "encrypt" 或 "decrypt"。
        debug (bool): 是否在加密后打印加密内容。
    """
    # 以二进制读写模式打开文件 (rb+ 允许读写,文件指针初始在开头)
    with open(filename, "rb+") as data_file:
        content = data_file.read() # 读取文件所有内容

        # 根据指定操作执行加密或解密
        processed_content = b""
        if action == "encrypt":
            processed_content = cipher.encrypt(content)
            if debug:
                print(f"加密后的内容 (bytes): {processed_content}")
        elif action == "decrypt":
            try:
                processed_content = cipher.decrypt(content)
                if debug:
                    print(f"解密后的内容 (bytes): {processed_content}")
            except InvalidToken:
                print(f"错误: 无法解密文件 '{filename}'。可能是密钥不匹配或数据已损坏。")
                return # 解密失败,退出函数
        else:
            raise ValueError("操作类型必须是 'encrypt' 或 'decrypt'")

        # 将文件指针移到文件开头
        data_file.seek(0)
        # 写入处理后的内容
        data_file.write(processed_content)
        # 如果新内容比旧内容短,则截断文件,确保文件大小正确
        data_file.truncate()

if __name__ == "__main__":
    test_filename = "example_data.txt"
    original_text = "Hello, world! This is a secret message that needs to be protected."

    # 1. 创建一个原始的明文文件
    with open(test_filename, "w", encoding="utf-8") as f:
        f.write(original_text)
    print(f"原始文件 '{test_filename}' 内容: {original_text}")

    # 2. 生成一个 Fernet 密钥并创建实例
    # 注意:此密钥仅用于本次运行,实际应用中需要持久化存储
    key_for_example = Fernet.generate_key()
    cipher_for_example = Fernet(key_for_example)
    print(f"生成的 Fernet 密钥 (Base64编码): {key_for_example.decode()}")

    # 3. 加密文件
    print("\n--- 执行加密 ---")
    process_file_in_place(test_filename, cipher_for_example, "encrypt", debug=True)
    with open(test_filename, "rb") as f:
        print(f"加密后文件 '{test_filename}' 的二进制内容 (部分): {f.read()[:50]}...") # 只打印前50字节

    # 4. 解密文件
    print("\n--- 执行解密 ---")
    process_file_in_place(test_filename, cipher_for_example, "decrypt")
    with open(test_filename, "r", encoding="utf-8") as f: # 解密后内容可按文本读取
        decrypted_text = f.read()
    print(f"解密后文件 '{test_filename}' 内容: {decrypted_text}")

    # 5. 验证解密内容是否与原始内容匹配
    assert decrypted_text == original_text
    print("\n验证成功:解密内容与原始内容一致。")

    # 清理测试文件
    if os.path.exists(test_filename):
        os.remove(test_filename)

代码解析:

  • open(filename, "rb+"):以二进制读写模式打开文件。r 表示读,b 表示二进制,+ 表示同时允许写操作。文件指针初始位于文件开头。
  • data_file.read():读取文件的全部内容。对于大文件,可能需要分块读取和处理。
  • cipher.encrypt(content) / cipher.decrypt(content):执行加密或解密操作。这些方法接受并返回字节串(bytes)。
  • data_file.seek(0):将文件指针重新定位到文件开头,以便从头开始写入新内容。
  • data_file.write(processed_content):将加密或解密后的内容写入文件。
  • data_file.truncate():非常重要! 如果新写入的内容比原始内容短,文件末尾可能会保留旧数据。truncate() 方法会将文件截断到当前文件指针位置,从而清除多余的旧数据。

4. 密钥管理:持久化与重用

在实际应用中,每次运行程序都生成新密钥是不可行的。为了能够在不同时间点或不同程序实例之间加密和解密数据,密钥必须被持久化存储并重用。

4.1 正确的密钥持久化方法

正确的密钥持久化


# python  # 编码  # 字节  # 工具  # ai  # 敏感数据  # 持久化存储  # crypto  # elif 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化76771 】 【 技术知识130152 】 【 IDC云计算60162 】 【 营销推广131313 】 【 AI优化88182 】 【 百度推广37138 】 【 网站推荐60173 】 【 精选阅读31334


相关推荐: Win10系统怎么查看网络连接状态_Windows10网络和共享中心  Win11触摸板没反应怎么办_开启Win11笔记本触摸板手势教程【步骤】  c++20的std::format怎么用 比printf更安全高效的格式化方法【详解】  如何在Golang中使用replace替换模块_指定本地或远程路径  c++ std::future和std::promise c++线程间通信【教程】  如何在Golang中实现微服务服务拆分_Golang微服务拆分与接口管理方法  Win11时间格式怎么改成12小时制 Win11时间格式切换教程【步骤】  Mac的“预览”如何合并多个PDF_Mac文件处理技巧【效率】  Win11怎么开启窗口对齐助手_Windows11系统多任务处理设置  Windows蓝屏BAD_POOL_HEADER故障详解_蓝屏池损坏错误修复指南  Win11怎么开启移动热点_Windows11共享网络给手机设置教程  php下载安装包怎么选_threadsafe与nts版本差异【解答】  c++怎么实现高并发下的无锁队列_c++ std::atomic原子变量与CAS操作【详解】  C#如何使用XPathNavigator高效查询XML  Mac如何整理桌面文件_Mac使用堆栈功能一键整理  php485支持哪些操作系统_php485跨系统支持情况介绍【解答】  如何使用Golang构建简易投票统计功能_Golang投票数据汇总与展示示例  Win11任务栏颜色怎么改_Win11自定义任务栏配色设置【美化】  PhpStorm怎么调试PHP代码_PhpStorm断点设置与调试启动步骤【指南】  MAC怎么设置程序窗口永远最前_MAC窗口置顶插件安装与快捷设置【方法】  Win11怎样安装剪映专业版_Win11安装剪映教程【步骤】  如何在Golang中编写异步函数测试_Golang异步操作测试策略  php命令行怎么运行_通过CLI模式执行PHP脚本的步骤【说明】  Win11怎么设置环境变量_Win11配置Path路径变量【详解】  XML的“混合内容”是什么 怎么用DTD或XSD定义  Go 中 defer 在 goroutine 内部不生效的原因与执行时机详解  Win11任务栏天气怎么关闭 Win11隐藏天气小组件图标【设置】  Go 中 := 短变量声明的类型推导机制详解  c# Task.ConfigureAwait(true) 在什么场景下是必须的  MAC如何快速搜索大文件_MAC磁盘空间分析与冗余数据清理【方法】  Windows的便笺功能如何使用?(桌面备忘技巧)  c++如何用AFL++进行模糊测试 c++ Fuzzing入门【安全】  如何使用Golang实现跨域请求支持_Golang CORS配置与处理方法  Windows如何使用注册表查找和删除项?(regedit教程)  php中::能访问全局变量吗_全局作用域与类作用域区分【操作】  c++中explicit(bool)的用法 c++条件性explicit【C++20】  PyTorch DDP 多进程训练在 Kaggle 笔记本中的正确启动方式  Win11怎样安装网易云音乐_Win11安装网易云教程【步骤】  Win11怎么清理C盘虚拟内存_Win11清理虚拟内存设置【教程】  Win11怎么清理C盘下载文件夹_Win11清理下载文件夹技巧【教程】  Windows10无法连接到Internet_Win10网络重置命令详解  Win11怎么关闭定位服务 Win11禁止应用获取位置信息【隐私】  Win11怎么关闭定位服务_保护Win11位置隐私设置指南【详解】  如何使用Golang log设置日志输出格式_Golang log日志格式示例  Win11蓝牙开关不见了怎么办_Win11蓝牙驱动丢失修复教程【方法】  Windows11怎么用“记事本”自动换行与编码 Windows11记事本启用自动换行选择UTF-8编码避免乱码兼容多语言【教程】  Win11怎么关闭自动调节屏幕亮度_Windows11禁用内容自适应亮度控制  Win11怎么设置默认邮件应用_Windows11应用关联Mail设置  Win11如何更改任务栏颜色 Win11自定义任务栏背景色【美化】  Win11开机速度慢怎么优化_Win11系统启动加速设置指南【方法】 

 2025-11-10

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

致胜网络推广营销网


致胜网络推广营销网

致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 915688610

 17370845950

 915688610@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.