前一篇文章介绍了如何用python自动解压缩加密的zip文件,
但是有一个问题,在服务器端脚本在解加密zip文件之前,需要检测其是否是加密文件,若是,则询问密码,结合密码解压缩;如果不是,则则直接解压缩。本文的灵感取自一篇文章《Linux zip 加密压缩》
所有加密的zip文件头8个字符好像都是这个样子的
0000000 4b50 0403 0014 0009
0000008
具体为什么会是这个格式,就不得而知了,需要以后做详细的研究。
还有另一个方法,就是通过python的 open() read()方法读取前十个字节,显示是十六进制数。经过测试,好像所有的zip文件前十个字节都是相同的,但是加密和未加密的文件则不同:
加密zip文件:'PK\x03\x04\x14\x00\t\x00\x08\x00'
未加密zip文件:'PK\x03\x04\x14\x00\x00\x00\x08\x00'
其中前四个字节‘PK\x03\x04' 是文件头标记。往后两个字节 ‘\x14\x00' 是解压文件所需的pkware的版本,再后来两个字节 '\x00\x00' 或者 '\t\x00' 是全局方式位标记,最后两个字节 '\x08\x00' 是压缩方式。
这里全局方式位置标记由于是否加密而有所不同,所以只需要比较这两个十六进制数字是否相等即可。
第二种方法还稍微快一些。
顺便说一下,博客园的文件上传系统只能上传zip文件,但是检测模块只是对文件后缀做分析。
使用linux 下的hexdump十六进制查看器的代码如下:
1 #!/usr/bin/env python
2 #_*_coding=utf-8_*_
3
4 importsubprocess5 importgetopt6 importsys7 importos8
9 if __name__=='__main__':10 try:11 opts, args = getopt.getopt(sys.argv[1:], "")12 exceptgetopt.GetoptError, err:13 printstr(err)14 sys.exit(2)15 #check if the zipfile exists
16 for arg inargs:17 if notos.path.isfile(arg):18 print "%s does not exists!" %arg19 sys.exit(2)20 #verify the zipfile
21 f = subprocess.Popen(['hexdump', '-n', '8', "%s" % arg], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0].rstrip()22 if f[23:27]=='0009':23 print "%s 是加密文件" %arg24 elif f[23:27]=='0000':25 print "%s 不是加密文件" %arg26 else:27 print "error"
2. 使用python自带的方法判断的代码如下:
1 #!/usr/bin/env python
2 #_*_coding=utf-8_*_
3
4 importsubprocess5 importgetopt6 importsys7 importos8
9 if __name__=='__main__':10 encryptedzip='\t\x00'
11 unencryptedzip='\x00\x00'
12 zipfile='PK\x03\x04'
13 try:14 opts, args = getopt.getopt(sys.argv[1:], "")15 exceptgetopt.GetoptError, err:16 printstr(err)17 sys.exit(2)18 #check if the zipfile exists
19 for arg inargs:20 if notos.path.isfile(arg):21 print "%s does not exists!" %arg22 sys.exit(2)23 #verify the zipfile
24 try:25 f=open("%s" % arg, "rb")26 top8hex=f.read(8)27 if top8hex[6:] ==encryptedzip:28 print "%s 是加密文件" %arg29 elif top8hex[6:] ==unencryptedzip:30 print "%s 不是加密文件" %arg31 elif not top8hex[:4] ==zipfile:32 print "%s 不是zip文件!" %arg33 exceptIOError, err:34 printstr(err)35 finally:36 f.close()
以上两种方法虽然是命令行程序,但是同样可以运用到cgi中。
如果有人能提供更到位、更精确的分析方法,请赐教:)