设为首页 收藏本站
查看: 1335|回复: 0

[经验分享] Python【十二】:使用PyCrypto调用AES加密文件

[复制链接]
累计签到:77 天
连续签到:1 天
发表于 2014-8-14 08:48:39 | 显示全部楼层 |阅读模式
今天来学习使用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加密就包含说明+使用方法+函数参数说明:
26275986_14049750648WdU.jpg

二、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()函数可以将列表转换成字符串,但是前后的转换并不是等价的,比如:
26275986_14049761800DZY.jpg
   可以看到a与c并不相等,将字符串转换成列表时,二者还是元素个数相等的,但是将列表转换成字符串时,会包含进“无关字符”,即'[]'、' '(空格)等,因此元素个数会发生改变。因此列表和字符串是不等价的转换。之所以想到了这个问题,是因为自己在考虑填充时开始想利用列表的append()方法写个循环,结果行不通,最后还是利用了序列乘法予以了解决。
-4. 第二十二行使用生成的cipher对象的encrypt方法加密文件流,得到密文文件流msg,注意这里与iv进行了一次异或,另一个需要注意的是encrypt方法的输入和输出都是一个字符串;
-5. 第二十三行主要是为了调试的需要,导入binascii模块查看密文文件流的前10个字节,每个二进制字节以十六进制的形式表示;
-6. 第二十七行到第三十三行的工作是生成一个明文文件,获取其明文数据流,这里可以直接从打开的文件中读取,不过为了测试的需要,这里临时写入一个文件,因此复制数据流的时候记得重置指针到文件开头,即fs.seek(0, 0);
-7. 第三十五行到第三十九行主要是将获取的明文数据流调用AES加密得到密文数据流,然后关闭文件;
   好了,现在我们看看结果,这里指定编码的时候不影响程序执行,但是会影响程序的print结果,第一次使用utf-8编码,第二次使用ascii编码:
26275986_1404977487uFF9.jpg



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-23723-1-1.html 上篇帖子: Python【十一】:阶段小结 下篇帖子: Python【十三】:类的基础
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表