Wolf从零学编程-用Python打造简单加密程序(四)

来源:互联网 发布:windows网络编程 视频 编辑:程序博客网 时间:2024/06/03 04:22
 分类:

目录(?)[+]

有了一点点RSA的知识作为基础,就可以开着Python-rsa的文档撸代码了。这一篇先单独完成了RSA对DES密钥及大文件的加解密,然后分步实现混合加密过程。

先要吐槽自己,我发现自己在写的过程中,RSA和rsa、DES和des、HASH和hash各种混用,真是不好的习惯,一定要形成自己的使用习惯,不管用大写还是小写,要从始而终。

一、加密DES密钥

现阶段RSA密钥最小建议是1024位,去掉PKCS的11个填充字节,可加密117字节明文,而DES密钥只有8字节,更常使用的3-DES密钥是16字节或24字节,AES是16、24、32个字节密钥,因此RSA可加密任何对称算法的密钥。

在编写DES时,我使用了CBC模式,这个模式要求收发双方共享一个初始值IV,因此实际上我的DES密钥可以算作16字节。

import pyDesimport rsa# rsa加密DES密钥'''生成rsa密钥对,输入des密钥和初始值并将二者连起来,编码后用接收方公钥加密,密文写入加密文件'''(pub_key,priv_key)=rsa.newkeys(1024)des_key = '1234qwer'des_IV = 'asdfzxcv'des = des_key + des_IVenc_des = rsa.encrypt(des.encode('utf-8'),pub_key)with open('enc_file.rsa','wb') as f:    f.write(enc_des)    f.close()# 解密文件'''密文是二进制写入,所以对enc_file二进制读出,解密后进行解码,只需要文本模式写入dec_file即可'''with open('enc_file.rsa','rb') as f1:    with open('dec_file.txt','w') as f:        f.write(rsa.decrypt(f1.read(),priv_key).decode('utf-8'))        f.close()    f1.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

运行后生成了128字节的enc_file和16字节的dec_file

mark

解密内容正确

mark

二、用RSA加密文件

如果不在乎延迟,可以使用RSA加密大文件,它的原理就是把文件拆分成多个117字节的分组,各组按顺序加密后再连接在一起,解密同样先分组,解密后连接成明文。注意,加密后密文文件会比明文大,因为每一组都会多11个字节填充。

python-rsa提供了对大文件加密的方法

from rsa.bigfile import *with open('test.doc','rb') as infile, open('enc_file.rsa','wb') as outfile:    encrypt_bigfile(infile,outfile,pub_key)
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

简单的两行代码,就可以实现文件加密。解密的函数是decrypt_bigfile(),参数和加密函数是一模一样的。

from rsa.bigfile import *with open('enc_file.rsa','rb') as infile, open('dec_test.doc','wb') as outfile:    encrypt_bigfile(infile,outfile,pub_key)
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

三、混合加密

混合加密就是发送方使用DES密钥加密文件形成密文2,用RSA加密DES密钥形成密文1,将密文1和密文2写入密文文件后发送。接收方先读取密文1,解密后用得到的DES密钥解密密文2。

先看加密过程:

import pyDesimport rsa# RSA加密DES密钥(pub_key,priv_key)=rsa.newkeys(1024)   # 生成rsa密钥对des_key = '1234qwer'                   # 输入8字节des密钥des_IV = 'asdfzxcv'                    # 输入8字节CBC模式初始值des_data = des_key + des_IV            # 将上面二者连起来enc_des = rsa.encrypt(des_data.encode('utf-8'),pub_key)    # 加密连接后的字符串des = pyDes.des(des_key,pyDes.CBC,des_IV,pad=None,padmode=pyDes.PAD_PKCS5) #定义des实例# DES加密文件with open('test.doc','rb') as f:    data = f.read()    enc_data = des.encrypt(data)    f.close()# 密文写入with open('enc_file.mix','wb') as f:          # mix无任何实际意义,纯粹是自己胡编    [f.write(x) for x in (enc_des,enc_data)]    # write()只接受一个参数,使用列表生成式将密钥密文和文件密文写入,也可拆开写    f.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

这个代码简单的运行是没有问题的,需要先搞清楚明文文件和密文文件体积的关系。

mark

可以看到,密文比明文大了136个字节,这里面有RSA的功劳,也少不了DES的事儿。

  1. des_data是16字节,被RSA加密后变为1024bit即128字节,然后被写入密文文件的开头
  2. 剩下8字节来自DES。因为明文刚好是8的倍数,所以填充了一个分组即8字节;若明文是27135字节,则只会填充一个字节。这种填充方法是PKCS5的规定。
      4. Concatenate M and a padding string PS to form an encoded         message EM:                 EM = M || PS ,         where the padding string PS consists of 8-(||M|| mod 8) octets         each with value 8-(||M|| mod 8). The padding string PS will         satisfy one of the following statements:                 PS = 01, if ||M|| mod 8 = 7 ;                 PS = 02 02, if ||M|| mod 8 = 6 ;                 ...                 PS = 08 08 08 08 08 08 08 08, if ||M|| mod 8 = 0.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这段话最下面3行直截了当的告诉我:离8的倍数差1,就填充1个01;差2,就填充2个02;如果刚好是8的倍数,就填充8个08。这里的01、02、08都是十六进制的,08换成二进制就是00001000,为1个字节。

解密过程

解密中将密钥密文和文件密文分别读取,先解密得到DES密钥和初始值,再用其解密文件。

以下代码和加密代码写在了一个文件里,所以开始的赋值都没有:

#分别读取DES密钥密文和明文密文with open('enc_file.mix','rb') as f:    wait_dec_des,wait_dec_data = [f.read(x) for x in (128,-1)]    #密钥密文128字节,剩下的是明文密文    f.close()#解密DES密钥和初始值dec_des = rsa.decrypt(wait_dec_des,priv_key).decode('utf-8')des_key,des_IV = dec_des[:8],dec_des[8:]#此处直接把解密得到的key和IV与输入值同名覆盖,因为key和IV目前是全局变量#不覆盖的话后面解密会直接使用,无法看出解密的key和IV是否正确#解密文件with open('dec_test.doc','wb') as f:    dec_data = des.decrypt(wait_dec_data)    f.write(dec_data)    f.close()
  • 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

解密文件与源文件的大小是一致的:

mark

内容也是相同的:

mark

不得不说,渣电脑调这段代码请创建test.txt,会快很多。并且在最后部分千万不要试图print(dec_data),不然绝对等到花儿也谢了。

我估计自己会花挺长时间调整RSA,这篇就到这里~下一篇贴出RSA部分的次终极形态

阅读全文
0 0
原创粉丝点击