如何仅读取文件片段检测RAR/ZIP压缩文件是否受密码保护?
检测ZIP/RAR文件是否加密(仅读取少量文件片段)
现有基于zipfile和rarfile库的testzip()/testrar()方法需要读取整个文件,不适合处理大型压缩文件。我们可以通过解析压缩文件的头部结构,仅读取前几KB数据来判断是否加密,无需加载完整文件。
实现思路
ZIP文件
ZIP文件的每个条目都包含局部文件头,其中的通用位标记(General Purpose Bit Flag)第0位为加密标识:如果该位为1,说明条目被加密。我们只需读取文件开头的局部文件头,检查这个标记即可。
RAR文件
RAR文件由多个块组成,文件头块中包含加密标记:
- 旧版RAR(v4及以下):块头的
Flags字段第3位表示加密 - RAR 5.0:块头的
Flags字段第2位表示加密
只需读取文件开头的块头信息,即可判断是否加密。
代码实现
import struct def is_zip_encrypted_stream(file_obj): """从文件流中检测ZIP是否加密(仅读取前几KB)""" try: # 读取ZIP局部文件头的前30字节(足够获取通用位标记) header = file_obj.read(30) if len(header) < 30: return False # 解析通用位标记(偏移量6,2字节小端) general_purpose_flag = struct.unpack('<H', header[6:8])[0] # 第0位为1表示加密 return (general_purpose_flag & 0x0001) != 0 except Exception: return False def is_rar_encrypted_stream(file_obj): """从文件流中检测RAR是否加密(仅读取前几KB)""" try: # 读取RAR文件头的前7字节(判断版本) header = file_obj.read(7) if len(header) < 7: return False # 检查RAR签名(RAR v4: 0x526172211A0700;RAR v5: 0x526172211A0701) signature = struct.unpack('<7B', header) if signature[:6] != (0x52, 0x61, 0x72, 0x21, 0x1A, 0x07): return False is_rar5 = (signature[6] == 0x01) if is_rar5: # RAR 5.0:读取块头的Flags字段(偏移量10,4字节小端) file_obj.seek(10) flags = struct.unpack('<I', file_obj.read(4))[0] # 第2位为1表示加密 return (flags & 0x00000004) != 0 else: # RAR v4:读取块头的Flags字段(偏移量8,2字节小端) file_obj.seek(8) flags = struct.unpack('<H', file_obj.read(2))[0] # 第3位为1表示加密 return (flags & 0x0008) != 0 except Exception: return False # 示例用法(流式读取本地文件) def check_encrypted_file(file_path): with open(file_path, 'rb') as f: # 先判断文件类型 f.seek(0) magic = f.read(4) f.seek(0) if magic.startswith(b'PK\x03\x04'): return is_zip_encrypted_stream(f) elif magic.startswith(b'Rar!'): return is_rar_encrypted_stream(f) else: return False # 测试 zip_path = "example.zip" rar_path = "example.rar" print(f"{zip_path} 是否加密: {check_encrypted_file(zip_path)}") print(f"{rar_path} 是否加密: {check_encrypted_file(rar_path)}")
说明
- 流式兼容:该方法支持从任意可读取的字节流(如上传时的临时流、网络流)中读取,无需保存完整文件到磁盘
- 性能优势:仅读取前几KB数据,处理大型压缩文件时几乎无性能损耗
- 局限性:
- ZIP文件:如果是分卷ZIP或第一个条目未加密但后续条目加密,会出现误判(但这类场景较少见)
- RAR文件:仅检测主文件头的加密标记,部分特殊分卷或加密方式可能需要额外处理,但覆盖绝大多数常规场景
内容的提问来源于stack exchange,提问作者Mehrdad HMT
相关产品推荐
相关产品推荐

