密码学中的 SHA-256 哈希

LinuxBeginner
立即练习

介绍

欢迎来到密码学的世界!在这个实验(Lab)中,你将亲手实践现代安全中最基本概念之一:密码学哈希。具体来说,我们将使用 SHA-256 算法。

密码学哈希函数是一种数学算法,它接受任意大小的输入(或称“消息”),并返回一个固定大小的字节串。这个输出通常被称为“摘要”(digest)或“哈希值”(hash)。例如,SHA-256 总是产生一个 256 位(32 字节)的哈希值。

这些函数具有几个重要的特性:

  • 确定性(Deterministic):相同的输入将始终产生相同的输出。
  • 单向性(One-way):从哈希值反推出原始输入在计算上是不可行的。
  • 雪崩效应(Avalanche Effect):输入中微小的变化(例如更改单个字符)将产生截然不同的输出哈希值。

在整个实验(Lab)中,你将使用 openssl 命令行工具和一个简单的 Python 脚本来探索这些特性,并理解哈希在现实场景中的应用,例如验证文件完整性和保护密码。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 93%。获得了学习者 100% 的好评率。

哈希函数特性

在这一步中,你将使用 openssl 命令行工具来探索哈希函数的两个核心特性:确定性(deterministic)和雪崩效应(avalanche effect)。如果一个函数对于相同的输入总是产生相同的输出,那么它就是确定性的。雪崩效应意味着输入中微小的变化会导致输出哈希值完全不同。

首先,让我们为字符串 "hello" 生成一个 SHA-256 哈希值。我们将使用 echo 命令将该字符串传递给 openssl

echo -n "hello" | openssl dgst -sha256

echo 中的 -n 标志很重要;它防止 echo 在字符串末尾添加一个换行符,否则会改变最终的哈希值。

你应该会看到类似以下的输出:

SHA2-256(stdin)= 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

现在,我们再次运行完全相同的命令来演示确定性。

echo -n "hello" | openssl dgst -sha256

注意输出是完全相同的。这证实了对于相同的输入,SHA-256 哈希值总是相同的。

SHA2-256(stdin)= 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

接下来,我们演示雪崩效应。我们将对输入字符串做一个非常小的改动——将 "hello" 改为 "Hello"(首字母大写)。

echo -n "Hello" | openssl dgst -sha256

观察新的哈希值:

SHA2-256(stdin)= 185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969

将此哈希值与 "hello" 的哈希值进行比较。尽管输入的改变非常微小(仅改变了第一个字母的大小写),但产生的哈希值却完全不同。这就是雪崩效应的体现,也是安全哈希函数的一个关键特性。

计算文件哈希值

在这一步中,你将计算一个文本文件的 SHA-256 哈希值。这是验证文件完整性的一种常见做法。当你从互联网下载文件时,网站通常会提供一个校验和(checksum,即哈希值),以便你可以验证文件在下载过程中是否损坏或被篡改。

本实验(Lab)的设置脚本已经在你的当前目录(~/project)中创建了一个名为 message.txt 的文件。首先,让我们使用 cat 命令查看其内容。

cat message.txt

你将看到以下内容:

This is a secret message.

现在,让我们计算该文件的 SHA-256 哈希值。语法与你之前使用的类似,但这次不是通过管道(pipe)输入,而是将文件名作为参数提供给 openssl dgst 命令。

openssl dgst -sha256 message.txt

该命令将处理文件并打印其 SHA-256 哈希值。输出将如下所示:

SHA2-256(message.txt)= 6432f513cfd40d47c8584494c0524468257e50dc1a0422f73becac85189543f8

这个哈希值充当了 message.txt 当前内容的唯一数字指纹。正如你将在后续步骤中看到的,如果有人更改了文件中的哪怕一个字符,哈希值也会完全改变。

生成多个哈希值

在这一步中,你将练习为不同的字符串输入生成 SHA-256 哈希值。这将有助于巩固你对任何唯一输入都会产生唯一哈希值的理解。我们将继续使用 echo -n 命令通过管道(pipe)传递给 openssl,以确保我们只对字符串本身进行哈希计算,不包含任何额外的字符。

首先,让我们为字符串 "labex" 生成哈希值。

echo -n "labex" | openssl dgst -sha256

输出将是 "labex" 的 SHA-256 哈希值:

SHA2-256(stdin)= 679e75b679886c5eaf8aaab88ddfc0181e6dae14cff346db8ba398bd7b2e31fe

接下来,让我们尝试一个不同的字符串 "crypto",看看它独特的哈希值。

echo -n "crypto" | openssl dgst -sha256

正如预期的那样,这会产生一个完全不同的哈希值:

SHA2-256(stdin)= da2f073e06f78938166f247273729dfe465bf7e46105c13ce7cc651047bf0ca4

这个实验证明了每一段不同的数据,无论大小如何,都有其独特的哈希值。这个特性是哈希值在数据验证、区块链技术和数字签名中应用的基础。

演示抗碰撞性

在这一步中,你将通过轻微修改 message.txt 文件并观察其哈希值如何变化,来直接观察雪崩效应(avalanche effect)和抗碰撞性(collision resistance)的概念。抗碰撞性意味着找到两个能产生相同哈希值的不同输入是极其困难的。

首先,让我们重新计算原始 message.txt 文件的哈希值,以便我们能清晰地记住它。

openssl dgst -sha256 message.txt

你应该会再次看到原始的哈希值:

SHA2-256(message.txt)= 6432f513cfd40d47c8584494c0524468257e50dc1a0422f73becac85189543f8

现在,让我们对文件进行一个非常小的更改。我们将在文件末尾追加一个句点(.)。我们可以使用 echo 命令和 >> 重定向操作符轻松完成此操作,该操作符会将输出追加到文件中。

echo "." >> message.txt

你可以通过再次查看文件内容来验证更改是否已完成。

cat message.txt

你将在末尾看到那个句点:

This is a secret message.
.

现在,让我们对修改后的文件重新计算哈希值。

openssl dgst -sha256 message.txt

新的哈希值将是:

SHA2-256(message.txt)= 4106e1c985a4ee1754fff76b8bffda0c4844679885cb70758f24cd43e771daac

将这个新哈希值与原始哈希值进行比较。它们是完全不同的。这个有力的演示表明,即使对文件进行一个字符的更改,也会导致哈希值发生根本性的变化,从而可以轻松检测到任何形式的篡改。

创建密码哈希

在这一步中,你将超越命令行,编写一个简单的 Python 脚本来计算密码的哈希值。以明文形式存储密码是一个主要的安全性漏洞。标准做法是存储密码的哈希值。当用户尝试登录时,系统会对他们输入的密码进行哈希计算,并与存储的哈希值进行比较。

设置脚本已经创建了一个名为 hash_password.py 的空文件。你现在将使用 nano 文本编辑器向其中添加代码。

使用 nano 打开文件:

nano hash_password.py

现在,将以下 Python 代码复制并粘贴到 nano 编辑器中:

import hashlib

## 我们想要计算哈希的密码
password = "mysecretpassword"

## Python 中的哈希函数处理的是字节(bytes),而不是字符串(string)。
## 我们必须首先使用 UTF-8 将字符串编码为字节。
password_bytes = password.encode('utf-8')

## 创建一个新的 SHA-256 哈希对象。
sha256_hash = hashlib.sha256(password_bytes)

## 获取哈希值的十六进制表示形式。
hex_digest = sha256_hash.hexdigest()

print(f"The password is: {password}")
print(f"The SHA-256 hash is: {hex_digest}")

该脚本执行以下操作:

  1. 导入 hashlib 库,它提供了各种哈希算法。
  2. 定义一个密码字符串。
  3. 使用 .encode('utf-8') 将字符串编码为字节。这是一个关键步骤,因为哈希函数操作的是字节。
  4. 创建一个 SHA-256 哈希对象,并用密码字节更新它。
  5. 使用 .hexdigest() 以可读的十六进制格式检索最终的哈希值。

粘贴代码后,保存文件并按 Ctrl+X,然后按 Y,最后按 Enter 退出 nano

最后,从终端运行你的 Python 脚本:

python3 hash_password.py

脚本将执行并打印密码及其对应的 SHA-256 哈希值:

The password is: mysecretpassword
The SHA-256 hash is: 94aefb8be78b2b7c344d11d1ba8a79ef087eceb19150881f69460b8772753263

你已成功使用 Python 执行了加密哈希计算,这是安全应用程序开发中必不可少的一项技能。

总结

恭喜你完成了这个实验(Lab)!你获得了关于 SHA-256 加密哈希函数的实际操作经验。

在这个实验(Lab)中,你学习了:

  • 哈希函数的核心特性:它们是确定性的(deterministic)、单向的(one-way),并表现出雪崩效应(avalanche effect)。
  • 如何在 Linux 环境中使用 openssl dgst -sha256 命令来计算字符串和文件的哈希值。
  • 哈希在验证文件完整性(file integrity)和检测篡改方面的重要性。
  • 如何使用 Python 的 hashlib 库以编程方式生成 SHA-256 哈希值,这是密码安全(password security)中的常见任务。

哈希是现代网络安全(cybersecurity)的基石。你在这里练习的技能对于理解更高级的主题至关重要,例如数字签名(digital signatures)、消息认证码(MACs)和区块链技术。作为下一步,你可以研究“密码加盐”(salting passwords),这在哈希的基础上增加了另一层安全防护。