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

有了一点点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 pyDes
import rsa

# rsa加密DES密钥
'''
生成rsa密钥对,输入des密钥和初始值并将二者连起来,编码后用接收方公钥加密,密文写入加密文件
'''
(pub_key,priv_key)=rsa.newkeys(1024)
des_key = '1234qwer'
des_IV = 'asdfzxcv'
des = des_key + des_IV
enc_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()

运行后生成了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)

简单的两行代码,就可以实现文件加密。解密的函数是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)

三、混合加密

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

先看加密过程:

import pyDes
import 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()

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

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.
                 

这段话最下面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()

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

mark

内容也是相同的:

mark

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值