Python 密码破解指南:0~4
Posted ApacheCN
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 密码破解指南:0~4相关的知识,希望对你有一定的参考价值。
译者:飞龙
本文来自【OpenDocCN 饱和式翻译计划】,采用译后编辑(MTPE)流程来尽可能提升效率。
收割 SB 的人会被 SB 们封神,试图唤醒 SB 的人是 SB 眼中的 SB。——SB 第三定律
零、简介
“我是无意中听到的,可能是因为我在偷听。”
——匿名
如果你可以带着这本书回到 20 世纪 90 年代初,把第 23 章实现 RSA 密码的内容出口到美国以外是非法的。因为用 RSA 加密的信息不可能被破解,像 RSA 这样的加密软件的出口被认为是国家安全问题,需要国务院的批准。事实上,强密码术与坦克、导弹和火焰喷射器处于同一管控水平。
1990 年,加州大学伯克利分校的学生丹尼尔·j·伯恩斯坦(Daniel J. Bernstein)想发表一篇学术论文,介绍他的 Snuffle 加密系统的源代码。美国政府通知他,他需要成为一个有执照的军火商,然后才能在互联网上发布他的源代码。政府还告诉他,如果他申请出口许可证,它将拒绝他,因为他的技术非常保密。
电子前沿基金会,一个年轻的数字公民自由组织,代表伯恩斯坦起诉美国政府。法院有史以来第一次裁定,编写的软件代码受第一修正案的保护,与加密相关的出口控制法,侵犯了伯恩斯坦在第一修正案中的权利。
现在,强大的加密技术是全球经济的基础,保护着拥有每天数百万互联网购物者使用的电子商务网站和企业。情报机构关于加密软件将成为严重威胁国家安全的预测是没有根据的。
但是就在 20 世纪 90 年代,自由传播这些知识(就像这本书所做的那样)会让你因军火武器走私罪而入狱。想要更详细地了解争取加密自由的法律斗争历史,请阅读史蒂文·利维的书《Crypto: How the Code Rebels Beat the Government, Saving Privacy in the Digital Age》(Penguin 出版社,2001 年)。
谁应该读这本书?
许多书教初学者如何用密码写秘密信息。也有一些书教初学者如何破解密码。但是没有书教初学者如何给计算机编程来破解密码。这本书填补了这一空白。
这本书是为那些对加密、黑客或密码学感兴趣的人准备的。这本书里的密码(除了第 23 章和第 24 章里的公钥密码)都是几个世纪前的,但是任何笔记本电脑都有破解它们的计算能力。没有现代组织或个人在继续使用这些密码,但通过学习它们,您将了解密码学的基础,以及黑客如何破解脆弱的加密。
注
你在本书中学到密码的过程将很有趣,但它们并不提供真正的安全性。不要使用本书中的任何加密程序来保护你的实际文件。一般来说,你不应该相信你创造的密码。真实世界的密码在投入使用之前,要经过专业密码学家多年的分析。
这本书也是给以前没有编程基础的人看的。它使用 Python 编程语言教授基本的编程概念,这是初学者最好入手的语言之一。它有一个温和的学习曲线,所有年龄的新手都可以掌握,但它也是专业软件开发人员使用的一种强大的语言。Python 可以运行在 Windows,macOS,Linux,甚至 Raspberry Pi 上,并且可以免费下载和使用。(参见第 xxv 页的下载并安装 Python 获取说明。)
在本书中,我将经常使用术语“黑客”。这个词有两种定义。黑客可以是这样一个人,他研究一个系统(例如一个密码的规则或一个软件)以便很好地理解它,以至于他们不受该系统原始规则的限制,并且可以以创造性的方式修改它。黑客也可以是闯入计算机系统、侵犯他人隐私并造成损害的罪犯。这本书在第一种意义上使用这个术语。黑客很酷。罪犯只是那些认为他们通过破坏东西来变聪明的人。
这本书里有什么?
前几章介绍了基本的 Python 和密码学概念。随后,剩下章节通常在解释密码程序和解释破解该密码的程序之间交替。每章还包括练习题,以帮助您复习所学内容。
-
第一章:制作纸质加密工具 涵盖了一些简单的纸质工具,展示了在计算机出现之前加密是如何完成的。
-
第二章:交互 shell 中的编程 讲解了如何使用 Python 的交互 Shell 一行一行地执行代码。
-
第三章:字符串和编写程序 涵盖了编写完整的程序,并介绍了本书所有程序中使用的字符串数据类型。
-
第四章:反向密码 解释了如何为你的第一个密码编写一个简单的程序。
-
第五章:凯撒密码 涵盖了一个几千年前首次发明的基本密码。
-
第六章:用暴力破解凯撒密码 解释了暴力破解技术,以及如何使用它在没有加密密钥的情况下解密消息。
-
第七章:用换位密码加密 介绍换位密码和用它加密信息的程序。
-
第八章:用换位密码解密 涵盖了换位密码的后半部分:能够用密钥解密消息。
-
第九章:编写一个程序来测试你的程序 介绍了用其它程序测试自己代码的编程技巧。
-
第十章:加密和解密文件 解释了如何编写从硬盘读取文件和向硬盘写入文件的程序。
-
第十一章:程序化检测英语 描述了如何让计算机检测英语句子。
-
第十二章:破解换位密码 结合前几章的概念,破解换位密码。
-
第十三章:仿射密码的模运算模块 解释了仿射密码背后的数学概念。
-
第十四章:仿射密码编程 涵盖了编写一个仿射密码加密程序。
-
第十五章:破解仿射密码 讲解如何写程序破解仿射密码。
-
第十六章:编写简单的替换密码 涵盖了编写一个简单的替换密码加密程序。
-
第十七章:破解简单替换密码 讲解如何编写程序破解简单替换密码。
-
第 18 章:编程维吉尼亚密码 解释了一个维吉尼亚密码的程序,一个更复杂的替换密码。
-
第十九章:频率分析 探讨英语单词的结构,以及如何用它来破解维吉尼亚密码。
-
第二十章:破解维吉尼亚密码 讲述了一个破解维吉尼亚密码的程序。
-
第 21 章:一次性密码本 解释了一次性密码本以及为什么它在数学上不可能被破解。
-
第二十二章:寻找并生成质数 讲述了如何编写一个快速判断一个数是否为质数的程序。
-
第 23 章:生成公钥密码的密钥 描述了公钥密码以及如何编写生成公钥和私钥的程序。
-
第 24 章:公钥密码器编程 解释了如何写一个公钥密码器程序,你不能仅仅用笔记本电脑就能破解它。
-
附录调试 Python 代码,向您展示如何使用 IDLE 的调试器来查找并修复程序中的 bug。
如何使用这本书
用 Python 破解代码不同于其他编程书籍,因为它关注的是完整程序的源代码。这本书向你展示了完整的程序,并解释了它们是如何工作的,而不是教你编程概念,让你自己去弄清楚如何制作自己的程序。
一般来说,你应该按章节顺序阅读这本书。在前几章建立编程概念的基础。然而,Python 是一种可读性很强的语言,在开始前面几章之后,你可以跳到后面的章节,拼凑出代码的功能。如果你在继续往后续章节阅读过程中,感觉迷失了,可以回到前面的章节。
键入源代码
当你通读这本书时,我鼓励你手动将这本书的源代码输入 Python 。这样做肯定会帮助你更好地理解代码。
键入源代码时,不要包含出现在每行开头的行号。这些数字不是实际程序的一部分,我们用它们来指代代码中的特定行。但是除了行号之外,请确保输入的代码与显示的完全一样,包括大写字母和小写字母。
你还会注意到,有些行不是从页面的最左边开始,而是缩进了四个、八个或更多的空格。你需要确保在每行开头输入正确的空格数,以避免发生错误。
但是如果你不想输入代码,你可以从本书的网站www.nostarch.com/crackingcodes
下载源代码文件。
检查代码编写中的错别字
尽管手动输入程序的源代码对学习 Python 很有帮助,但您可能偶尔会犯一些会导致错误的错别字。这些错别字可能很难发现,尤其是当您的源代码非常长的时候。
为了快速方便地检查你键入的源代码中的错误,你可以将文本复制并粘贴到该书网站上的在线比较工具中,网址为www.nostarch.com/crackingcodes
。差异工具显示了书中的源代码和你的源代码之间的任何差异。
本书编码约定
这本书的目的不是设计成一本参考手册;而是作为给初学者的实践指南。出于这个原因,编码风格有时违背了最佳实践,但这是一个有意识的决定,使代码更容易学习。这本书也跳过了理论上的计算机科学概念。
经验丰富的程序员,可能会指出改变本书中的代码实现方法可以提高效率,但本书主要关注的是让程序以最少的努力工作。
在线资源
这本书的网站(www.nostarch.com/crackingcodes
)包括许多有用的资源,包括程序的可下载文件和练习题的示例解答。这本书全面地涵盖了经典密码,但是因为总是有更多的东西需要学习,所以我也包括了对这本书中介绍的许多主题的进一步阅读的建议。
下载安装 Python
在开始编程之前,您需要安装 Python 解释器,这是一个执行您将用 Python 语言编写的指令的软件。从现在开始,我将把“Python 解释器”称为“Python”。
从www.python.org/downloads
免费下载适用于 Windows、macOS 和 Ubuntu 的 Python。如果你下载了最新版本,这本书里的所有程序都可以运行。
注
一定要下载 Python 3 的某个版本(比如 3.6)。本书中的程序是为在 Python 3 上运行而编写的,在 Python 2 上可能无法正确运行。
Windows 安装
在 Windows 上,下载 Python 安装程序,其文件名应该以.msi
结尾。并双击它。按照安装程序在屏幕上显示的说明安装 Python,如下所示:
-
选择立即安装开始安装。
-
安装完成后,点击关闭。
macOS 安装
在 macOS 上,从网站上下载适用于您的 macOS 版本的 dmg* 文件,然后双击它。按照安装程序在屏幕上显示的说明安装 Python,如下所示:
-
当 DMG 包在新窗口中打开时,双击
Python.mpkg
文件。您可能需要输入电脑的管理员密码。 -
点击继续通过欢迎部分,点击同意接受许可。
-
选择 HD Macintosh (或者你的硬盘名称),点击安装。
Ubuntu 安装
如果您运行的是 Ubuntu,请按照以下步骤从 Ubuntu 软件中心安装 Python:
-
打开 Ubuntu 软件中心。
-
在窗口右上角的搜索框中输入 Python 。
-
选择 IDLE(使用 Python 3.6) ,或者随便什么最新版本。
-
点击安装。
您可能需要输入管理员密码才能完成安装。
下载pyperclip.py
本书中几乎每个程序都使用了我编写的一个自定义模块,名为pyperclip.py
。这个模块提供了让你的程序复制和粘贴文本到剪贴板的功能。它不是 Python 内置程序里自带,所以你需要从www.nostarch.com/crackingcodes
下载。
这个文件必须和你写的 Python 程序文件在同一个文件夹里(也叫目录*)。否则,当您尝试运行程序时,会看到以下错误消息:
ImportError: No module named pyperclip
现在您已经下载并安装了 Python 解释器和pyperclip.py
模块,让我们看看您将在哪里编写程序。
启动 IDLE
Python 解释器是运行你的 Python 程序的软件,而交互式开发环境(IDLE)软件是你编写程序的地方,很像文字处理器。安装 Python 时会安装 IDLE。如果要开始启动 IDLE,请按照下列步骤操作:
-
在 Windows 7 或更新版本上,点击屏幕左下角的开始图标,在搜索框中输入
IDLE
,选择 IDLE (Python 3.6 64 位)。 -
在 macOS 上,打开 Finder,点击应用,点击 Python 3.6 ,然后点击
IDLE
图标。 -
在 Ubuntu 上选择应用 -> 工具 -> 终端然后进入 idle3 。(您也可以点击屏幕顶部的应用,选择应用,然后点击IDLE 3 。)
无论你运行的是哪种操作系统,IDLE 窗口看起来都应该类似于图 1。根据 Python 的具体版本,标题文本可能略有不同。
图 1:IDLE 窗口
这个窗口叫做交互 Shell。shell 是一种程序,它可以让你在计算机中输入指令,很像 macOS 上的终端或 Windows 命令提示符。有时你会想运行一小段代码,而不是编写一个完整的程序。Python 的交互式 shell 允许您输入 Python 解释器软件的指令,计算机会立即读取并运行这些指令。
例如,在交互式 shell 中的>>>
提示符旁边键入以下内容:
>>> print(\'Hello, world!\')
按下Enter
键,交互 shell 应该显示以下响应内容:
Hello, world!
总结
在计算机的引入带来了现代密码学之前,仅仅使用铅笔和纸是不可能破解许多密码的。尽管许多古老的经典密码容易受到计算机的攻击,但学习它们仍然很有趣。编写破解这些密码的密码分析程序是学习如何编程的好方法。
在第 1 章中,我们将从一些基本的加密工具开始,在没有计算机帮助的情况下加密和解密信息。
让我们开始破解吧。
一、制作纸质加密工具
“加密精灵已经从瓶子里出来了。”
——简·库姆,WhatsApp 创始人
在我们开始写密码程序之前,让我们看一下只用铅笔和纸实现加密和解密的过程。这将帮助你理解密码是如何工作的,以及产生秘密信息的数学原理。在这一章中,你将了解我们所说的密码是什么,以及代码与密码有何不同。然后,您将使用一种称为凯撒密码的简单密码,用纸和笔对消息进行加密和解密。
本章涵盖的主题
-
什么是密码学?
-
代码和密码
-
凯撒密码
-
密码轮
-
用算术实现密码学
-
双重加密
什么是密码学?
历史上,任何需要与他人共享秘密的人,如间谍、士兵、黑客、海盗、商人、暴君和政治活动家,都依赖密码学来确保他们的秘密保密和不被公开。密码学是使用秘密代码的科学。要理解加密是什么样子的,请看下面两段文字:
左边的文字是一条经过加密的秘密信息,或者说变成了一个秘密代码。对于不知道如何解密它,或者把它变回原始的英文信息的人来说,它是完全不可读的。右边的消息是没有隐藏含义的随机乱码。加密使信息对其他无法解密的人保密,即使他们得到了加密后的信息。一条加密的信息看起来完全像随机的胡说八道。
一个密码学家使用并研究秘密代码。当然,这些秘密信息并不总是保密的。一个密码分析专家,也被称为密码破译者或黑客,可以破解密码并读取他人的加密信息。这本书教你如何使用各种技术加密和解密信息。但不幸的是或者说幸运的是,你将在本书中学到的黑客行为不会让你陷入法律问题的危险。
代码与密码
与密码不同的是,代码可以被理解和公开获得。代码用符号代替信息,任何人都可以通过查找来翻译成信息。
在 19 世纪早期,一个众所周知的代码来自于电报的发展,它允许通过电线在各大洲之间进行近乎即时的通信。通过电报发送信息比以前派一个骑马的人携带一袋字母要快得多。然而,电报不能直接发送写在纸上的字母。相反,它只能发送两种类型的电脉冲:一种称为“点”的短脉冲和一种称为“划”的长脉冲。
要将字母表中的字母转换成这些点和破折号,你需要一个编码系统将英语转换成电脉冲。将英语转换成点和破折号来发送电报的过程称为编码,接收到消息时将电脉冲翻译成英语的过程称为解码。用于编码和解码电报(以及后来的无线电)信息的代码被称为莫尔斯电码,如表 1-1 所示。塞缪尔·莫尔斯和阿尔弗雷德·维尔发明了莫尔斯电码。
表 1-1: 国际莫尔斯电码编码
字母 | 编码 | 字母 | 编码 | 数字 | 编码 |
---|---|---|---|---|---|
A |
N |
1 |
|||
B |
O |
2 |
|||
C |
P |
3 |
|||
D |
Q |
4 |
|||
E |
R |
5 |
|||
F |
S |
6 |
|||
G |
T |
7 |
|||
H |
U |
8 |
|||
I |
V |
9 |
|||
J |
W |
0 |
|||
K |
X |
||||
L |
Y |
||||
M |
Z |
通过用一键电报机点击点和破折号,报务员几乎可以立即将英语信息传达给世界另一端的人!(要了解更多关于莫尔斯电码的信息,请访问/www.nostarch.com/crackingcodes
。)
与代码不同的是,密码是一种特殊类型的代码,旨在使信息保密。你可以使用一种密码将可理解的英文文本,称为明文,转换成隐藏秘密信息的乱码,称为密文*。密码是一组在明文和密文之间转换的规则。这些规则通常使用只有通信者知道的秘密密钥来加密或解密。在这本书里,你将学习几种密码,并编写程序使用这些密码来加密和解密文本。但是首先,让我们使用简单的纸质工具手工加密消息。
凯撒密码
你将学习的第一个密码是凯撒密码,它是以 2000 年前使用它的朱利叶斯·凯撒命名的。好消息是它简单易学。坏消息是因为它太简单了,所以密码分析者也很容易破解。然而,这仍然是一个有用的学习练习。
凯撒密码的工作原理是,在移动字母表后,用一个新字母替换信息中的每个字母。例如,朱利叶斯·凯撒通过将字母表中的字母下移三位,然后用移位后的字母表中的字母替换每个字母,来替换他信息中的字母。
例如,消息中的每个 A 都将被替换为 D,每个 B 都将是 E,依此类推。当 Caesar 需要移动字母表末尾的字母(如 Y(时,他会绕到字母表的开头,并将三个位置移动到 b。在本节中,我们将使用凯撒密码手动加密消息。
密码轮
为了使使用凯撒密码将明文转换为密文更容易,我们将使用一个密码轮,也称为密码盘。密码轮由两个字母环组成;每个环被分成 26 个槽(26 个字母的字母表)。外环代表明文字母表,内环代表密文中对应的字母。内环也是从 0 到 25 的数字。这些数字代表加密密钥,在这种情况下,它是从 A 移动到内环上相应字母所需的字母数。因为移位是循环的,用大于 25 的密钥移位会使字母绕回,所以移位 26 就等于移位 0,移位 27 就等于移位 1,依此类推。
您可以在www.nostarch.com/crackingcodes
在线访问虚拟密码轮。图 1-1 显示了它的样子。要旋转滚轮,请单击它,然后四处移动鼠标光标,直到您想要的配置就位。然后再次单击鼠标以停止滚轮旋转。
图 1-1:在线密码轮
这本书的网站上还提供了一个可打印的纸质密码轮。剪下两个圆,将它们叠放在一起,将较小的一个放在较大的一个的中间。通过两个圆圈的中心插入一个大头针或圆头钉,这样你就可以在适当的位置旋转它们。
使用纸张或虚拟转轮,你可以手工加密秘密信息。
用密码轮加密
要开始加密,在一张纸上用英语写下你的信息。对于这个例子,我们将加密消息,密码是 ROSEBUD。接下来,旋转密码轮的内轮,直到其插槽与外轮的插槽匹配。注意外轮字母 A 旁边的点。注意这个点旁边的内轮上的数字。这是加密密钥。
例如,在图 1-1 中,外圆的 A 在内圆的数字 8 之上。在我们的例子中,我们将使用这个加密密钥来加密消息,如图 1-2 所示。
图 1-2:用 8 的凯撒密钥加密信息
对于消息中的每个字母,在外圈找到它,并用内圈的相应字母替换它。在这个例子中,消息中的第一个字母是 T(“THE SECRET…”中的第一个 T),所以在外圆中找到字母 T,然后在内圆中找到相应的字母,也就是字母 b。因此,秘密消息总是用 b 替换 T。(如果您使用不同的加密密钥,明文中的每个 T 将被替换为不同的字母。)消息中的下一个字母是 H,变成 p,字母 E 变成 m,外轮上的每个字母总是加密到内轮上的同一个字母。为了节省时间,在您查找“THE SECRET…”中的第一个 T 并看到它加密到 B 后,您可以将消息中的每个 T 替换为 B,因此您只需要查找一个字母一次。
在您加密整个消息之后,原始消息(秘密密码是 ROSEBUD)就变成了 BPM AMKZMB XIAAEWZL QA ZWAMJCL。请注意,非字母字符(如空格)不会改变。
现在你可以把这封加密的邮件发送给别人(或者自己保存),除非你告诉他们秘密的加密密钥,否则没有人能够阅读它。一定要对加密密钥保密;任何知道消息是用密钥 8 加密的人都可以读取密文。
用密码轮解密
要解密密文,从密码轮的内圈开始,然后移动到外圈。例如,假设您收到了密文 IWT CTL EPHHLDGS XH HLDGSUXHW。除非你知道密钥(或者除非你是一个聪明的黑客),否则你无法解密这条消息。幸运的是,你的朋友已经告诉你他们用 15 密钥来传递信息。该密钥的密码轮如图 1-3 所示。
图 1-3:设置在 15 密钥的密码轮
现在,您可以将外圆上的字母 A(下面有圆点的那个)排列在内圆上有数字 15 的字母(也就是字母 P(上。然后,在内圈上找到秘密消息中的第一个字母,就是 I,再看外圈上对应的字母,就是 t,密文中的第二个字母 W 解密成字母 h,将密文中的其余字母解密回明文,就得到消息,新密码是剑鱼,如图 1-4 所示。
图 1-4:用 15 的凯撒密钥解密一条消息
如果你使用了一个不正确的密钥,比如 16,解密后的信息将是 SGD MDV OZRRVNQC HR RVNQCEHRG,这是不可读的。除非使用正确的密钥,否则无法理解解密的消息。
用算术加密和解密
密码轮是使用凯撒密码加密和解密的方便工具,但是您也可以使用算术加密和解密。要做到这一点,从 A 到 Z 写字母表的字母,在每个字母下面写下从 0 到 25 的数字。从 A 下面的 0 开始,B 下面的 1,依此类推,直到 z 下面的 25。
图 1-5:从 0 到 25 对字母表进行编号
你可以用这个字母到数字的代码来代表字母。这是一个强大的概念,因为它允许你对字母进行数学运算。例如,如果将字母CAT
表示为数字 2、0 和 19,则可以将 3 相加得到数字 5、3 和 22。这些新数字代表字母FDW
,如图 1-5 所示。你刚刚给CAT
这个词“加”了 3!稍后,我们将能够编程一台计算机来为我们做这些数学运算。
要使用凯撒密码算法进行加密,请在您要加密的字母下找到数字,然后将密钥号添加到该数字中。得到的总和就是加密字母下的数字。比如,我们来加密 HELLO。你好吗?使用密钥 13。(您可以使用 1 到 25 之间的任何数字作为密钥。)首先找到 H 下面的数字,是 7。然后在这个数上加 13:7+13 = 20。因为数字 20 在字母 U 下面,字母 H 加密到 U。
同样,要加密字母 E (4(,加 4 + 13 = 17。17 以上的数是 R,所以 E 被加密成 R,以此类推。
这个过程一直进行到字母 O,O 下面的数字是 14。但是 14 加 13 是 27,数字列表最多只有 25。如果字母的数字和密钥的和是 26 或更多,你需要从中减去 26。在这种情况下,27–26 = 1。数字 1 上面的字母是 B,所以 O 用密钥 13 加密到 B。当您加密邮件中的每个字母时,密文将为 URYYB。UBJ·NER·LBH?
要解密密文,减去密钥而不是加上密钥。密文字母 B 的数目是 1。1 减去 13 得到–12。像我们加密的“减 26”法则,解密时结果小于 0,就需要加 26。因为–12+26 = 14,密文字母 B 解密为 o。
注
如果你不知道如何用负数加减,你可以在
www.nostarch.com/crackingcodes
了解一下。
如你所见,使用凯撒密码不需要密码轮。你所需要的只是一支铅笔,一张纸,和一些简单的算术!
为什么双重加密不起作用
您可能认为使用两个不同的密钥对一条消息加密两次会使加密的强度加倍。但凯撒密码(以及大多数其他密码)并非如此。事实上,双重加密的结果和普通加密的结果是一样的。让我们尝试对消息进行双重加密,看看为什么。
例如,如果您使用密钥 3 对单词 KITTEN 进行加密,您将在明文字母的数字上加上 3,得到的密文将是 NLWWHQ。如果您随后加密 NLWWHQ,这次使用密钥 4,得到的密文将是 RPAALU,因为您在明文字母的数字上加了 4。但这和用密钥 7 加密一次小猫这个词是一样的。
对于大多数密码,多次加密不会提供额外的强度。事实上,如果你用两个加起来是 26 的密钥对一些明文进行加密,得到的密文将和原始明文一样!
总结
几个世纪以来,凯撒密码和其他类似的密码被用来加密秘密信息。但是如果你想加密一条长消息——比如说,一整本书——手工加密可能需要几天或几周的时间。这就是编程可以发挥作用的地方。计算机可以在不到一秒的时间内加密和解密大量文本!
要使用计算机进行加密,你需要学习如何编写程序,或者使用计算机能够理解的语言来指导计算机执行我们刚刚执行的相同步骤。幸运的是,学习像 Python 这样的编程语言并不像学习像日语或西班牙语这样的外语那样困难。除了加法、减法和乘法,你也不需要知道很多数学知识。你需要的只是一台电脑和这本书!
让我们继续第 2 章,在这里我们将学习如何使用 Python 的交互式 shell 一次一行地探索代码。
练习题
练习题的答案可以在本书的网站www.nostarch.com/crackingcodes
找到。
-
用给定的密钥加密比尔斯的《魔鬼字典》中的以下条目:
-
密钥 4:
AMBIDEXTROUS: Able to pick with equal skill a right-hand pocket or a left.
-
密钥 17:
GUILLOTINE: A machine which makes a Frenchman shrug his shoulders with good reason.
-
密钥 21:
IMPIETY: Your irreverence toward my deity.
-
-
用给定的密钥解密下列密文:
-
密钥 15:
ZXAI: P RDHIJBT HDBTIXBTH LDGC QN HRDIRWBTC XC PBTGXRP PCS PBTGXRPCH XC HRDIAPCS.
-
密钥 4:
MQTSWXSV: E VMZEP EWTMVERX XS TYFPMG LSRSVW.
-
-
用密钥 0 加密下面的句子:
This is a silly example.
-
以下是一些单词及其加密。每个单词用了哪个密钥?
-
ROSEBUD – LIMYVOX
-
YAMAMOTO – PRDRDFKF
-
ASTRONOMY – HZAYVUVTF
-
-
用密钥 8 加密的这句话用密钥 9 解密成什么?" ummsmaa:Cvkwuuwv xibqmvkm qv xtivvqvo I zmdmvom bpib QA ewzbp epqtm . "*
二、交互式 SHELL 中的编程
“分析引擎并不能自命地创造任何东西。它可以做任何我们知道如何命令它执行的事情。”
——阿达·洛芙莱斯,1842 年 10 月
在编写加密程序之前,您需要学习一些基本的编程概念。这些概念包括值、运算符、表达式和变量。
本章涵盖的主题
-
运算符
-
值
-
整数和浮点数
-
表达式
-
计算表达式
-
变量值
-
覆盖变量
让我们从探索如何在 Python 的交互式 shell 中进行一些简单的数学运算开始。请务必在您的计算机旁边阅读这本书,这样您就可以输入简短的代码示例并了解它们的功能。从输入程序开发肌肉记忆将帮助你记住 Python 代码是如何构造的。
一些简单的数学表达式
通过打开 IDLE 启动(参见第二十七页上的启动 IDLE(。您将看到交互式 Sheel 和在>>>
提示符旁边闪烁的光标。交互式 Shell 可以像计算器一样工作。在 shell 中键入2 + 2
,然后在键盘上按enter
。(在某些键盘上,这是回车键
。)计算机应显示数字4
做出响应,如图 2-1 所示。
图 2-1:将2 + 2
键入 shell 。
在图 2-1 的例子中,+
符号告诉计算机将数字2
和2
相加,但是 Python 也可以做其他计算,比如用减号(–
(减去数字,用星号(*
(乘以数字,或者用正斜杠(/
(除以数字。当以这种方式使用时,+
、-
、*
和/
被称为运算符,因为它们告诉计算机对它们周围的数字执行运算。表 2-1 总结了 Python 数学运算符。这些2
s(或其他数字)被称为值。
表 2-1:Python 中的数学运算符
运算符 | 操作 |
---|---|
+ |
加法 |
- |
减法 |
* |
乘法 |
/ |
除法 |
本身,2 + 2
不是程序;它只是一个简单的指令。程序由许多这样的指令组成。
整数和浮点值
在编程中,整数如4
、0
、99
称为整数。带小数点的数字(3.5
、42.1
、5.0
(称为浮点数。在 Python 中,数字5
是一个整数,但是如果你把它写成5.0
,它将是一个浮点数。
整数和浮点是数据类型。值42
是整型或int
数据类型的值。值7.5
是浮点或float
数据类型的值。
每个值都有一个数据类型。你将学习一些其他的数据类型(比如第三章的中的字符串),但是现在只要记住,任何时候我们谈论一个值,这个值是一个特定的数据类型。通常只需查看值是如何书写的,就可以很容易地识别数据类型。整数是没有小数点的数字。浮点数是带小数点的数字。所以42
是 int,但是42.0
是 float。
表达式
您已经看到 Python 解决了一个数学问题,但是 Python 可以做更多的事情。尝试在 shell 中键入以下数学问题,在每个问题之后按下enter
键:
>>> 2+2+2+2+2 # ➊
10
>>> 8*6
48
>>> 10-5+6 # ➋
11
>>> 2 + 2 # ➌
4
图 2-2:一个表达式由值(如 2 (和运算符(如 + (组成。
这些数学题叫做表达式。计算机可以在几秒钟内解决数百万个这样的问题。表达式由运算符(数学符号)和连接的值(数字)组成,如图 2-2 所示。一个表达式中可以有任意多的数字 ➊,只要它们由运算符连接;你甚至可以在一个表达式中使用多种类型的操作符 ➋。您还可以在整数和这些运算符 ➌ 之间输入任意数量的空格。但是一定要确保表达式总是在行首开始,前面没有空格,因为行首的空格会改变 Python 解释指令的方式。您将在第 45 页的的块中了解更多关于行首空格的信息。
运算顺序
你可能还记得数学课上的短语“运算顺序”。比如先做乘法再做加法。表达式2 + 4 * 3
的计算结果为14
,因为先进行乘法运算来计算4 * 3
,然后再加上2
。圆括号可以让不同的运算符先行。在表达式(2 + 4) * 3
中,首先进行加法计算(2 + 4)
,然后将总和乘以3
。括号使得表达式的计算结果为18
而不是14
。Python 数学运算符的运算顺序(也称为优先(类似于数学。首先计算括号内的运算;接下来从左到右执行*
和/
运算符;然后从左到右执行+
和-
运算符。
计算表达式
当计算机求解表达式10 + 5
并得到值15
时,我们说它已经对表达式求值。对表达式求值会将表达式简化为一个值,就像解决数学问题会将问题简化为一个数字:答案。
表达式10 + 5
和10 + 3 + 2
具有相同的值,因为它们的计算结果都是15
。甚至单个值也被认为是表达式:表达式15
的计算结果是值15
。
Python 会继续计算表达式,直到它变成单个值,如下所示:
Python 从最里面最左边的括号开始计算表达式。即使圆括号相互嵌套,圆括号内的表达式部分的计算规则也与任何其他表达式相同。所以当 Python 遇到((7 + 1) / (3 - 1))
时,它首先求解最左边的内括号中的表达式(7 + 1)
,然后求解右边的表达式(3 - 1)
。当内括号中的每个表达式都被简化为单个值时,外括号中的表达式将被求值。请注意,除法运算的结果是浮点值。最后,当括号中没有更多的表达式时,Python 按照运算符的顺序执行任何剩余的计算。
在一个表达式中,可以有两个或多个由操作符连接的值,也可以只有一个值,但是如果在交互式 shell 中输入一个值和一个操作符,就会得到一条错误消息:
>>> 5 +
SyntaxError: invalid syntax
发生这个错误是因为5 +
不是一个表达式。具有多个值的表达式需要操作符来连接这些值,而在 Python 语言中,+
操作符期望连接两个值。一个语法错误意味着计算机不理解你给它的指令,因为你打错了。这似乎并不重要,但计算机编程不仅仅是告诉计算机做什么——它还涉及知道如何正确地给计算机发出它可以遵循的指令。
错误是可以接受的!
犯错误是完全可以的!您不会因为输入错误的代码而导致损坏您的计算机。Python 会简单地告诉你发生了一个错误,然后再次显示>>>提示符。您可以继续在交互式 shell 中输入新代码。
在您获得更多编程经验之前,错误消息可能对您没有太大意义。但是,您总是可以在 google 上搜索错误消息文本,以找到解释该特定错误的网页。你也可以去www.nostarch.com/crackingcodes
查看常见 Python 错误消息列表及其含义。
变量值
程序通常需要存储值,以便在后续程序中使用。您可以通过使用=
符号(称为赋值操作符(将值存储在变量中。例如,要将值15
存储在名为spam
的变量中,在 shell 中输入spam = 15
:
>>> spam = 15
你可以把变量想象成一个盒子,里面有值15
(如图 2-3 (。变量名spam
是盒子上的标签(这样我们就可以区分一个变量和另一个变量),存储在里面的值就像盒子里面的一张纸条。
当你按下Enter
键时,你将不会看到任何东西,除了一个空行作为回应。除非你看到错误消息,否则你可以认为指令执行成功。出现下一个>>>
提示,以便您可以输入下一条指令。
这个带有=
赋值操作符的指令(称为赋值语句(创建变量spam
并将值15
存储在其中。与表达式不同,声明语句是不计算任何值的指令;相反,他们只是执行一个动作。这就是 shell 中的下一行不显示任何值的原因。
弄清楚哪些指令是表达式,哪些是语句可能会令人困惑。请记住,如果 Python 指令的计算结果是单个值,那么它就是一个表达式。如果没有,那就是声明语句。
图 2-3:变量就像有名字的盒子,可以装值。
赋值声明语句写成变量,后面是=
运算符,再后面是表达式,如图 2-4 所示。表达式计算的值存储在变量中。
图 2-4:赋值语句的组成部分
请记住,变量存储的是单个值,而不是分配给它们的表达式。例如,如果您输入语句spam = 10 + 5
,表达式10 + 5
首先被计算为15
,然后值15
被存储在变量spam
中,我们可以通过在 shell 中输入变量名看到:
>>> spam = 10 + 5
>>> spam
15
变量本身是一个由表达式计算的结果并存储在变量中的值。值本身也可以是一个对自身求值的表达式:
>>> 15
15
这里有一个有趣的转折。如果您现在在 shell 中输入spam + 5
,您将得到整数20
:
>>> spam = 15
>>> spam + 5
20
如你所见,变量可以像值一样用在表达式中。因为spam
的值是15
,所以表达式spam + 5
计算为表达式15 + 5
,然后表达式15 + 5
计算为20
。
覆盖变量
您可以通过输入另一个赋值声明语句来更改存储在变量中的值。例如,输入以下内容:
>>> spam = 15
>>> spam + 5 # ➊
20 # ➋
>>> spam = 3 # ➌
>>> spam + 5 # ➍
➎ 8
第一次输入spam + 5
➊ 时,表达式的计算结果为20
➋,因为你在变量spam
中存储了值15
。但当你输入spam = 3
➌ 时,数值15
被数值3
覆盖(即替换),如图 2-5 所示。现在当你输入spam + 5
➍ 时,表达式计算结果为8
➎ ,因为spam + 5
计算结果为3 + 5
。spam
中的旧值被遗忘。
图 2-5:变量spam
中的值 15 被值 3 覆盖。
您甚至可以使用spam
变量中的值给spam
分配一个新值:
>>> spam = 15
>>> spam = spam + 5
>>> spam
20
赋值语句spam = spam + 5
告诉计算机“变量spam
的新值是当前值spam
加五。”=
符号左侧的变量被赋予右侧表达式的值。您可以将spam
中的值变大通过几次5
的加法运算:
>>> spam = 15
>>> spam = spam + 5
>>> spam = spam + 5
>>> spam = spam + 5
>>> spam
30
每次执行spam = spam + 5
时,spam
中的值都会改变。存储在spam
中的值最终是30
。
变量名
尽管计算机不关心你给变量取什么名字,但你应该这样做。给变量起一个能反映它们所包含的数据类型的名字,这样更容易理解程序是做什么的。你可以给你的变量取像abrahamLincoln
或monkey
这样的名字,即使你的程序与亚伯拉罕·林肯或猴子无关——计算机仍然会运行程序(只要你一直使用abrahamLincoln
或monkey
(。但是当你在很长一段时间没有看到一个程序时,你可能不记得每个变量是做什么的。
一个好的变量名描述了它包含的数据。想象一下,你搬到了一所新房子,并给你所有的搬家箱子贴上标签东西。你永远找不到任何东西!变量名spam
、eggs
、bacon
等等(受《Monty Python》的“Spam”草图的启发)在本书和 Python 的大部分文档中用作示例的通用名称,但是在您的程序中,描述性名称有助于使您的代码更具可读性。
变量名(以及 Python 中的其他东西)是区分大小写的。区分大小写意味着不同大小写的相同变量名被认为是完全不同的变量。例如,spam
、SPAM
、Spam
和sPAM
在 Python 中被认为是四个不同的变量。它们都可以包含各自独立的值,不能互换使用。
总结
那么我们什么时候开始制作加密程序呢?很快。但是在你破解密码之前,你需要学习一些基本的编程概念,所以你还需要读几章编程的章节。
在本章中,您学习了在交互式 shell 中编写 Python 指令的基础。Python 需要你准确地告诉它以它期望的方式做什么,因为计算机只理解非常简单的指令。您了解了 Python 可以对表达式求值(即将表达式简化为单个值),表达式是值(如2
或5
(与运算符(如+
或-
(的组合。您还了解了可以将值存储在变量中,这样您的程序就可以记住它们以便以后使用。
交互式 shell 是学习 Python 指令的有用工具,因为它允许你一次输入一个指令并查看结果。在第 3 章中,你将创建包含许多指令的程序,这些指令是按顺序执行的,而不是一次执行一个。我们将讨论一些更基本的概念,你将编写你的第一个程序!
练习题
练习题的答案可以在本书的网站www.nostarch.com/crackingcodes
找到。
-
哪个是除法运算符,
/
还是\\
? -
下面哪个是整数值,哪个是浮点数值?
42 3.141592
-
以下哪几行不是表达式?
4 x 10 + 2 3 * 7 + 1 2 + 42 2 + 2 spam = 42
-
如果你在交互式 shell 中输入下面几行代码,➊和➋会打印出什么?
spam = 20 ➊ spam + 20 SPAM = 30 ➊ spam
三、字符串和编写程序
“亲手编写程序代码是学习一门新编程语言的唯一方法。”
——布莱恩·克尼根和丹尼斯·里奇,C 语言
第 2 章给了你足够的整数和数学知识,但是 Python 不仅仅是一个实现计算器功能。因为加密就是通过将明文转换成密文来处理文本值,所以在本章中,您将学习如何存储、组合和在屏幕上显示文本。您还将编写第一个程序,用文本"Hello, world!"
来问候用户,并让用户输入他们的名字。
本章涵盖的主题
-
字符串
-
字符串连接和复制
-
索引和切片
-
print()
函数 -
用 IDLE 写源代码
-
在 IDLE 中保存和运行程序
-
注释
-
input()
函数
使用字符串值处理文本
在 Python 中,我们处理被称为字符串值的小段文本(或者简称为字符串(。我们所有的加密和破解程序都处理字符串值,将类似于\'One if by land, two if by space\'
的明文转换成类似于\'
b1rJvsJo
!Jyn1q,J702JvsJo!J63nprM\'
的密文。在我们的程序中,明文和密文在我们的程序中都被表示为字符串值,Python 代码可以通过多种方式操作这些值。
您可以将字符串值存储在变量中,就像存储整数和浮点值一样。当您键入一个字符串时,将它放在两个单引号(\'
(之间,以显示该字符串的开始和结束位置。在交互式 shell 中输入以下内容:
>>> spam = \'hello\'
单引号不是字符串值的一部分。Python 知道\'hello\'
是一个字符串,spam
是一个变量,因为字符串用引号括起来,而变量名没有。
如果您在 shell 中输入spam
,您将看到spam
变量的内容(\'hello\'
字符串):
>>> spam = \'hello\'
>>> spam
\'hello\'
这是因为 Python 的变量赋值是将值存储在变量中:在本例中,是字符串\'hello\'
。字符串中几乎可以包含任何键盘字符。这些都是字符串的例子:
>>> \'hello\'
\'hello\'
>>> \'KITTENS\'
\'KITTENS\'
>>> \'\'
\'\'
>>> \'7 apples, 14 oranges, 3 lemons\'
\'7 apples, 14 oranges, 3 lemons\'
>>> \'Anything not pertaining to elephants is irrelephant.\'
\'Anything not pertaining to elephants is irrelephant.\'
>>> \'O*&#wY%*&OcfsdYO*&gfC%YO*&%3yc8r2\'
\'O*&#wY%*&OcfsdYO*&gfC%YO*&%3yc8r2\'
请注意,\'\'
字符串中没有字符;单引号之间没有任何内容。这被称为空串或空字符串。
用+
运算符连接字符串
您可以使用+
操作符把两个字符串值连接起来创建一个新字符串。这样做被称为字符串连接。在 Shell 中输入\'Hello,\' + \'world!\'
:
>>> \'Hello,\' + \'world!\'
\'Hello,world!\'
Python 准确地把你需要连接的字符串连接起来,所以当你连接它们时,它不会在字符串之间加一个空格。如果希望结果字符串中有一个空格,那么必须在两个原始字符串中有一个空格。要在\'Hello,\'
和\'world!\'
之间加一个空格,可以在\'Hello,\'
字符串的末尾和第二个单引号之前加一个空格,如下所示:
>>> \'Hello, \' + \'world!\'
\'Hello, world!\'
+
操作符可以将两个字符串值连接成一个新的字符串值(\'
Hello, \' + \'world!\'
到\'Hello, world!\'
(,就像它可以将两个整数值相加得到一个新的整数值(2 + 2
到4
(。由于值的数据类型,Python 知道+
操作符应该做什么。正如你在第 2 章中学到的,一个值的数据类型告诉我们(和计算机)这个值是什么类型的数据。
只要数据类型匹配,就可以在带有两个或更多字符串或整数的表达式中使用+
运算符。如果你尝试使用一个字符串和一个整数的操作符,你会得到一个错误。在交互式 shell 中输入以下代码:
>>> \'Hello\' + 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: must be str, not int
>>> \'Hello\' + \'42\'
\'Hello42\'
第一行代码导致错误,因为\'Hello\'
是一个字符串,而42
是一个整数。但是在第二行代码中,\'42\'
是一个字符串,所以 Python 将其连接起来。
用*
运算符复制字符串
你也可以在一个字符串和一个整数之间使用*
操作符来做字符串复制。这会将字符串复制(即重复)整数值的任意倍。在交互式 shell 中输入以下内容:
>>> \'Hello\' * 3 # ➊
\'HelloHelloHello\'
>>> spam = \'Abcdef\'
>>> spam = spam * 3 # ➋
>>> spam
\'AbcdefAbcdefAbcdef\'
要复制一个字符串,输入字符串,然后输入*
操作符,然后输入您希望字符串重复的次数 ➊。你也可以存储一个字符串,就像我们对spam
变量所做的那样,然后复制这个变量来代替 ➋。您甚至可以将复制的字符串存储回同一个变量或新变量中。
正如你在第 2 章的中看到的,*
操作符可以处理两个整数值,将它们相乘。但是它不能处理两个字符串值,这将导致如下错误:
>>> \'Hello\' * \'world!\'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can\'t multiply sequence by non-int of type \'str\'
字符串连接和字符串复制表明,Python 中的运算符可以根据它们所操作的值的数据类型执行不同的任务。+
操作符可以做加法或字符串连接。*
操作符可以做乘法或字符串复制。
使用索引从字符串中获取字符
您的加密程序经常需要从字符串中获取单个字符,这可以通过索引来完成。使用索引,您可以在字符串值(或包含字符串的变量)的末尾添加方括号[
和]
,它们之间有一个数字,以访问一个字符。这个数字被称为索引,它告诉 Python 字符串中的哪个位置有你想要的字符。Python 索引从0
开始,所以字符串中第一个字符的索引是0
。索引1
用于第二个字符,索引2
用于第三个字符,依此类推。
在交互式 shell 中输入以下内容:
>>> spam = \'Hello\'
>>> spam[0]
\'H\'
>>> spam[1]
\'e\'
>>> spam[2]
\'l\'
图 3-1:字符串hello
及其索引
请注意,表达式spam[0]
的计算结果是字符串值\'H\'
,因为H
是字符串\'Hello\'
的第一个字符,索引从0
开始,而不是1
(参见图 3-1)。
您可以对包含字符串值的变量使用索引,就像我们在前面的示例中所做的那样,或者对字符串值本身使用索引,如下所示:
>>> \'Zophie\'[2]
\'p\'
表达式\'Zophie\'[2]
计算出第三个字符串值,即\'p\'
。这个\'p\'
字符串就像任何其他字符串值一样,可以存储在变量中。在交互式 shell 中输入以下内容:
>>> eggs = \'Zophie\'[2]
>>> eggs
\'p\'
如果输入的索引对于字符串来说太大,Python 会显示一条"index out of range"
错误消息,如下面的代码所示:
>>> \'Hello\'[10]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range
字符串\'Hello\'
中有五个字符,所以如果您试图使用索引10
,Python 会显示一个错误。
图 3-2:字符串hello
及其负索引
负索引
负索引从一个字符串的末尾开始,向后。负索引-1
是字符串中最后一个字符的索引。索引-2
是倒数第二个字符的索引,以此类推,如图 3-2 所示。
在交互式 shell 中输入以下内容:
>>> \'Hello\'[-1]
\'o\'
>>> \'Hello\'[-2]
\'l\'
>>> \'Hello\'[-3]
\'l\'
>>> \'Hello\'[-4]
\'e\'
>>> \'Hello\'[-5]
\'H\'
>>> \'Hello\'[0]
\'H\'
注意-5
和0
是同一字符的索引。大多数情况下,您的代码将使用正索引,但有时使用负索引更容易。
使用切片从字符串中获取多个字符
如果你想从一个字符串中得到多个字符,你可以使用切片来代替索引。切片也使用[
和]
方括号,但是有两个整数索引而不是一个。这两个索引由冒号(:
(分隔,并告诉 Python 切片中第一个和最后一个字符的索引。在交互式 shell 中输入以下内容:
>>> \'Howdy\'[0:3]
\'How\'
切片计算的字符串从第一个索引值开始,一直到第二个索引值,但不包括第二个索引值。字符串值\'Howdy\'
的索引0
为H
,索引3
为d
。因为切片向上但不包括第二个索引,所以切片\'Howdy\'[0:3]
的结果为字符串值\'How\'
。
在交互式 shell 中输入以下内容:
>>> \'Hello, world!\'[0:5]
\'Hello\'
>>> \'Hello, world!\'[7:13]
\'world!\'
>>> \'Hello, world!\'[-6:-1]
\'world\'
>>> \'Hello, world!\'[7:13][2]
\'r\'
请注意,表达式\'Hello, world!\'[7:13][2]
首先将列表片求值为\'world!\'[2]
,然后进一步求值为\'r\'
。
Python游戏与影视编程指南 PDF
Python游戏与影视编程指南
链接:https://pan.baidu.com/s/1mux9QOONtWXU6IQUcvW4aQ 密码:mr1k
以上是关于Python 密码破解指南:0~4的主要内容,如果未能解决你的问题,请参考以下文章
markdown Sublime Text 3 Build 3203/3200和Sublime Merge的破解指南 - Build 1111/1109(Linux x86_64) - 更新#4(2