“皮卡丘加解密法”程序设计
比赛留下的保存稿
学生 张以赏 指导师 陶丽
摘要
加密可以用于保证安全性,但是其它一些技术在保障通信安全方面仍然是必须的,尤其是关于数据完整性和信息验证。追溯加密的历史,在古代,加密是由许多办法完成的。在中国较“流行”使用淀粉水在纸上写字,再浸泡在碘水中使字浮现出来。而在密码学上,最早的加密是美国的摩尔斯在1844年发明的,故也被叫做摩尔斯电码。加密旨在确保通讯的秘密性,例如间谍、军事将领、外交人员间的通讯,同时也有宗教上的应用。而当处于当经的信息时代,出现了更多加密方式比如RSA算法、DES算法等。而我这次要设计的课题就是要设计一种属于我的加解密法。
关键词
加密解密 Python 信息技术 信息编码 进制转换 编程 程序制作
情境引入
前段时间,在高中的信息课上老师讲了《数据的采集与编码》,老师介绍到,在计算机中所有的字符都以一种特定的形式进行二进制编码。比如像字母“A”使用ASCLL编码在计算机中就是十六进制的“41”。而我又对“摩尔斯电码”倍感兴趣,有一次上课时我不经想到了一个问题,“既然每一个字符在计算机中都有一个特定的编码,我是否可以将这些编码进行改变达到加密文本的效果呢?”说着我就可开始设计起了我的加密法“皮卡丘加密法”。
构想思路
方法一(三进制法)、我最初的想法是把“皮卡丘”三个字拆成三个字符,再将汉字的十六进制编码转化为三进制,0替换成“皮”,1替换成“卡”,2替换成“丘”,每一个字符之间使用“-”来隔开。想法虽好但是在实际测试时发现加密的结果太冗长,加密的结果很不美观。将“abc”加密后的结果是“卡皮卡丘卡-卡皮卡丘丘-卡皮丘皮皮。虽然对后续的解密的难度大大减小,但是没有达到我预想要的加密效果。
方法二(编程语言法)、我在想目标既然是将加密后的文本经过一定的处理得到最后我们想要的字符的编码,那可不可以将加密的后的文本直接变成一个“数学式子”,做一个数学计算,相加、相乘、平方根。用到循环等编程思想。凑出对应字符数值。算出最后的字符编码。缺点显而易见,太长了,而且不方便书写与解析。在生成密文时算法的难度会非常大,所以这种方法也被放弃了。
方法三(改进的编程语言法)、既然编程语言法中使用的式子太长了,那么可不可以使用两个字符来表示计算的符号呢?我尝试用更多的符号来减少运算。并且指定了一系列编程的关键字与函数,我认为只要功能增多,那么表示出来的结果一定会小。但是反其道而行,越来越长,数字“64”竟用10个字符来替代。而且这种方法也难以编程,对于生成密文有很大的困难。解密方面也会在代码上大费周章所以这种方式也没有被我采用。
方法四(十六进制法)、快要半途而弃的我又看了一遍信息书和我设计的三种方法,书上介绍说我们常用的进制有“二进制”“八进制”和“十六进制”。在“方法三”的时候我尝试使用了多个中文字符来表示一个符号。我把三进制法与编程语言法相互结合。可以使用简单点的方法用两个中文字符来替代一个十六进制数。经过整理手稿我觉得这个方法可行。
构建算法
顺着思路,我开始使用Python设计程序。首先我们必须明确程序要实现的功能是什么。我们先来实现顺思路的加密流程。第一步是要建立一个编码表,让每个十六进制与我们设计的编码一一对应起来。下面是我设计的一个编码表,参考了编程语言法后我设计了两大类编码分别是“数字表示类”和“流程控制类”,我们还要为加密后的内容的格式进行整理,这样有助于我们做解密的程序。“数字表示类”中加括号被我叫做“拓展类”用于表示七到F的十六进制数。
我们要先使用简单举例的方式来做为接入点。比如某一个字符串有两位,每一位对应的十六进制依次是“01 02”,我们就可以根据上面编码表进行加密,结果为“皮皮卡丘皮卡”,我规定把每一个编码表对应的文本叫做“一节”。其中的“卡丘”就是两个字符之间的“分隔符”。这个加密结果就有三节分别是“皮皮”、“卡丘”、“皮卡”。我把编码表分为两类一类是“数字表示类”,用于表示十六进制,另一类是“流程控制类”,用于美化和分类字符串。这一步是简单的,我们可以在Python中定义两个字典(dict):普通字典和拓展字典,来保存我们的编码表。
另外我们还要在定义“白名单字符串”和“白名单句子”,用于存储一些我们不希望被加密的文本,像是标点符号和“皮卡丘”之类的字符串。而解密字典,就是通过“zip()”函数将两个加密字典的值(value)和项(key)互相调换。体现在代码中就是如下图所示的那样。
加密算法设计
接着可以正式设计加密算法了。首先我们要知道我们已知的信息,我们给出一段要加密的内容(我们称作“明文”),明文是一串字符串,我们可以通过Python中的“len()”函数来获取到明文的长度。我们先使用“for循环”依次遍历字符串(因为Python编程时默认使用的是“utf-8”的编码格式,所以中文仅占一个字节。),并把取出循环中的中文字符串取出十六进制的编码,再通过我们设计编码表进行转换。
在设计的过程中,我查阅了资料,发现Python想要取出一个字符的对应编码可以使用“ord()”命令来取出。在我的实际测试后,一个新的问题又孕育而生了——“ord()”命令取出的是十进制的字符编码,而不是十六进制了。苦恼的时候,我又想到信息书上有介绍十进制和十六进制的互相转换,这下简单了,我们可以参照书上写出对应的代码。
在解决进制转化后,新的问题又来了,加密有时候会出现加密后的密文有太多重复的“括号”,我们要想办法删除这些括号。比如“丘皮(皮卡)(丘丘)(卡丘)卡丘”,我们可以使用文本替换的方法将“)(”替换成空白,最后结果就是“丘皮(皮卡丘丘卡丘)卡丘”会相对美观不少。
有时候也会出现类似于“皮皮皮皮皮卡卡卡 ”的密文,根据编码表我想要实现的密文是“皮皮~皮卡-”。在我此时有一个想法,我们写一个“美化函数”可以让程序把上一节和下一节进行比对,如果相同就用“~”替换,若结尾字符刚好可以作为下一节,下一节使用“-”代替。
我们也写一个算法的过程,并写出相对应的代码:
我们将算法写成代码并使用while循环遍历字符串中的每一节并与下节的字符进行比对:
我们将美化代码和加密代码融合一下,写出加密的最终代码(下文第一张图是循环中的算法图片,第二张图片是体现在代码中的算法):
在先前的测试中,发现标点符号也会被加密,且“皮卡丘”文本自身也会被加密,为了防止这些现象发生,我们在最开始设置了白名单符号与白名单句子。“(”、“)”、 “~”、 “-”由于本身是构成加密文本的,所以我们要把它们夹在“丘丘”之间表示不加密。这一步比较简单根据思路可以很轻松的写出代码。
加密的效果如下:
解密算法
解密就要逆着加密的思维来了,我们照例来写一个流程图。但是在此之前我们必须先分析一下如何“逆思维”。
首先,密文中会出现类似于“(”“)”的控制符,我们把括号里的内容称为“拓展模式”,定义一个拓展模式变量,遇到“(”使用拓展编码表,遇到“)”使用普通编码表。同样我们使用循环反复遍历密文中的内容,每次读取一个字符放入临时列表中,若临时列表已经达到了两个字符且刚好存在于我们定义的编码表之中,我们就通过编码表取出对应的数字。
其次,当遇到“卡丘”控制符时,将获取到的十六进制转化成十进制通过“chr()”函数取出对应的字符。我们在读取时需要考虑一个问题,我们加密时去除的十六进制是倒着取出的,所以在解密时,也要倒着把十六进制读取出来,所以想要获取到正确的十进制必须把十六进制“倒着”转换,比如正确的十六进制是“1 2”,但是实际上获取到的是“2 1”。所以我设计了一个函数进行转化:
最后,在把剩下的控制符进行同样的定义和操作。就可以写出这样的流程图:
对应的代码如下:
交互界面
为了让代码更便于用户的使用所以我们写一个简单的交互页面。由于这不是我们本次课题所要讲的内容,所以就简单的制作一下了。
作品展示
总结反思
这个程序是来自我的一个小小的想法,我觉得最让我寻味的就是研究程序算法时我的纠结与思考。根据这次的设计下来,我认为程序设计分为三个大类,分别是“想法的实现”“算法的设计”和“代码的编程”。在设计过程中我征求了老师的想法以及同学们的建议,唯有不断在设计中纠错才可以设计出一个程序。
作品下载
说明:张以赏的网名为“我叫以赏”。在写论文时,并一同制作了视频,源码先放在码云和Github上开源。
视频思路呈现:https://www.bilibili.com/video/BV1JZ4y1V7JZ
码云开源:https://gitee.com/wojiaoyishang/pikachu-method
Github开源:https://github.com/wojiaoyishang/pikachu-method