密码学中的 HMAC 消息认证

LinuxBeginner
立即练习

介绍

在数字通信的世界中,确保消息不仅保持私密,而且在传输过程中未被篡改(完整性)以及确实来自声称的发件人(真实性)至关重要。虽然简单的哈希函数可以检查意外的数据损坏,但它们无法阻止恶意篡改,因为任何人都可以重新计算修改后消息的哈希值。

这就是 HMAC(基于哈希的消息认证码)发挥作用的地方。HMAC 是一种特定类型的消息认证码(MAC),它将加密哈希函数(如 SHA-256)与一个密钥结合起来。只有拥有该密钥的一方才能为给定消息生成和验证 HMAC。这个过程同时提供了数据完整性和真实性。

在这个 Lab 中,你将获得使用 HMAC 的实践经验。你将从理解概念开始,然后使用强大的 openssl 命令行工具来生成密钥和计算 HMAC。最后,你将了解如何在 Python 脚本中实现 HMAC,这是应用程序开发中的一项常见任务。

HMAC 简介

在这一步中,我们将介绍 HMAC 的基本概念及其对安全通信的重要性。

像 SHA-256 这样的标准哈希函数接收输入消息并生成一个固定大小的字符序列,即哈希值或摘要(digest)。即使消息中的单个比特发生变化,生成的哈希值也会完全不同。这对于检查数据完整性非常有用。然而,它不能提供真实性(authenticity)。如果攻击者截获并修改了消息,他们可以简单地为被篡改的消息计算一个新的哈希值并将其发送出去。接收方将无法知道消息已被更改。

HMAC 通过将一个密钥引入哈希过程来解决这个问题。密钥是一种秘密信息,仅在发送方和目标接收方之间共享。

HMAC 的过程大致如下:

  1. 发送方将密钥与消息结合起来。
  2. 对这种组合应用哈希函数(例如 SHA-256)。
  3. 生成的哈希值,现在称为 HMAC,与原始消息一起发送。

当接收方收到消息和 HMAC 时,他们使用自己拥有的密钥执行相同的计算。

  • 如果计算出的 HMAC 与收到的 HMAC 匹配,接收方就知道消息没有被篡改(完整性),并且它来自拥有该密钥的人(真实性)。
  • 如果 HMAC 不匹配,则认为消息已泄露,应予丢弃。

此步骤纯粹是概念性的。在接下来的步骤中,你将把这些理论付诸实践。

生成 HMAC 密钥

在这一步中,你将生成一个安全的随机密钥,这是 HMAC 安全性的基础。一个可预测的密钥将允许攻击者伪造 HMAC。我们将使用 openssl 工具,这是一个多功能的加密命令行实用程序。

我们将使用 openssl rand 命令来生成随机数据。

  • -hex: 此选项告诉 openssl 将随机数据输出为十六进制字符串。
  • 32: 这指定了要生成的随机字节数。32 字节等效于 256 位,这是一个强大且常用的密钥长度,特别是与 SHA-256 哈希算法配合使用时。

为了方便在后续命令中使用该密钥,我们将生成它并将其存储在一个名为 HMAC_KEY 的环境变量中。在你的终端中运行以下命令:

export HMAC_KEY=$(openssl rand -hex 32)

此命令执行 openssl rand -hex 32,并将其输出(十六进制密钥)捕获并分配给 HMAC_KEY 变量。

你可以使用 echo 命令查看刚刚生成的密钥:

echo $HMAC_KEY

你应该会看到一长串十六进制字符。你的密钥将是唯一的。

0db348c78473ce8460416f875cd87239d0f5f66fbe5103ba4b5c84cf2cd76914

现在你已经有了一个密钥,可以准备创建 HMAC 了。

计算 HMAC-SHA256

在这一步中,你将使用生成的密钥为示例消息计算 HMAC。首先,我们创建一个包含消息的文件。

我们将使用 echo 命令创建一个名为 message.txt 的文件。-n 标志很重要,因为它阻止 echo 在字符串末尾添加换行符,这会改变内容,进而改变最终的 HMAC。

echo -n "This is a secret message." > message.txt

现在,有了消息和密钥,我们就可以计算 HMAC 了。我们将使用 openssl dgst 命令,该命令用于计算消息摘要(哈希)。

  • -sha256: 指定我们希望使用 SHA-256 哈希算法。
  • -mac hmac: 指定我们希望使用 HMAC 方法计算消息认证码(MAC)。
  • -macopt hexkey:$HMAC_KEY: 这提供了 MAC 算法的选项。在这里,我们指定密钥是十六进制格式(hexkey),并使用我们之前创建的环境变量 $HMAC_KEY 传递密钥本身。
  • message.txt: 包含要认证的数据的输入文件。

执行以下命令生成 HMAC:

openssl dgst -sha256 -mac hmac -macopt hexkey:$HMAC_KEY message.txt

输出将是使用你的密钥计算出的消息的 HMAC 摘要。输出格式将显示所使用的算法和生成的 HMAC 值。

HMAC-SHA2-256(message.txt)= 214fbb56f716dfe1c2f4a60615a5b901b263fd74c9678b2aef4f01779b34dea8

这个 HMAC 值就是你将与消息一起发送给同样拥有该密钥的接收方的部分。

验证 HMAC 完整性

在这一步中,你将看到 HMAC 验证过程的实际运行情况。你将观察到使用正确密钥如何成功,而使用错误密钥或修改后的消息如何导致失败。

使用正确密钥进行验证

验证不是一个特殊的命令;它只是接收方重新计算 HMAC 并将其与收到的值进行比较的操作。如果你再次运行上一步中的命令,你将得到完全相同的 HMAC 值。这证实了只要密钥和消息没有改变,HMAC 就是一致的。

观察使用错误密钥时的失败情况

现在,让我们通过尝试使用不同的密钥来验证消息,模拟攻击者或错误的配置。首先,生成一个新的“错误”密钥:

export WRONG_KEY=$(openssl rand -hex 32)

现在,尝试使用这个 $WRONG_KEY 为原始的 message.txt 计算 HMAC:

openssl dgst -sha256 -mac hmac -macopt hexkey:$WRONG_KEY message.txt

你将在输出中看到一个新的 HMAC 值:

HMAC-SHA2-256(message.txt)= 781729497e89f3f9cb1d8c7ab632e22753062ac39cd64de0e5b81a45de245d78

请注意,这个 HMAC 与你使用正确 $HMAC_KEY 生成的完全不同。这证明了如果没有正确的密钥,就无法为消息生成有效的 HMAC,从而确保了认证性(authenticity)。

观察消息被修改时的失败情况

我们来看看如果消息本身被篡改会发生什么。我们将对 message.txt 进行轻微修改:

echo -n "This is a tampered message." > message.txt

现在,使用原始的、正确的密钥($HMAC_KEY)再次计算 HMAC:

openssl dgst -sha256 -mac hmac -macopt hexkey:$HMAC_KEY message.txt

同样,你将得到一个完全不同的 HMAC 值。这证明了消息的任何修改,无论多么微小,都将被检测到,从而确保了完整性(integrity)。

在 Python 中实现 HMAC

在这一步中,你将学习如何使用 Python 以编程方式执行 HMAC 操作。这在需要确保消息安全性的 Web 应用程序、API 和其他软件中是一个常见需求。Python 的标准库为此目的提供了 hmachashlib 模块。

我们将编写一个简单的 Python 脚本来计算消息的 HMAC-SHA256。首先,使用 nano 文本编辑器打开文件 hmac_example.py

nano hmac_example.py

现在,将以下 Python 代码复制并粘贴到 nano 编辑器中。此代码导入必要的库,定义密钥和消息,然后计算并打印 HMAC。

注意:在此示例中,我们对密钥和消息进行了硬编码。在实际应用中,密钥应被安全存储和管理。密钥和消息都必须是字节字符串(byte strings),因此我们在它们前面加上了 b 前缀。

import hmac
import hashlib

## 密钥 (必须是 bytes)
## 在实际应用中,应从安全位置获取
key = b'\x0d\xb3\x48\xc7\x84\x73\xce\x84\x60\x41\x6f\x87\x5c\xd8\x72\x39\xd0\xf5\xf6\x6f\xbe\x51\x03\xba\x4b\x5c\x84\xcf\x2c\xd7\x69\x14'

## 要认证的消息 (必须是 bytes)
message = b'This is a secret message.'

## 1. 创建一个新的 HMAC 对象
##    - 传入密钥
##    - 传入消息
##    - 指定哈希算法 (来自 hashlib)
h = hmac.new(key, message, hashlib.sha256)

## 2. 以十六进制格式获取摘要
hex_digest = h.hexdigest()

print("HMAC Digest:")
print(hex_digest)

粘贴代码后,按 Ctrl+O 保存文件,然后按 Enter 确认文件名,最后按 Ctrl+X 退出 nano

现在,从终端运行你的 Python 脚本:

python3 hmac_example.py

脚本将执行并打印计算出的 HMAC 摘要。

HMAC Digest:
214fbb56f716dfe1c2f4a60615a5b901b263fd74c9678b2aef4f01779b34dea8

你现在已经成功在 Python 中实现了 HMAC 生成,这项技能可以直接应用于构建安全的软件。

总结

在这个实验(Lab)中,你获得了关于基于哈希的消息认证码(HMAC)的实践经验,HMAC 是现代密码学中确保数据完整性和认证性的基石。

你了解到:

  • HMAC 将加密哈希函数与一个密钥结合起来,以创建消息认证码。
  • 只有持有密钥的一方才能生成或验证 HMAC,从而防止未经授权的修改和伪造。
  • openssl 命令行工具是一个强大的实用程序,可用于执行加密操作,包括生成随机密钥(openssl rand)和计算 HMAC(openssl dgst)。
  • 消息的任何更改或使用错误的密钥都会导致完全不同的 HMAC,使得篡改易于检测。
  • Python 提供了 hmachashlib 库,以便轻松地将 HMAC 功能集成到你的应用程序中。

通过掌握 HMAC,你已经迈出了构建更安全、更可信赖系统的重要一步。