Python密码学编程 第2版

978-7-115-52999-2
作者: [美]阿尔·斯维加特(Al Sweigart)
译者: 郑新芳赵怡翾
编辑: 陈聪聪
分类: Python

图书目录:

详情

自互联网面世以来,网络安全一直是人们所重视的问题。从20世纪中叶开始,流传千百年的密码算法纷纷被投入到了网络安全的应用中;随后,在20世纪70年代,与古典密码完全不同的密码体制——公钥密码算法横空出世,密码学的发展完成了一次飞跃。 Python诞生于20世纪90年代,它是一种面向对象语言特点与解释型语言特点相结合的高级程序设计语言,已经得到了大规模应用。本书将Python语言与密码学结合起来,从简单的古典密码算法开始,一直到公钥密码算法,进行了简洁而细致的说明与解读。每一种密码算法的讲解包括原理部分、实现部分和破解部分(公钥算法不包括破解部分),其中后两者附有详细的Python代码,注释简洁明了,可读性极高。每章的末尾还提供了一些习题,帮助读者巩固所学知识并进行深入理解。 本书适合任何想要学习Python编程并对密码学抱有兴趣的读者。本书对Python编程的基础要求不高,初学者可以放心地阅读本书。相信本书一定能够为读者带来绝佳的阅读体验。

图书摘要

版权信息

书名:Python密码学编程(第2版)

ISBN:978-7-115-52999-2

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。


著    [美] 阿尔·斯维加特(Al Sweigart)

译    郑新芳 赵怡翾

责任编辑 陈聪聪

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315


Copyright©2018 by Al Sweigart. Title of English-language original: Cracking Codes with Python: An Introduction to Building and Breaking Ciphers, ISBN 978-1-59327-822-9), published by No Starch Press. Simplified Chinese-language edition copyright ©2020 by Posts & Telecom Press. All rights reserved.

本书中文简体版由No Starch Press公司授权人民邮电出版社独家出版。

未经出版者书面许可,不得以任何方式复制或抄袭本书内容。

版权所有,侵权必究。


自互联网面世以来,网络安全一直是人们所重视的问题。从20世纪中叶开始,流传千百年的密码算法纷纷被投入到了网络安全的应用中;随后,在20世纪70年代,与古典密码完全不同的密码体制——公钥密码算法横空出世,密码学的发展完成了一次飞跃。

Python诞生于20世纪90年代,它是一种面向对象语言特点与解释型语言特点相结合的高级程序设计语言,已经得到了大规模应用。本书将Python语言与密码学结合起来,从简单的古典密码算法开始,一直到公钥密码算法,进行了简洁而细致的说明与解读。每一种密码算法的讲解包括原理部分、实现部分和破解部分(公钥算法不包括破解部分),其中后两者附有详细的Python代码,注释简洁明了,可读性极高。每章的末尾还提供了一些习题,帮助读者巩固所学知识并进行深入理解。

本书适合任何想要学习Python编程并对密码学抱有兴趣的读者。本书对Python编程的基础要求不高,初学者可以放心地阅读本书。相信本书一定能够为读者带来绝佳的阅读体验。


Al Sweigart是一名软件开发工程师和技术图书作者,现居旧金山。Python是他最喜欢的编程语言。他为Python开发了若干开源模块。


Ari Lacenski设计过移动App和Python软件,现居西雅图。

Jean-Philippe Aumasson(第22~24章)是瑞士Kudelski Security的首席研究工程师。他定期在Black Hat、DEF CON、TROOPERS及Infiltrate等信息安全会议上发表演讲。他也是Serious Cryptography的作者。


如果没有No Starch团队的帮助,那么本书是不可能出版的。感谢出版人Bill Pllock;感谢编辑Riley Hoffman、Jan Cash、Annie Choi、Anne Marie Walker及Laurel Chun,在本书出版过程中对我的鼎力相助;感谢技术责编Ari Lacenski在本书编辑过程中对我的帮助,起初我将本书拿给她看时,那还只是一摞打印稿;感谢JP Aumasson在第23章中给我提供的专业意见;感谢Josh Ellingson为本书设计的精彩封面。


如果读者带着本书穿越回到20世纪90年代,就会发现第23章关于RSA密码的内容在当时的美国是不允许出口的。由于RSA密码加密过的信息不可能被破解,因此美国政府将出口类似RSA的加密软件视作与美国国家安全相关的问题,需要由美国国务院提供许可。事实上,法律对高强度的密码算法甚至有着和坦克、导弹、火焰喷射器一样严格的限定。

1990年,加利福尼亚大学的一名学生Daniel J. Bernstein想要发表一篇关于Snuffle加密系统源代码的学术论文。美国政府告知他,如果想要将代码发表在互联网上,就必须先得到一张军火商的许可证。同时,美国政府还告诉他,因为他的技术安全等级太高,所以如果他要申请一张军火许可证的话,政府就不得不吊销他的出境护照。

电子前线基金会(EFF)是一个十分年轻的数字公民自由组织,在Bernstein起诉美国政府的时候,它与Bernstein站在了同一阵线。这是有史以来第一次,法庭判决一份软件代码受到宪法第一修正案的保护,且对该加密软件的出境控制触犯了Bernstein的法定人权。

现在,每天都有成千上万的互联网商人使用强大的密码算法。这些密码算法已然成为全球经济、商业安全保障和电子商务站点的基石。情报机构曾经预测加密软件将会毁灭国家安全机制的骇人言论早已失去踪影。

许多图书指导初学者如何运用密码算法写出密文以及破解密码算法,但目前几乎没有一本书教授初学者如何用计算机编程实现密码算法的破解,本书填补了这一空白。

本书是为对加密、破解或密码算法抱有浓厚兴趣的人士准备的。除第23章和第24章介绍的公钥密码算法以外,本书其余的密码算法均有超过一个世纪的历史,但目前的笔记本电脑有破解它们的计算能力。现在已经很少有组织或个人会使用这些密码算法了,但通过学习这些算法,读者能够了解密码算法建立的基础,也能了解黑客破解弱密码算法的方式。

注意

本书介绍的密码算法都非常有趣,但它们实际上并不安全。切记不能使用本书中的任何加密程序去加密真实的文件。还有一个普遍的定理是,不要信任任何你自己创造出来的密码算法。真实世界中的密码算法是经过密码学家多年的专业分析及设计之后才投入使用的。

本书也是为从未学习过编程的读者准备的。它将以Python语言传达基础的编程理念。对于新手来说,Python是一门优秀的编程语言,拥有平缓的学习曲线,各年龄段的初学者均可以掌握,而它同时也是一种用于专业软件开发的强大语言。Python程序可以运行在Windows、macOS、Linux系统,甚至树莓派,下载和使用Python程序都是完全免费的。

在本书中,作者将频繁用到“黑客”这一术语。“黑客”这个词语有两种定义,它可能指某个研究密码系统(如密码算法的原理或软件代码的片段)的人,这个人精通整个系统,以致他不会受到系统原则的限制,甚至可以创造性地对系统进行修改;这个词也可能是指闯入计算机系统的不法分子,他们会侵犯人们的隐私,造成各类损失。本书采用的是第一种释义。黑客是很“酷”的,而犯罪分子不过是一些认为搞破坏就能显得自己高人一等的家伙罢了。

第1~3章将介绍Python和密码学的基本概念。第4~24章则依次解释某种密码算法的加密程序与其对应的破解程序。每章配备习题,有助于读者复习所学到的知识。

本书与其他编程类图书的不同之处在于,它的重点在于讲解一段完整的源代码。本书会向读者展示完整的程序并解释其工作原理,而不是仅告诉读者编程的原理,然后让读者自己去研究如何编写一个程序。

在阅读本书的过程中,建议读者手动将本书中的代码输入Python文件中。这样做有助于读者更好地理解代码。

在输入源代码时,注意不要将每行开头的行号一起输入。这些数字并不是代码的一部分,只不过是在解释代码的过程中可能会提到具体的某一行代码,因此使用了行号。当然,除需要注意行号的问题以外,还必须确保输入的代码和书中完全一致,包括大小写形式。

读者可能会注意到,某些代码并不是从最左侧开始书写的,它的前面有4格、8格甚至更多的缩进。请确保输入正确的空格数,避免出错。

虽然手动输入程序的源代码对学习Python有很大帮助,但这个过程可能会偶尔出现拼写错误,导致程序报错。要检查出拼写错误可能十分困难,尤其是在源代码非常长的情况下。

本书并不是一本编程参考书,而是一本为初学者设计的实践指南。因此,本书中的代码有时候并未与最佳代码样式相符,但对本书而言,让代码学习起来更容易才是明智的选择。同时,本书并不会对计算机科学的理论做任何介绍。

老练的程序员可能会指出,本书的部分代码可以改进得更有效率一些,但本书最关心的问题不是代码执行的效率,而是以简单的方式让程序能够执行。

在开始编程之前,读者首先要安装Python编译器(Python Interpreter),即一种用于执行Python指令的软件。以下将Python编译器简称为Python。

读者可从Python官网上免费下载Windows、macOS、Ubuntu 版本的Python。只要下载最新版本,本书中的所有程序就能够正常运行。

注意

读者需要确保下载的版本是Python 3系列(如Python 3.6)。本书中的程序是在Python 3上运行的,在Python 2上可能无法正常运行。

在Windows上,首先下载Python安装包,该安装包的文件名应该以 .msi 结尾,双击这个安装包,然后按照安装程序在屏幕上显示的指南安装Python。

(1)选择Install Now开始安装。

(2)安装完成后,单击Close按钮。

在macOS上,首先下载符合当前macOS版本的.dmg文件并双击,然后按照安装程序在屏幕上显示的指南安装Python,如下所示。

(1)当DMG包打开新窗口时,双击Python.mpkg文件。这个过程可能要输入计算机的管理员密码。

(2)单击欢迎界面上的Continue按钮并单击Agree按钮接受相关条款。

(3)选择HD Macintosh(或读者硬盘的名称)并单击Install按钮。

如果当前系统是Ubuntu,那么可以按照以下步骤从Ubuntu软件中心安装Python。

(1)打开Ubuntu软件中心。

(2)在窗口右上角的搜索栏中输入Python。

(3)选择IDLE(Python 3.6版本),或其他最新版本。

(4)单击Install按钮。

在完成安装的过程中,可能要输入管理员密码。

本书中的程序用到了一个作者编写的通用模块:pyperclip.py。这个模块可以让程序复制并粘贴文本到剪贴板中。

该文件的位置必须和读者编写的Python文件在同一文件夹(或称同一路径)中,否则运行程序时会出现如下报错信息。

ImportError: No module named pyperclip

下载并安装完Python编译器及pyperclip.py模块之后,接下来看一看编写程序的工具。

Python编译器即为能够执行Python程序的软件,而交互式开发环境(Interactive Development Environment,IDLE)就是编写程序的地方,它更像是一个文字处理器。IDLE在安装Python的同时就一并被安装好了,可以通过以下步骤启动IDLE。

无论是哪种操作系统,IDLE的窗口看起来都和图0.1差不多。顶部的文字可能会有些许不同,这取决于读者下载的Python版本。

图0.1所示的这个窗口称为交互式运行环境(interactive shell)。在交互式运行环境中,可以将指令输入计算机,这与macOS的Terminal或Windows的Command Prompt程序类似。有时,程序员可能不想编写一个完整的程序,只想试着执行几行代码片段,Python交互式运行环境就提供了这一功能,使得程序员能够直接往里输入指令,而计算机会立即读取并执行这些指令。

图0.1 IDLE窗口

例如,将下列代码输入交互式运行环境的 >>> 提示符之后。

>>> print('Hello, world!')

按回车键,交互式运行环境将显示以下内容。

Hello, world!

在现代密码学引入计算机技术之前,仅靠纸和笔是无法破解大部分密码的。虽然计算机使许多古老的、经典的密码变得十分脆弱,但学习这些密码的过程仍然非常有趣。编写密码分析程序去破解这些密码是学习如何编程的好方法。

在第1章中,我们将从基础的密码学工具说起,在没有计算机帮助的情况下实现对信息的加密和解密。

让我们开始破解的相关学习吧!


本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。

本书提供如下资源:

要获得以上配套资源,请在异步社区本书页面中单击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。

作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,单击“提交勘误”,输入勘误信息,单击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/selfpublish/submission即可)。

如果学校、培训机构或企业想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。

“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。

“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。

异步社区

微信服务号


在开始编写密码程序之前,先用纸笔对加密和解密过程一窥究竟,不仅有利于明白密码的工作原理,也有助于理解生成密文时使用的数学原理。本章将介绍什么是密码学、编码和密码的区别,并用纸笔完成一个简单密码——凯撒密码的加密和解密过程。

本章要点

自古以来,间谍、士兵、黑客、海盗、商人等人,大多依靠密码学来确保他们的秘密不会人尽皆知。密码学是一门使用秘密编码的学科。想要明白密码长什么样,看一看下面两段文本。

nyr N.vNwz5uNz5Ns6620Nz0N3z2v

N yvNwz9vNz5N6!9Nyvr9

y0QNnvNwv tyNz

Nw964N6!9N5vzxys690,N.vN2z5u-

3vNz Nr Ny64v,N.vNt644!5ztr vNz

N 6N6 yv90,Nr5uNz Nsvt64v0N

yvN7967v9 BN6wNr33Q N-m63 rz9v

!NN2 Nuwv,N9,vNN!vNrBN3zyN4vN

N6 Qvv0z6nvN.7N0yv4N 4 zzvNN

vyN,NN99z0zz6wz0y3vv26 9

w296vyNNrrNyQst.560N94Nu5y

rN5nz5vv5t6v63zNr5.

N75sz6966NNvw6 zu0 wtNxs6t

49NrN3Ny9Nvzy!

以上左侧的文本是一个经过加密(转换为秘密编码)的消息。对于那些不知道如何将密码解密(将其转换回原始的英文消息)的人来说,它完全不可读。而以上右侧的文本是随机的“胡言乱语”,没有任何隐藏的含义。加密使不懂得如何解密的人即便拿到了密码,也无法参透其中的含义,因为加密后的消息和随机的“胡言乱语”毫无区别

密码学家使用和研究密码。当然,这些秘密消息并不总是保密的。密码分析学家,又称为密码破解者或黑客,可以破解密码并读懂他人的加密消息。本书讲解如何使用各种技术对信息进行加密和解密。

与密码不同的是,编码的方式是可以公开获得并理解的。编码使用符号替换消息中的内容,任何人都可以查阅符号是如何进行翻译的。

19世纪初,一个著名的编码来源于电报的发展,它使各地通过电线进行即时通信成为现实。用电报发送信息比之前骑马去送一大袋信件的传统方式要快得多。然而,电报不能直接发送纸上书写的字母,它只能发送两种类型的电脉冲:称为“点”的短脉冲和称为“线”的长脉冲。

要将字母表中的字母转换成脉冲类型中的点和线,需要一个编码系统将英语翻译成电脉冲。英语转换成电报发送的点和线的过程称为编码,而收到消息时把电脉冲转换成英语的过程称为解码。电报(和后来的无线电)对消息进行编码和解码的方式称为摩尔斯电码,如表1-1所示。摩尔斯电码是由Samuel Morse和Alfred Vail开发的。

表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

▬ ▬ ● ●

电报操作员通过在拥有一个按钮的电报机上敲击点和线,可以向世界另一边的人传达英语信息,而且仅需要很短的时间!

与编码相对,密码是一种特定类型的编码方式,目的是保证消息的机密性。可以使用密码将可理解的英文文本(称为明文)转换为隐藏秘密的乱码(称为密文)。密码是使明文和密文相互转换的一组规则。这些规则中,通常会使用一个只有通信者知道的密钥来进行加密或解密。在这本书中,读者将学习几个密码,并编写程序来使用这些密码对文本进行加密和解密。但在此之前,让我们先用简单的纸质工具手动完成文本加密。

即将学习的第一个密码是凯撒密码,它以早期使用者Julius Caesar的名字命名。它简单易学,但也因此极易被密码分析员破解。但是,它仍然可以用来进行练习。

凯撒密码通过替换字母完成加密,每个字母由字母表中其后特定位数的字母代替。例如,Julius Caesar将字母表向后移动3个字母的位置,然后用得到的新字母表中的字母替换原消息中的每个字母。

例如,消息中的每一个A都变成D,每个B都变成E等。当Caesar需要将字母表末尾的字母(如Y)移位时,他会绕回到字母表的开头,移动3个位置到B。在本节中,将使用凯撒密码手动加密消息。

为了更方便地使用凯撒密码将明文转换为密文,将使用一个密码轮,也称为密码盘。密码轮包含两个由字母组成的环,每个环有26个槽(为字母表的26个字母准备)。外圈表示明文中的字母,内圈表示在密文中相对应的字母。内圈同样把字母从0到25进行标号,这些数字代表加密密钥,这里的加密密钥是指将A移动到内环上对应的字母所需经过的字母位数。因为轮盘是圆形的,用大于25的密钥移位会使字母表绕一整个圈,所以移动26位与移动0位相同,移动27位与移动1位相同,以此类推。

读者可以通过原书网站在线访问虚拟的密码轮,其形式如图1-1所示。为了旋转密码轮,需要先单击它,然后移动鼠标光标,直到想要的配置到位。再次单击鼠标,密码轮停止旋转。

在本书的配套资源中也可以获得可打印的纸版密码轮。剪下两个圆圈,把它们叠放,小的圆圈放在大的圆圈中间。在两个圆圈的中心插入一个大头钉或曲头钉,这样它们就可以旋转了。

无论使用纸质密码轮还是虚拟密码轮,都可以完成手动加密。

图1-1 在线密码轮

开始加密前,请先用英文在一张纸上写下待加密的消息。在这个例子中,待加密消息是“THE SECRET PASSWORD IS ROSEBUD”。接下来,旋转密码轮的内轮,直到它的槽与外轮中的槽相匹配。注意外轮上字母“A”旁边的点,点在内轮上最接近的数字就是加密密钥。

例如,在图1-1中,外轮的“A”对应内轮的8。现在使用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”,因此每个字母只需查找一次。

在对整个消息进行加密之后,原始消息“THE SECRET PASSWORD IS 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”。对密文中剩下的字母进行解密,还原成明文,可以得到完整的消息“THE NEW PASSWORD IS SWORDFISH”,如图1-4所示。

图1-4 用密钥为15的凯撒密码解密消息

如果使用不正确的密钥(如16),则解密的消息将是“SGD MVV OZRRVNQC HR RVNQCEHG”,依然不可读。除非使用正确的密钥,否则解密出来的消息也是不可理解的。

使用密码轮实现凯撒密码的加密和解密是十分便捷的,但是也可以通过数学计算进行加密和解密。在此过程中,从“A”到“Z”写出字母表中的字母,在每个字母下标注数字0~25。从“A”下面的0开始,“B”下面是1,以此类推,直到“Z”下面是25,如图1-5所示。

图1-5 为字母标号0~25

可以用这些数字来表示对应的字母。这是一个强有力的概念,有了它的存在,就可以在字母上进行数学运算。如果将字母“CAT”表示为数字2、0和19,分别加3获得数字5、3和22,则根据图1-5,这些新的数字表示字母“FDW”,这样就实现了为“CAT”加密。稍后,会设计一个计算机程序实现这一计算过程。

要运用算术实现凯撒密码的加密,请找到要加密的字母下方的数字,并将其加上密钥的值,得到的和就是对应密文字母下的数字。可以使用1~25的任意数字作为密钥,例如,使用密钥13加密“HELLO. HOW ARE YOU?”。首先,找到“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”。

读者可能会认为,使用两个不同的密钥对消息进行两次加密将使加密强度增加一倍,但这对于凯撒密码(以及大多数其他密码)来说并不适用。事实上,加密两次的结果与一次正常加密的效果相同。现在,尝试对消息进行两次加密,以理解原因。

如果使用密钥3对单词“KITTEN”进行加密,那么密文字母由明文字母的标号加3获得,是“NLWWHQ”。再对“NLWWHQ”进行加密,这次使用密钥4,得到的密文将是“RPAALU”。但这两次加密实现的最终效果和用密钥7加密一次“KITTEN”是没有任何区别的。

对于大多数密码而言,加密多次并不能增加强度。事实上,如果使用两个加起来为26的密钥对一明文进行加密,得到的密文将和原始明文完全相同!

凯撒密码和其他类似的密码用于加密信息已有几个世纪之久,但是,如果想加密一条长消息,比如说一整本书,手动加密可能需要几天或几周的时间,这时便有了编程的用武之地。计算机可以在不到1s的时间内对大量文本进行加密和解密!

要使用计算机实现加密,需要学习如何用计算机能理解的语言进行编程或者说指导计算机来执行与前述相同的步骤。幸运的是,学习Python这样的编程语言并不像学习日语或西班牙语等外语那样困难。除了加法、减法和乘法之外,也不需要更多的数学知识。需要的只是一台计算机和这本书!

现在前往第2章,学习如何使用Python的交互式运行环境逐行实现代码。

1.对下列Ambrose Bierce所著《魔鬼辞典》中的内容,用给定的密钥进行加密。

a.密钥为4:“AMBIDEXTROUS: Able to pick with equal skill a right-hand pocket or a left.”

b.密钥为17:“GUILLOTINE: A machine which makes a Frenchman shrug his shoulders with good reason.”

c.密钥为21:“IMPIETY: Your irreverence toward my deity.”

2.用给定的密钥解密下列密文。

a.密钥为15:“ZXAI: P RDHIJBT HDBTIXBTH LDGC QN HRDIRWBTC XC PBTGXRP PCS PBTGXRPCH XC HRDIAPCS.”

b.密钥为4:“MQTSWXSV: E VMZEP EWTMVERX XS TYFPMG LSRSVW.”

3.用0作为密钥对句子进行加密:“This is a silly example.”。

4.下面是一些单词和对应的密文。每个单词使用了什么密钥?

a.ROSEBUD – LIMYVOX

b.YAMAMOTO – PRDRDFKF

c.ASTRONOMY – HZAYVUVTF

5.一个用密钥8加密的句子,用密钥 9 解密,变成了什么样?“UMMSVMAA: Cvkwuuwv xibqmvkm qv xtivvqvo i zmdmvom bpib qa ewzbp epqtm.”。


在能够编写解密程序之前,读者需要了解一些基础的编程概念。这些概念包括(value)、操作符(operator)、表达式(expression)以及变量(variable)。

本章要点

现在从如何在Python交互式运行环境(Python Interactive Shell)中做一些简单的数学运算开始。请务必在计算机旁边阅读本书,这样读者可以随时输入样例代码,并观察执行结果。锻炼编写代码的身体记忆有助于记忆Python的代码是如何构建起来的。

打开IDLE(请翻阅前言“启动IDLE” 部分),读者将会看到命令行工具界面以及在“>>>”提示符后闪烁的光标。交互式运行环境可以像计算器一样进行运算。在界面上输入“2+2”并敲击键盘上的“Enter”键(在某些键盘上可能是“return”键),计算机将会显示数字4作为响应,如图2-1所示。

图2-1的样例中,“+”号指示计算机将数字2和2相加,除此之外,Python也可以进行其他类型的运算,例如用负号“−”执行减法、用一个星号“*”执行乘法或者用一个正斜线“/”执行除法。当我们把这些符号(+、−、*、/)用作运算的时候,它们就成为了操作符(operator),因为它们能指示计算机去操作两端的数字。表2-1总结了Python中的算术操作符。上面提到的数字2(或其他数字)就叫作(value)。

图2-1 在Shell中输入“2+2”

表2-1 Python中的算术操作符

操 作 符

运 算 名

+

加法

减法

*

乘法

/

除法

要特别说明的是,“2+2”并不是一个程序,它只是一条单独的指令。程序是由许多这样单独的指令构成的。

在程序中,整数(如4、0、99)被称作整型(integer);带小数点的数(如3.5、42.1或5.0)被称作浮点数(floating-point number)。Python中数字5是一个整型,但如果把它写成5.0,它就成为了一个浮点数。

整型和浮点型都属于数据类型(data type),数值42是一个整型的值,或者说是数据类型int的一个值;数值7.5是一个浮点型的值,或者说是数据类型float的一个值。

每一个值都有其数据类型,这在接下来的章节中将会做更多介绍(如第3章中的字符串类型),但是现在只需要记住,任何时候人们谈到一个值,所说的都是一个特定数据类型的值。想要区分这些值的数据类型非常简单,通常观察它的书写格式就可以辨认。整型数据类型即没有小数点的数字,浮点型即带有小数点的数字。因此,42是一个整数,但42.0是一个浮点数。

读者已经看到Python解决一个数学问题的过程了,但Python能做到的远不止这些。尝试把下列数学问题输入Shell界面,在每一个问题输入完成后按下Enter键。

❶ >>> 2+2+2+2+2
 10
 >>> 8*6
 48
❷>>> 10-5+6
 11
❸>>> 2 +    2
 4

这些数学问题被称作表达式(expression)。计算机可以在数秒内解决成千上万条类似的表达式。表达式由被操作符(数学符号)连接起来的值(数字)组成,如图2-2所示。在一个表达式中,读者想要它包含多少数字,它就可以包含多少数字,只需使用操作符把这些数字连接起来,同时也可以在一条表达式中使用不同的操作符。除此之外,还可以在整数和操作符之间输入任意数量的空格。但需要确保的是,每条表达式的起始位置必须一直保持在一行的开头,前面不能有空格,这是因为起始的空格会改变Python解释指令的方式。读者将会在4.8节中了解到更多有关起始空格的知识。

图2-2 一个表达式由值(比如2)和操作符(比如+)组成

读者可能还记得数学课堂上曾经提到过“运算顺序”这个短语。例如,乘法要在加法之前进行运算。表达式“2+4*3”的运算结果为14,这是因为乘法首先执行,先计算“4*3”,然后才将结果与2相加。括号可以使不同的操作符优先执行。如表达式“(2+4)*3”,加法首先计算“2+4”,然后才将所得的和乘以3。括号使得表达式的值由14变为了18。Python中数学操作符的操作顺序(也称作优先级)和数学上的运算顺序是类似的。括号内的运算先被执行,其次是*和/两个操作符从左到右进行运算,然后才是+和−两个操作符从左到右执行。

当计算机对表达式“10+5”进行计算并得到结果15时,我们就说它计算出了表达式的值。计算表达式的过程是将一个表达式简化为一个值,这就类似于解决一个数学问题,最终把这个问题缩减为一个数字,即问题的答案。

表达式“10+5”和“10+3+2”有相同的值,因为它们的计算结果都是15。甚至单一的值也可以被视作表达式:表达式15经过运算,得到的值是15。

在得到一个单一的值之前,Python会持续对表达式进行如下的计算。

Python一般按照括号由内到外、从左至右的顺序计算表达式的值。即使这些括号互相嵌套在一起,它们内部的表达式仍然是按照与其他任何表达式相同的规则进行计算的。因此,当Python遇到表达式“((7+1)/(3−1))”的时候,它首先计算最左边并且位于内部括号中的值,即“(7+1)”,然后计算右边的括号中的值,即“(3−1)”。当位于内部的两个括号的值都被计算出来之后,再计算外括号内部的值。注意,除法计算得到的结果都是浮点数。最后,当括号内部再也没有其他表达式的时候,Python将按照数学运算的次序进行剩余部分的计算。

一个表达式中可以包含两个及以上的、由操作符连接起来的值,或者包含单一的值,但是如果在交互式运行环境中输入了一个值和一个操作符,就会收到报错信息。

>>> 5 +
SyntaxError: invalid syntax

出现这个报错的原因是,“5+”并不是一个表达式。一个包含多个值的表达式需要通过操作符去连接这些值,并且在Python语言中,操作符“+”正是可以连接两个值的符号。一个句法错误(syntax error)意味着,由于没有正确地输入指令,因此计算机不能理解如何执行它。这看上去并不是很重要,但计算机编程不仅指示计算机要做什么——还要了解如何正确地向计算机发出可以执行的指令。

报错没什么大不了的! 

触发报错没什么大不了的!输入引发报错的代码并不会破坏读者的计算机。Python只会提示出现了一个错误,然后再次把“>>>”提示符显示在界面上,开发人员可以继续在后面输入新的代码。

虽然在积累更多的编程经验之前,报错信息可能对读者没有太大意义,但读者始终可以将报错信息输入搜索引擎中,找到能够解释这个报错的网站。

程序往往需要保存出现过的数值,方便后续代码使用。这时可以使用“=”(赋值操作符)将数值存储在变量中。例如,要将数值15存储在一个名为spam的变量中,可以在交互式运行环境中输入“spam = 15”。

>>> spam = 15

可以将变量想象为一个盒子,将数值15装在这个盒子当中(见图2-3)。变量名spam是这个盒子外部的标签(所以我们可以辨别不同的变量),而存储在其中的值就像是盒子中的便签条。

图2-3 变量就像贴有名字的盒子,里面装着值

当按下“Enter”键的时候,计算机只会显示一行空白的内容作为响应。除非遇到报错,否则可以认为计算机成功执行了指令。下一个“>>>”标识符会紧跟着出现,这样,开发人员就可以输入下一条指令了。

带有“=”这个赋值操作符的指令(被称作赋值语句)创造了一个名为spam的变量,并将数值15存储在这个变量当中。与表达式不同的是,语句(statement)是不需要经过计算得到结果的指令,它们仅仅执行一步操作。这就是为什么交互式运行环境中紧跟该语句的下一行没有显示任何的值。

要分辨哪些指令是表达式、哪些指令是语句可能会十分令人费解。然而只需要记住,如果一条Python指令计算出了一个独立的值,它就是一个表达式;如果没有,它就是一条语句。

一条赋值语句的书写形式是,一个变量名,后面跟着“=”操作符,“=”后是一个表达式,如图2-4所示。表达式计算出的值就存储在这个变量中。

图2-4 一条赋值语句的组成部分

记住,每个变量只存储一个单独的值,并不存储为它赋值的那个表达式。例如,如果输入一条语句:spam = 10 + 5,则表达式首先会计算“10+5”的值,然后再将结果15存储到变量spam中,可以通过在交互式运行环境中输入变量名来查看其中存储的值。

>>> spam = 10 + 5
>>> spam
15

一个变量本身就是一个表达式,其计算结果就是存储在其中的值。一个值本身也是一个表达式,其计算结果就是它本身。

>>> 15
15

下面介绍一种有趣的变化:如果在交互式运行环境中输入“spam + 5”,你将会得到整数20。

>>> spam = 15
>>> spam + 5
20

如上所示,变量可以在表达式中起到和值相同的作用。因为变量spam的值是15,所以表达式“spam + 5”和表达式“15 + 5”是等价的,其计算结果为20。

通过输入另一条赋值语句,可以改变变量中存储的值。例如,输入如下代码。

 >>> spam = 15
❶ >>> spam + 5
❷ 20
❸ >>> spam = 3
❹ >>> spam + 5
❺ 8

第一次输入“spam + 5”的时候,表达式的值是20,这是因为数值15存储在变量spam中。然而,在输入“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的新值是目前它的值加上5”,“=”右边的表达式将值赋予“=”左边的变量。以此类推,可以继续多次为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这两个变量)。但是在很长一段时间没有看到这个程序之后,再回头看一看这些变量,开发人员可能已经不记得每个变量的作用了。

一个好的变量名可以描述它存储的值。想象一下,如果一个人要搬家,把所有要搬走的箱子都贴上Stuff的标签,他可就什么都找不到了!在本书和其他许多Python的文献中,变量名spam、eggs和bacon等(来自喜剧Monty Python中以“spam”命名的一个段落)都被广泛地用作样例,但在读者自己的程序中,一个描述性的变量名有助于提高代码的可读性。

变量名(与Python的其他任意组成部分一样)是大小写敏感的。大小写敏感的意思是,如果两个变量的名称是相同的单词,但大小写书写情况不同,那么它们就被视作两个完全不同的变量。例如,spam、SPAM、Spam和sPAM在Python中是4个不同的变量。它们可以分别存储自己的值,而不会在使用的过程中互换。

读者可能会问:什么时候可以开始编写加密程序呢?答案是,很快了。但是在有能力破解密文之前,读者需要学习更多的基础编程概念,因此,还得再阅读一个关于编程的章节。

在本章中,读者学习了在交互式运行环境中编写Python指令的基本方法:Python要求开发人员按照它期望的方式告诉它具体该做什么,因为计算机只能理解非常简单的指令。读者还学习到Python可以计算表达式的值(也就是将一个表达式消减为一个单独的值)以及表达式是由值(如2或5)和操作符(如+或−)组成的。读者也了解到把值存储在变量中,程序就可以记住这些值并在之后使用它们。

交互式运行环境是一种很好的用于了解Python指令用途的工具,因为它允许开发人员每次输入一条指令并查看结果。在第3章中,读者将要编写包含了许多指令的程序,它们将按照一定的顺序执行,而不是每输入一次就执行一条,第3章的内容将探讨更多的基础概念,读者会编写自己的第一个程序!

1.哪个操作符用于除法,“/”还是“\”?

2.下列数值中,哪个是整数,哪个是浮点数?

42
3.141592

3.下列数行代码中,哪一行不是表达式?

4 x 10 + 2
3 * 7 + 1
2 +
42
2 + 2
spam = 42

4.如果你将下列几行代码输入交互式运行环境中,第1行和第2行会打印出什么?

 spam = 20
❶ spam + 20
 SPAM = 30
❷ spam


相关图书

深度学习的数学——使用Python语言
深度学习的数学——使用Python语言
动手学自然语言处理
动手学自然语言处理
Web应用安全
Web应用安全
Python高性能编程(第2版)
Python高性能编程(第2版)
图像处理与计算机视觉实践——基于OpenCV和Python
图像处理与计算机视觉实践——基于OpenCV和Python
Python数据科学实战
Python数据科学实战

相关文章

相关课程