版权声明:本文为博主原创文章,转载请注明出处和链接。
之前我分步完成了RSA加密DES密钥、RSA加密大文件、DES和RSA混合加密,在这一篇要把这些功能以及数字签名和验证整合起来。
血淋淋的事实告诉我们,如果要写博客,就一定要在敲代码的同时写!不然就会像我现在这样,看着改完的代码只能回忆起当初遇到的问题,却实在不愿意重现当时的场景。列出的问题也都没有实例和截图支撑。
在整合过程中遇到了以下问题:
1.文件路径
我的目标是让用户选择文件,程序自己识别出路径。可我目前没有UI,自己调的时候只能手动输入,我希望可以输入原始的路径,程序为其去转义。
这时发现问题:把路径写在代码里,就必须以去掉转义的形式写入,否则根本不可能执行下一行代码;但是用户是不可能去掉转义的,他们选择的必然是普通的windows文件路径。(如何去转义)例如:
- 1
- 1
这行代码是无法执行的,只有在这时就去转义才可以。
之后我尝试使用input():
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
Python已经善解人意的帮我转换好了,文件路径的问题就暂时这么解决。
2.密钥文件
同样我希望用户选择密钥文件,程序自动读取其中的密钥,那么我首先需要生成密钥文件。起初我的想法很简单,把生成的公钥和私钥分别写进密钥文件中,加解密时读取就好了,我的代码是这样的:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
执行后是这样的:
- 1
- 2
- 3
- 1
- 2
- 3
从外表看起来一模一样,但是调试加密大文件时,我读出的公钥并不能使用,代码报出了:
TypeError: Public key required, but got ‘PublicKey(110033558209536852961104748072325524170015000991015977032379850324526371006049699376882883630502167366123178380691560970530014782054865549746026675957941702625202522315342068759285591171619104078716050913217288395405360879790773854123724004013945588678161196488714307142003225792589258676722681038564826071359, 65537)’
此时我的内心有一万头草泥马跑过~~~又回头去翻python-rsa的文档,原来作者提供了相应的储存和读取方法,使用save_pkcs1()和load_pkcs1()圆满解决,见base.py代码。
3.部分方法重复使用
- 密钥文件生成,一次生成文件可在RSA加密、混合加密、签名中多次使用
- 密钥读取,每次RSA加解密操作都会使用
- 新文件命名,任何加解密操作都会使用
于是把这几个功能拿出来,简单修改后丢进了一个base.py模块
4.汉字解码问题
代码中明明已经声明了’utf-8’编码,但就死活不让输入中文,报”UnicodeDecodeError:’utf-8’ codec can’t decode “,这个问题遇到过两次:
- 第一次,第一天关机,第二天再运行就不报错了
- 第二次,当场新建个文档,把模块代码完全复制过去运行,不报错
5.DES密钥密文长度
如果我规定RSA只能选择1024位,就没有这个问题,但很可惜,我不仅没这么规定,甚至只给出1024、2048、3072、4096这么几个没什么约束的建议,我总不能阻止用户选择1020位,那么密文就是1020位的,于是问题产生了:
在混合加密中,如何正确的从密文文件中读出DES密钥密文?
经试验,1020位RSA加密后的密文是128字节!没错,和1024位加密后长度一致;也就是说,从1017到1024位的RSA产生的密文都是128字节,1016位产生的密文是127字节。于是我写了一个方法计算密钥密文的长度。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
n转换成二进制后以’0b’开头,因此位数要减掉2。
6.DES初始值
DES的密钥只有8个字节,但是一旦选择CBC模式,就还需要选择一个初始值,并且解密时也必须输入相同的初始值,这等同于让用户记住16个字节的密钥。我考虑能不能让初始值随机生成,并随密文一起传送,解密时自动使用,这样用户也省事。
问题是初始值是解密时使用的,我只能发送一个文件,又不能把初始值明文写在密文文件里,在DES加密中暂时只能让用户输入了。
不过在混合加密里是完全可以实现的,密钥和随机生成的初始值一起被加密,接收方解密密钥后直接用来解密文件。因此在混合加密中,初始值选择随机生成8字节的字母和数字组合。
- 1
- 2
- 3
- 1
- 2
- 3
看了一遍代码,只记得这几个问题了。
7.签名和验证
目前逻辑功能还差一个签名和验证,python-rsa提供了‘MD5’、‘SHA-1’、‘SHA-256’、‘SHA-384’ 、‘SHA-512’等hash算法,以及简单的方法sign()和verify()。
先贴代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 代码中涉及读写文件的,我使用了全部’rb’的笨办法
- hash算法目前规定了使用SHA-1,有了UI后可以做成选项
简单的测试如下:(因为全篇没图,这个位置我强行贴图了)
Too young!作者的代码里没有’return False’,在验证中有多个步骤,任何一个步骤失败都会直接报’Verification failed’。
于是我把验证改成简单的异常捕获:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
这次可以打印危险提示了
到这里为止,程序的所有功能模块就完成了,代码都放在了我的github仓库,接下来是漫长的UI学习。