Python 密码学实用指南(全)(2)https://developer.aliyun.com/article/1507499
Windows 密码哈希
在本节中,我们将看到如何使用 Cain 获取哈希,然后了解 MD4 和 Unicode 的工作原理。然后,我们将讨论如何使用 Google 破解哈希和如何使用单词列表破解哈希。
使用 Cain 获取哈希
Cain 是一个免费的黑客工具,可以从正在运行的操作系统中收集 Windows 哈希。为了测试它,我们将在 Windows Server 上创建三个帐户,这是 Windows 操作系统的最新版本。您可以使用命令提示符中的用户命令来执行此操作。您可以添加一个名为John
的用户,密码为P@sw0rd
,一个名为Paul
的用户,密码为P@sw0rd
,以及一个名为Ringo
的用户,密码为P@sw0rd999
:
如果运行 Cain,它可以收集哈希。以下屏幕截图显示了三个用户及其哈希值:
LM Hash 部分是一个已经不再被任何 Windows 版本使用的过时系统,因此它只包含一个没有信息的虚拟值。当您登录时 Windows 实际使用的哈希称为 NT Hash。请注意,如果两个用户使用相同的密码,它们将具有完全相同的哈希值:464
值。这是该系统的一个弱点。不幸的是,这是一个非常薄弱且陈旧的密码系统。
MD4 和 Unicode
这是 Microsoft 使用的算法。它将密码编码为 Unicode 而不是 ASCII,然后当您通过 MD4 运行它(这是一个非常古老的算法,甚至比 MD5 还要古老),它会产生 NT 哈希值:
使用 Unicode 的原因是因为 Microsoft 是一个国际操作系统,允许您使用中文和日文等语言的密码,这些语言不是每个字符使用 8 位编码,而是每个字符使用 16 位编码。
使用 Google 破解哈希
由于密码哈希没有变化,任何两个具有相同密码的用户将具有相同的哈希,过去 24 年来已经破解了单词列表的所有黑客都将他们的结果放在了互联网上,导致了这样一种情况:你可以直接谷歌经常使用的密码哈希:
如果你只是把一个哈希放到谷歌上,你经常会发现有人已经为你破解了并放在了互联网上。例如,这里有一个P@sw0rd
,已经有一个已知的结果,所以你可以破解它。这种简单的方法适用于很多密码,但这种技术对于我们用于用户Ringo
的密码P@sw0rd999
不起作用。
使用单词列表破解哈希
因此,在密码无法破解的情况下,你需要自己计算:
你只需使用相同的过程。进行一系列的猜测,对它们进行哈希,然后寻找你的答案。如果你的猜测列表最终达到正确的值,你当然会在这里找到它。因此,你可以看到密码P@sw0rd999
的5c2c...
。
这很简单,所以让我们在 Python 中试一试。
在终端窗口中,我们将输入python
命令。接下来我们将导入hashlib
库:
因此,你可以看到进行编码的行。我们输入密码,编码为utf-16le
,这是 Unicode;然后,我们用 MD4 进行哈希,并将其表示为hexdigest
。
这是P@sw0rd
的数字。现在,如果我们尝试访问Ringo
用户,我们需要有一个包含两个哈希值的列表,这些值最终需要达到正确的值:
如果我们只是按顺序使用997
,998
和999
进行计数,我们将得到我们正在寻找的5c2c...
值。
Linux 密码哈希
在本节中,我们将首先讨论如何从操作系统中获取哈希值,然后看看加盐和拉伸过程是如何使 Linux 哈希值更加安全的。然后我们将讨论现代版本的 Linux 使用的特定哈希算法,最后看看如何使用单词列表和 Python 破解哈希。
在这里,我们创建了三个用户来测试软件,方式与我们之前在 Windows 上做的方式类似。John
和Paul
有相同的密码,而Ringo
有不同的密码:
你可以从/etc/shadow
文件中获取哈希值,从中我们将打印出最后三条记录。因此,你会看到John
,Paul
和Ringo
,每个用户名后面都跟着$6
,这表明它是密码的第 6 种类型,这是最现代和安全的形式。然后是一长串随机字符,直到下一个美元符号,然后是一个更长的随机字符串,这就是密码哈希本身。
你可以看到的第一件事是密码哈希,它比 Windows 密码哈希要长得多,更复杂。接下来要观察的是,即使John
和Paul
有相同的密码,它们的哈希完全不同,因为在对它们进行哈希之前,它们会添加一个随机的salt
,以掩盖这些密码是相同的事实,从而使密码更加安全。加盐是在进行哈希之前添加随机字符的过程;这里也使用了拉伸。它不仅仅使用一轮 MD4,而是使用了 5000 轮 SHA-512,这简单地使得计算哈希需要更多的 CPU 时间。这样做的目的是减缓试图制作密码哈希字典的攻击者的速度。
你可以在/etc/login.defs
文件中找到该方法的详细信息,该文件显示现代版本的 Linux 使用SHA512
和5000
轮的加密方法:
因此,该过程要求你将salt
与密码结合起来。你执行一个包括 5000 轮 SHA-512 哈希的算法。它实际上有超过 20 个步骤,涉及将两个哈希值放在一起并混合位,但它比仅仅重复相同的哈希算法要复杂一些。
我们将使用passlive
库。在 Python 中使用它之前,你必须使用pip install passlib
命令进行安装。一旦你安装好了,你就可以导入sha512_crypt
模块。以下是你如何使用它:
让我们开始 Python 终端。然后我们可以像之前展示的那样导入passlib
库,因为我们已经将其放入pip install
中。
现在,我们可以计算第一个,它将使用影子文件中的salt
值并对其进行哈希,如前面的屏幕截图所示。
正如你所看到的,我们得到了正确的结果(以r7k
开头)。如果我们进行字典攻击,我们将得到一系列密码猜测,如下所示:
只需尝试它们,直到找到与之匹配的那个。
挑战 1 – 破解 Windows 哈希
在对 Windows 哈希进行审查和进行 1 位数哈希的示例之后,我们将给你两个挑战——一个是 2 位数密码,另一个是 7 位数密码。以下是 Python 中 Windows 哈希的样子:
该算法使用hashlib
对密码的哈希进行 MD4,但在此之前,将其编码为utf-16le
,然后计算结果的hexdigest
以获得长数字,该数字以464
开头,在这种情况下,这是一个 Windows 密码哈希。
因此,你可以编写一个程序,尝试这个字符串中的所有字符,它将由 10 个数字组成,然后计算每个字符的哈希。你将得到一个简单的包含 10 个值的字典:
你可以使用一个 1 位数密码来破解这个 1 位数哈希,方法如下:
因此,这是一个挑战。密码是 00 到 99 之间的 2 位数,这是哈希:
因此,你需要创建一个循环,尝试 100 个可能的值。
接下来是一个 7 位数密码,这是哈希:
因此,你将不得不尝试 1000 万个值。这只需要几秒钟,这就是为什么 Windows 密码哈希非常薄弱——你可以每秒尝试数百万个。
挑战 2 – 破解多轮哈希
在审查了 Python 中 MD5 和 SHA 的工作原理之后,我们将看到多轮哈希是什么,然后你将得到两个挑战来解决。
MD5 和 SHA 都很容易计算:
从hashlib
库中,你只需要使用hashlib.new
方法,并将算法的名称放在第一个参数中,密码放在第二个参数中,然后将十六进制摘要添加到其中,以便看到十六进制的实际结果,而不仅仅是对象的地址。要进行多轮,你只需重复该过程。
你需要将密码放入h
,然后使用当前的h
来计算下一个h
,并一遍又一遍地重复这个过程。以下是一个打印多轮 MD5 哈希的前 10 轮的小脚本:
这种技术称为拉伸,它被更强大的密码哈希例程所使用,比如我们在前面部分看到的 Linux 密码哈希。
这是你的第一个挑战:一个 3 位数密码使用 MD5 哈希 100 次。从这个哈希中找到它:
这里还有一个挑战。在这个挑战中,你有一个未知轮数的 SHA-1,但不超过 5000。因此,你只需尝试所有值,并从这个哈希中找到结果的 3 位数密码。
挑战 3 – 破解 Linux 哈希
在审查了 Linux 哈希之后,我们将向你展示你的挑战。
Linux 哈希是经过盐处理和拉伸的,有各种版本。我们正在讨论当前版本,即版本 6,也就是最安全的形式:
哈希是以美元符号开头的长字符串;6
表示版本,然后是一个美元符号,后面跟着salt
,再加一个美元符号,后面是哈希。要在 Python 中计算它们,您需要导入一个特殊的 SHA-512 crypt
库,就像您之前看到的格式一样。
这是您的第三个挑战:以这种格式的 3 位密码。salt
值为penguins
,hash
是以P
开头的一长串混乱字符。
摘要
在本章中,我们介绍了 MD5 和 SHA-1 哈希算法,Windows 密码哈希算法和 Linux 密码哈希算法。在挑战中,您破解了一个 Windows 密码哈希以恢复明文密码,以及使用未知数量的 MD5 和 SHA-1 轮次破解了另一个密码哈希。最后,您破解了 Linux 密码哈希以恢复明文密码。
在第三章,强加密中,我们将介绍两种主要的强加密方法,即 AES 和 RSA。
第三章:强加密
强加密甚至可以对抗决心坚定的对手,比如敌对军事机构,如果做得正确的话。强加密的两种主要方法是 AES 和 RSA,它们都得到了美国政府的批准。你不需要有编程经验来学习这个,也不需要任何特殊的计算机;任何能运行 Python 的计算机都可以完成这些项目。而且你不需要太多的数学,因为我们不打算发明新的加密技术,只是学习如何使用标准的现有的那些,这些不需要任何比基本代数更高级的东西。
在本章中,我们将涵盖以下内容:
- AES 强加密
- ECB 和 CBC 模式
- 填充预言攻击
- RSA 强加密
- 接下来呢?
AES 强加密
在这一部分,我们将看一下高级加密标准(AES),私钥加密,密钥和块大小,如何影响 AES,以及 Python 和混淆和扩散。
AES 是美国国家标准技术研究所批准的加密标准,被认为非常安全。它甚至被批准用于保管机密军事信息。它是私钥加密,这是几千年来一直在使用的加密类型,发送方和接收方都使用相同的密钥。它是块密码,因此输入数据必须放在长度为 128 位的块中,明文块用密钥加密,产生密文块:
有三种密钥大小:128、192 和 256 位。最常见的 AES 类型是 128 位密钥大小,这就是我们在这个例子中要使用的。在 Python 中,使用起来非常容易。
首先,你需要从crypto cipher
导入AES
模块,然后你需要一个 16 字节的密钥和明文,这是 16 字节的整数倍。然后你将用密钥创建一个新的 AES 对象,然后用密码加密计算它。这会给你一个 16 字节的字符串,可能是不可打印的,所以最好将其编码为十六进制以打印出来;当然,如果你解密它,你会回到原始的明文。这具有许多理想的加密属性,其中之一是混淆。如果你改变密钥的一位,它会改变整个密文。
因此,如果我们将密钥改为kex
,你会看到所有的密文都改变了。这就是你想要的。两个非常相似的密钥会产生完全不同的结果,因此你无法找到任何模式来推断密钥的信息。
同样,扩散是一种理想的属性,如果你用相同的密钥对同一明文进行两次加密,但你改变了明文的一位,整个密文再次改变。看下面的例子:
在这里,我们有字节,得到相同的433
结尾于6a8
。如果我们把最后一个字母改成t
,你会发现它以90c
开头,以5d2
结尾;也就是说,它完全改变了。
让我们在 Python 中看一下:
- 打开终端窗口并启动
python
。我们将输入以下命令,如截图所示:
- 我们导入
AES
模块,有一个 16 字节的密钥和一个 16 字节的明文。我们创建了一个 AES 对象,对其进行了加密,然后我们在这里打印出了十六进制值:
- 现在,我们改变密钥:
我们来到密钥行,将其改为z
,然后再次进行操作,用该密钥创建一个新的 AES 对象。进行加密并再次打印出结果,你会看到一切都不同了。
现在它以b
开头,以4
结尾,完全改变了。
- 现在,我们将保留密钥不变,改变明文。让我们把
t
改成F
。现在如果我们加密它并以十六进制打印出结果,一切又都改变了;尽管这与上面的密钥相同:
因此,这显示了混淆和扩散,这是可取的特性。在下一节中,我们将讨论 ECB 和 CBC 模式。
ECB 和 CBC 模式
我们将比较电子密码本(ECB)和密码块链接(CBC)并向您展示如何在 Python 中实现 AES CBC。
ECB
在 ECB 方法中,每个明文块都分别使用密钥加密,因此如果你有两个相同的明文块,它们将产生相同的密文:
如果你有一张图片,上面有大片的纯色,比如灰色和黑色,然后你加密它,你会得到不同的颜色,但图案不会改变:
这不好。你仍然可以看到这是一只企鹅的图片,这不是大多数人对加密的期望。你期望加密隐藏数据,以便查看加密数据的攻击者无法知道消息是什么,而这里这种属性是不存在的。
因此,CBC 被认为是这个问题的最佳解决方案。
CBC
除了密钥,你还需要添加一个初始化向量,它在加密之前与明文进行异或运算。然后对于下一个块,你取加密产生的密文,并将其用作第二个块的初始化向量。第三个块的输出被用作第三个块的初始化向量。因此,即使每个块中的输入明文相同,每个块中的密文也会不同:
这导致更多的混淆:
你可以看到企鹅现在完全看不见,所有字节都是随机的,所以这几乎是每个目的的首选。
要在 Python 中执行它,这是我们之前在 EBC 模式下执行的 AES 的方法。默认情况下,你不需要指定模式。
如果你想使用 CBC 模式,你可以输入以下命令:
AES 模式 CBC 当你创建密码对象时。你还需要提供一个初始化向量,它可以是 16 字节,就像密钥一样。如果你加密 16 字节的文本块,由于初始化向量,结果中没有明显的差异,但它只是一个十六进制块。要看到这种效果,你需要使明文更长。当你加密它时,你会得到一个十六进制的块。这就是 ECB 模式,它并没有消除数据中的所有模式。这是具有相同重复输入的 CBC 模式。正如你所看到的,输出没有模式,并且无论你走多远,都不会重复。因此,它更有效地隐藏了数据。
让我们来看看。我们在终端中启动 Python,然后添加这段代码:
因此,你可以看到 16 字节的密钥和 16 字节的 AES 明文在 ECB 模式下。我们对其进行加密并打印答案。
如果我们想要使它更长,我们添加这个:
你可以在 Python 中对字符串对象进行乘法运算,如果你只是打印它出来,你会看到它只是同样的东西三次。
现在我们可以加密plain3
:
当我们打印出来时,它将在 33 处有重复的模式。现在,如果我们改变模式,我们需要一个iv
:
我们只需要 16 个字节,所以我们将 16 个字节添加到iv
。接下来,我们创建一个新的AES
对象。现在,在iv
中,我们再次加密plain3
,然后再次打印出结果。
你可以看到它有61f
,你可以看到不再有重复。因此,如果你真的想要模糊输入,这是一种更有效的加密方式。
Python 密码学实用指南(全)(4)https://developer.aliyun.com/article/1507503