今天来学习使用Python实现对任意文件进行AES加密。Python强大之处一是表现在语法简单,内容小巧,却可以实现复杂的程序功能;二是其优秀的跨平台能力,尤其涉及系统API调用时,统一封装为PythonAPI,我们所需要的仅仅是在运行机器上有Python解释器;三是丰富的库模块,使得我们可以使用Python实现多种多样的功能。所有的这一切,都使得我们摆脱程序开发时的细枝末节,而将重点放在程序逻辑和技术实现之上。我们准备使用Python来对一个文件进行AES加密,当然我们可以自己来实现这个加密函数(其实推荐C/C++的实现,因为速度快),但是我们完全可以调用现成的模块。这里我们使用的模块是PyCrypto。
一、关于PyCrypto
由于我们今天主要调用PyCrypto库来实现加密,所以这里还是稍微做些介绍吧!PyCrypto是一个免费的加密算法库,支持常见的DES、AES加密以及MD5、SHA各种HASH运算。我们可以在其官方主页下载最新版本:https://www.dlitz.net/software/pycrypto/ ,我编写程序时最新的是v2.6.1,下载之后得到一个zip的发布包,其中提供了setup.py文件,可以知道该程序包是使用Distutils分发的,基本的命令应该是:
python setup.py build
python setup.py install
如果你的系统时Linux,那么恭喜你可以轻松地完成上面的安装过程,当然你的系统上应当有Python2;如果你的系统是Winodws7,那么恭喜你和楼主一样,需要在Windows上重新编译该包了。具体的过程比较繁琐,比如设置系统PATH变量,更改编译器MSVC设置等,这里给大家推荐一篇详细的安装教程:http://blog.victorjabur.com/2011/06/05/compiling-python-2-7-modules-on-windows-32-and-64-using-msvc-2008-express/ ,如果你打不开,那么恭喜你需要“翻墙”才行了。当然为诸多不方便上网或者不方便阅读的童鞋,我也准备了两个Windows下的自动配置包程序,但是是针对win7下的python2.7和PyCrypto2.6.1的,编译器使用的是VS2008,如果你的也是这个版本,可以拿来直接用了:
pycrypto.zip
(872.68 KB, 下载次数: 0)
这些工作都做完之后,在PowerShell中启动python,输入import Crypto运行,如果没有提升错误则说明安装PyCrypto成功。PyCrypto中包含了许多加密方法,我们可以查阅官方文档:https://www.dlitz.net/software/pycrypto/api/current/ ,比如DES加密就包含说明+使用方法+函数参数说明:
二、AES加密小程序
这部分我们来对一个文件(任何类型)进行加密,这里给出一个测试程序,虽然功能尚未完善,但是已经可以实现针对文件的AES加密。按照我们以往的惯例,我们先给出实现的代码,然后再逐行讲解。
# -*- coding: cp936 -*-
#A Test to Return a AES-File of a Common File
from Crypto.Cipher import AES
from Crypto import Random
import binascii
def AES_File(fs):
key = b'1234567890!@#$%^' #16-bytes password
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
print 'if fs is a multiple of 16...'
#if fs is a multiple of 16
x = len(fs) % 16
print 'fs的长度是: ', len(fs)
print 'The num to padded is : ', x
if x != 0:
fs_pad = fs + '0'*(16 - x) #It shoud be 16-x not
print 'fs_pad is : ', fs_pad
print len(fs_pad)
print len(fs_pad)%16
msg = iv + cipher.encrypt(fs_pad)
print 'File after AES is like...', binascii.b2a_hex(msg[:10])
return msg
#Create a Test Src File and Get FileSteam
fs = open('test', 'w+')
fs.write('啊,我爱你,我的祖国!')
fs.write('凌晨三时开始进攻!')
fs.seek(0,0)
fs_msg = fs.read()
print fs_msg
fs.close()
#Crypt Src FileStream
fc = open('fc', 'wb')
fc_msg = AES_File(fs_msg)
fc.writelines(fc_msg)
fc.close()
raw_input('Enter for Exit...')
-1. 第一行的‘-*-coding:cp936 -*-’用于告诉Python解释器源码文件的编码方式,Python的默认方式是ASCii的,但是由于代码中出现了汉字,因此运行时解释器会提示我们是否要注明解码的方式,也可以使用'coding:utf-8';
-2. 第四行到第六行主要引入一些必要的模块,Crypto.Cipher模块中的AES模块以及Crypto中的Random模块,binascii模块为查看二进制下的数据提供了各种方法。
-3. 第八行到二十四行主要实现调用AES加密API的函数,我们命名为AES_File(),其中:
第九行用于指定AES加密的初始密钥,根据AES规范,可以是16字节、24字节和32字节长,这里我们使用了一个16字节的初始密钥,其实完全可以由用户输入的口令+salt获得;
第十行是用于生成iv,这里使用了Crypto模块中的Random模块,读取其16字节的数据作为iv的值,AES的分块大小固定为16字节;
第十一行用于生成了加密时需要的实际密码,主要使用了AES.new(key, AES.MODE_CBC,iv)函数,key和iv由前两步生成,这步可以指定加密模式,这里选择的是CBC模式;
第十二到第二十一行主要用于判断数据长度是否为16字节块的整数倍,从而进行适当的Padding,这里的关键是利用'%'运算判断是否是16字节的整数倍,然后在尾部追加(16-x)个填充字符;
其实这里还有一个关键的问题,那就是Python中列表和字符串的转换问题。使用list()函数可以将字符串转换成列表,使用str()函数可以将列表转换成字符串,但是前后的转换并不是等价的,比如:
可以看到a与c并不相等,将字符串转换成列表时,二者还是元素个数相等的,但是将列表转换成字符串时,会包含进“无关字符”,即'[]'、' '(空格)等,因此元素个数会发生改变。因此列表和字符串是不等价的转换。之所以想到了这个问题,是因为自己在考虑填充时开始想利用列表的append()方法写个循环,结果行不通,最后还是利用了序列乘法予以了解决。
-4. 第二十二行使用生成的cipher对象的encrypt方法加密文件流,得到密文文件流msg,注意这里与iv进行了一次异或,另一个需要注意的是encrypt方法的输入和输出都是一个字符串;
-5. 第二十三行主要是为了调试的需要,导入binascii模块查看密文文件流的前10个字节,每个二进制字节以十六进制的形式表示;
-6. 第二十七行到第三十三行的工作是生成一个明文文件,获取其明文数据流,这里可以直接从打开的文件中读取,不过为了测试的需要,这里临时写入一个文件,因此复制数据流的时候记得重置指针到文件开头,即fs.seek(0, 0);
-7. 第三十五行到第三十九行主要是将获取的明文数据流调用AES加密得到密文数据流,然后关闭文件;
好了,现在我们看看结果,这里指定编码的时候不影响程序执行,但是会影响程序的print结果,第一次使用utf-8编码,第二次使用ascii编码:
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com