Python 中的加密包

2024年8月29日 | 阅读 7 分钟

在接下来的教程中,我们将学习 Python 编程语言中用于加密的包,并通过不同的示例进行说明。

那么,让我们开始吧。

理解加密包

加密是在数据从一台计算机传输到另一台计算机时保护有用信息或在计算机上存储数据的实践。加密涉及将明文加密为密文,并将密文解密为明文。Python 支持 cryptography 包,该包允许我们加密和解密数据。cryptography 包的 fernet 模块具有核心功能,可通过 encrypt()decrypt() 方法分别生成密钥、将明文加密为密文以及将密文解密为明文。

如何安装 Python cryptography 包?

要安装 Python 包,我们需要 'pip',这是一个用于管理软件包的框架,可以从受信任的公共存储库安装模块。一旦我们有了 'pip',我们就可以在 Windows 命令提示符 (CMD) 或终端中使用如下命令安装 cryptography 库。

语法

验证安装

模块安装完成后,我们可以通过创建一个空的 Python 程序文件并写入如下 import 语句来验证它:

文件:verify.py

现在,保存上述文件并在终端中使用以下命令执行它:

语法

如果上述 Python 程序文件没有返回任何错误,则表示模块已正确安装。但是,如果出现异常,请尝试重新安装该库,并建议参考该库的官方文档。

理解 Fernet (对称加密)

Fernet 是对称(也称为“密钥”)认证加密的实现。Fernet 保证我们无法在没有密钥的情况下进一步操纵或读取使用它加密的数据。Fernet 还支持通过 MultiFernet 实现密钥轮换。

现在让我们通过一些 Fernet 类及其方法来详细了解加密的概念。

class cryptography.fernet.Fernet(key)

此类提供加密和解密功能。此类接受 key 作为输入参数。此 key 参数是 URL 安全的 base64 编码的 32 字节密钥。必须将其保密。拥有此密钥的任何人都可以创建和读取消息。

现在,在我们查看 Fernet 类的一些方法之前,让我们看一个简单的示例来演示其用法。

示例 1

输出

Encrypted Message:  b'gAAAAABiZAj1lcmLXPbRJng9wxgowFB731MLUFu-nstC8Sdnzn24y_lhu_h1QmR5N68d_DdpH8mIGNF6Y-7PgSmgUYkxwouw7R80lWk1k9IPp7MiKtv5O3OWmG6gk4rK4k5iNzE5sPd-L_ns0Zn8nmG2Zr--QDUi2Q=='

Decrypted Message:  b'Hello, Students! Welcome to Python tutorial at Javatpoint.com'

说明

在上面的代码片段中,我们从 cryptography 包的 fernet 模块导入了 Fernet 类。然后,我们使用名为 generate_key() 的类方法来生成密钥。然后,我们使用该密钥通过 encrypt() 方法将明文转换为密文,并打印加密的消息。然后,我们再次使用该密钥通过 decrypt() 方法将密文转换为明文,并为用户打印解密的消息。

我们可以看到解密后的输出在原始消息前面有一个 'b',这表示 byte 格式。但是,在打印原始消息时,我们可以使用 decode() 方法将其删除。让我们看一个演示 decode() 方法实现的以下示例。

示例 2

输出

Encrypted Message:  b'gAAAAABiZrxrUg61HeVbOke04ftXTKnl17z3e8LjHfLMiCPQ2ZQ4Hz43bL1twbcS4cXcsclsUZKT-q3oyWVecKH39hgEgh1GQaB4E1gkMJr1Q6LbC93N97yeFq0kME_ttc-BVrXCGZBzNPRdW1zl45v7ow-d893kkMiab-y1OSMjbVFL9nK_iZE='

Decrypted Message:  This example demonstrates the implementation of the decode() method.

说明

在上面的代码片段中,我们从 cryptography 包的 fernet 模块导入了 Fernet 类。然后,我们使用名为 generate_key() 的类方法来生成密钥。然后,我们使用该密钥通过 encrypt() 方法将明文转换为密文,并打印加密的消息。然后,我们再次使用该密钥通过 decrypt() 方法将密文转换为明文。最后,我们使用 decode() 方法将消息从 byte 转换为 string,并为用户打印。

现在让我们了解我们之前使用的方法的工作原理。

  1. generate_key(): 此方法属于 Fernet 类,用于生成新的 fernet 密钥。必须妥善保管密钥,因为它是解密密文的重要组成部分。如果密钥丢失,用户将无法再解密消息。此外,如果入侵者或黑客获得了密钥,他们就可以读取和伪造数据。
  2. encrypt(data): 此方法允许我们加密作为参数传递给它的数据。此加密的输出称为“Fernet token”,它本质上是密文。加密的 token 还包含生成它的时间戳。如果数据不是字节格式,encrypt 方法会引发异常。
    参数
    1. data (bytes)- 此参数包含我们想要加密的消息。
    返回值:安全的消息或密文,没有密钥无法读取或更改。这被视为“Fernet token”。它是 URL 安全的 base64 编码。
    引发:TypeError - 如果 data 不是 bytes,则引发此异常。
  3. encrypt_at_time(data, current_time): 此方法用于通过显式传递的当前时间来加密作为参数传递给它的数据。此方法的工作方式与我们之前看到的 encrypt() 方法类似。
    此方法背后的思想是让客户端代码能够测试 token 的过期时间。由于我们可以以不安全的方式使用此方法,因此我们必须确保在测试之外传递为 current_time 的时间是正确的,即 int(time.time())
    参数
    1. current_time (int)- 此参数表示当前时间。
    注意:encrypt() 类似,加密的消息包含明文的时间戳;在这种情况下,时间戳是 current_time 参数的值。
  4. decrypt(token, ttl = None): 此方法用于解密作为参数传递给它的 Fernet token。如果 token 成功解密,我们将获得原始明文。否则将引发异常。立即使用此数据是安全的,因为 Fernet 在返回数据之前会验证数据未被篡改。
    参数
    1. token (bytes) - 此参数是 Fernet token。这是调用 encrypt() 的结果。
    2. ttl (int) - 这是一个可选参数,包含消息可以有效的秒数。如果消息比 ttl 秒(从创建时算起)旧,则会引发异常。如果未提供 ttl 参数(或为 None),则不考虑消息的年龄。
    返回值:原始明文。
    引发:此方法引发以下异常
    • cryptography.fernet.InvalidToken - 如果 token 无效,则引发此异常。token 可能无效的原因有多种:它比 ttl 旧、格式错误或不包含有效签名。
    • TypeError - 如果 token 不是 bytes,则引发此异常。
  5. decrypt_at_time(token, ttl, current_time): 此方法用于通过显式传递的当前时间来解密 token。此方法的工作方式与我们之前看到的 decrypt() 方法类似。
    此方法背后的思想是让客户端代码能够测试 token 的过期时间。由于我们可以以不安全的方式使用此方法,因此我们必须确保在测试之外传递给它的 current_time 参数的时间是正确的,即 int(time.time())
    参数
    1. current_time (int) - 此参数表示当前时间。
  6. extract_timestamp(token): 此方法用于提取我们传递给它的 token 的时间戳。然后,调用者可以决定 token 是否即将过期,例如,发布新 token。
    参数
    1. token (bytes) - 此参数是 fernet token。这是调用 encrypt() 的结果。
    返回值:token 的 UNIX 时间戳。
    引发:此方法引发以下异常
    • cryptography.fernet.InvalidToken - 如果 token 的签名无效,则引发此异常。
    • TypeError - 如果 token 不是 bytes,则引发此异常。