哈希与加密?什么是哈希值,什么是哈希加密,什么是哈希解密

2025-03-09 10:04:44

哈希与加密

有一个常见的误解,认为哈希和加密是一回事。他们不是。 哈希是不可逆的。以以下示例为例:

$ echo -n Password123 | md5sum
42f749ade7f9e195bf475f37a44cafcb -

我们将字符串 “Password123” 传递给 MD5 算法 (algo),它进行数学运算,并返回 生成的十六进制编码哈希。获得相同哈希输出值的唯一方法是将 algo 原始输入。有冲突,但我们可以稍后讨论。

大多数哈希算法的输出十六进制编码的固定长度的二进制字符串。其他人,比如这个例子, 使用 base64 编码的字符串作为输出。请注意,长度始终相同:

{SHA}uNF8eZRJ8jmr8WTjyocRJPVpe7w=
{SHA}lqdu/Zr6o2dgIER8Up1/7lcUtgw=
{SHA}qYUOwLMlDEuukA5HCT4LR1kQzco=
{SHA}MXZBCpyWJ7TTs1w2kgGJslwNwTg=
{SHA}2sAPLaUh9Mz0bI+XxKEg7qyABe8=

TL;博士

加密是可逆的,哈希不是


我不想过多地谈论加密(因为那些东西是给书的),但重要的是要 能够区分哈希字符串和加密字符串。加密通常会填充字符串 在加密发生之前满足特定长度。它还需要密钥(或密码)才能解密。 如果正在使用加密密码,则 string 将根据输入的长度而变化。如果你看到一堆密文密码,该 的长度各不相同,您可能正在处理加密而不是哈希。AES-256-CBC 示例 加密字符串和关联的纯文本(密钥为“ASDF”):

foobar             | U2FsdGVkX19G+KtytNHdj6yH2AVvX26pEmtunS/PRnU=
foobarfoobar       | U2FsdGVkX18sPpIvN6nVh68lOUCcb3gR2fKbCCnBxog=
foobarfoobarfoobar | U2FsdGVkX1/EOnUt57TCW4Rh0EdNnWX+lDatuQv2xEXXeAeowW0XG/EXJUe9aSUz

$ cat encrypted_passwords
U2FsdGVkX19G+KtytNHdj6yH2AVvX26pEmtunS/PRnU=
U2FsdGVkX18sPpIvN6nVh68lOUCcb3gR2fKbCCnBxog=
U2FsdGVkX1/EOnUt57TCW4Rh0EdNnWX+lDatuQv2xEXXeAeowW0XG/EXJUe9aSUz

$ for i in `cat encrypted_passwords`; do echo $i | openssl enc -base64 -d -aes-256-cbc -pass pass:asdf; echo; done
foobar
foobarfoobar
foobarfoobarfoobar

现在你可能会想:你可能是对的。然而,关键材料必须可供系统访问 意味着本质上是一个纯文本主密码位于某个地方 - 无论是作为 RSA 密钥还是密码 或文件中、嵌入在数据库中、在应用程序中硬编码或内存中某个位置的密码。pfft, no one's going use asdf as the key to encrypt their users' passwords

使用 MD5 的相同字符串:

foobar             | 3858f62230ac3c915f300c664312c63f
foobarfoobar       | 59faa421729e846dd800dce59943bfc0
foobarfoobarfoobar | 1352aadab322d1a033c27964be0965db

哈希密码远非完美,事实上它有点糟糕,但它比加密要糟糕 因为它试图实现什么。用户选择绝对最低要求的频率高于 not,还可以在多个站点上使用它。很多 “hacks” 实际上只不过是凭证重用 攻击。如果最初的妥协是使用加密,那么攻击者必须付出的唯一努力 in 是查找解密所有密码的密钥。对于哈希,他们至少需要付出努力 破解它们。当与 sha512crypt、bcrypt、scrypt 或 argon2 等现代算法一起使用时,哈希值 可能需要付出很大的努力才能破解。



腌制

加盐是在哈希之前向密码添加一个字符串。每个哈希的盐应该是唯一的, 通常是随机选择的,因为重点是让相同的明文 “password” 哈希值 每次的值都不同。这使得密码破解者的生活变得困难,因为为了 检查 1,000 个用户中的每一个用户的“密码”一词,每个用户都有一个唯一的 SALT,他们必须这样做 作品 1,000 次 - 每个用户/盐一次。这也意味着他们无法有效地使用 预编译的字典或 rainbow 表(通常...),因为它们需要一个自定义的 每盐。

网站有时会把这搞砸,并为所有用户使用通用盐;这违背了目的。

以下是加盐的 SHA1 哈希值:


b353977827f67a4ae0318f3a9447fae1c13d9d90:b8d18ca
|______________________________________|||_____|
                  hash                  |  salt
                                        |
                                    separator

此哈希的明文是 “password”。它的盐值为 “b8d18ca”,并使用 SHA1($salt.$pass) 的 API 中。这意味着该算法获取了 password 的明文,生成了 salt, 并将其添加到明文前面。当网站或应用程序尝试验证您的密码时 将来,它会将您的明文密码作为输入,读取存储的 Hash 中的 salt 值, 将其添加到您选择的密码前面,并将生成的哈希值与存储的哈希值进行比较。裂化 如果不知道它的一部分是盐,哈希将产生以下纯文本:

b8d18capassword

由于算法作了纯文本输入,因此 salt 和生成的哈希值可以保留 对用户透明。在裂解时,如果算法是盐的,我们需要知道盐,这样我们才能 在生成候选 plaintext 时提供它。

如果实施得当,盐渍会使开裂更加耗时。使用随机盐, 您强制 Cracker 浪费时间尝试破解 salt 不匹配的哈希值。这大致 完成 device_speed / number_of_salts 所需的努力,因为我们需要生成一个候选人 对于每种盐。如果盐是静态的,那么数学运算是相同的......speed_of_device / 1.另一种查看方式 这:

Our GTX 980 cracks SHA1($salt.$pass) at 3576.8 MH/s or 3.5 billion candidates per second
Our hashlist contains 1000 unique salts

3,500,000,000 / 1000 = 3,500,000 candidates per second

这慢了三个数量级,损失了 99.9%。使用静态盐时,它看起来像这样:

Our GTX 980 cracks SHA1($salt.$pass) at 3576.8 MH/s or 3.5 billion candidates per second
Our hashlist contains 1 unique salt
              
3,500,000,000 / 1 = 3,500,000,000 candidates per second

如果这没有意义,请继续阅读,我们稍后会有漂亮的图表......


迭 代

与简单地“hash this plaintext”相比,另一个常见的改进是,“hash this plaintext,然后 hash 那个结果,然后 hash 那个结果“重复了数千次。这样就可以尝试单个 candidate password 时,密码破解程序必须进行数千次作。这称为 迭代、循环或可变成本。一些密码哈希算法使用硬编码的 迭代轮次;其他 Git. 则使其在 Hash 本身的一部分中可配置。例如,md5crypt() 使用 MD5,包括 salt,并正好循环 1000 次。sha512crypt() 使用 sha512,包括一个盐、 并循环可配置的次数(默认为 5,000)。

迭代主要影响哈希算法的计算周期成本,而不是其内存占用或 其他因素。在设计经过优化以抵抗某些类型的哈希类型时,这些也很重要 的攻击,但这太杂草了,不能在这里讨论。


哈希类型对破解速度的影响

我们来看一些例子来演示哈希算法选择的影响,无论是 salted、使用多次迭代等。假设攻击者收集了 1,000 个用户的哈希值 来自某个受感染的网站,他们只想进行一次简单的攻击,测试每个密码 哈希值 - 1.43 亿个候选密码。

受感染网站使用的哈希类型将对所需的时间产生巨大影响 攻击者通过该攻击。这是一张(相对、大致)有多少的图表 完成该攻击需要秒,具体取决于所使用的哈希类型,其中 标准显卡:

嗯,那没用!最强的哈希类型要慢得多,但速度更快 类型只是被压扁到什么都没有。让我们使用对数 X 轴时间再次尝试相同的数据 规模。当条形从左向右移动时,它们将增加 10 的幂次方:

所以一些要点是:当你想破解一些密码哈希时,单轮比 多轮和无盐比加盐更容易。相反,当某些公司或网站 宣布包含用户数据的数据泄露,a) 密码最好已经过哈希处理, 不仅仅是纯文本;b) 它们最好是加盐的,而不仅仅是哈希的;c) 他们最好有 一直在使用强大的多轮加盐哈希,而不仅仅是单轮。



识别哈希类型

在尝试破解给定的密码哈希之前,由破解者来弄清楚使用了哪种哈希算法来实现它。识别哈希类型通常很简单,但并非总是如此。Crackers 通常根据线索(例如哈希长度和格式)做出有根据的猜测。归根结底,确信哈希类型猜测是否正确的唯一方法是哈希是否被破解。

这里和这里提供了一些用于此任务的优秀资源,它们都显示了常见哈希值是什么样的。

Kali Linux 中提供了“hash-identifier”软件包(可在此处获得),有助于识别未知的哈希类型。



碰撞

当两个不同的输入导致相同的哈希输出时,就会发生冲突。这很糟糕(显然)。对于密码,这可能意味着我可能没有破解您的实际密码,但是由于我找到了一个产生相同哈希值的输入,我可以使用纯文本值来欺骗系统,使其认为密码是合法的。

Microsoft Office 在其文档保护中使用了一种多年来容易发生冲突的算法。发现单个哈希的多个冲突并不少见,所有这些冲突都会解锁文档。

一旦发现冲突,算法实际上就会被破坏。如果它发生一次,则从统计上讲,它很可能会再次发生。唯一阻碍我们的是时间和处理能力。随着算法变得更加稳健,生成候选算法并比较哈希输出以搜索它们需要更多的能力和时间。因此,设计人员越来越擅长创建不易发生冲突的算法。


上一条:hashcat密码破解硬件
下一条:什么是 Hashcat?密码破解的第一步【基础入门篇】