实现功能,递归遍历当前目录下的所有文件加密和解密
- 加密脚本(encrypt_files.py)
py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import random
from pathlib import Path
# 核心配置(加密解密需保持一致)
HEADER_BYTES = 16 # 修改文件开头16个字节(足够让大部分文件失效)
BACKUP_MARK = b"===FILE_HEADER_BACKUP===" # 备份标识
ENCRYPT_SUFFIX = [".bat", ".py"] # 跳过加密的文件类型
LOCK_SUFFIX = ".lock" # 加密后追加的后缀
def encrypt_files():
"""加密文件:修改开头关键字节+追加.lock后缀,使文件无法正常打开"""
current_dir = os.getcwd()
print(f"开始加密目录:{current_dir}")
print("-" * 60)
file_count = 0
skipped_count = 0
for file_path in Path(current_dir).rglob("*"):
# 跳过目录、指定后缀的文件、已加密(带.lock)的文件
if (not file_path.is_file()
or file_path.suffix.lower() in ENCRYPT_SUFFIX
or str(file_path).endswith(LOCK_SUFFIX)):
skipped_count += 1
continue
try:
file_size = os.path.getsize(file_path)
# 跳过空文件
if file_size == 0:
print(f"空文件,跳过:{file_path}")
continue
with open(file_path, "rb+") as f:
# 1. 检查是否已加密(尾部有备份标识则跳过)
f.seek(0, os.SEEK_END)
file_len = f.tell()
mark_len = len(BACKUP_MARK)
if file_len > mark_len + HEADER_BYTES:
f.seek(-(mark_len + HEADER_BYTES), os.SEEK_END)
tail_content = f.read()
if tail_content.endswith(BACKUP_MARK):
print(f"已加密,跳过:{file_path}")
continue
# 2. 读取开头关键字节(备份)
f.seek(0)
header_data = f.read(HEADER_BYTES)
if len(header_data) < HEADER_BYTES:
continue # 极小文件跳过
# 3. 生成随机字节覆盖开头(使文件失效)
random_bytes = bytes([random.randint(0, 255) for _ in range(HEADER_BYTES)])
f.seek(0)
f.write(random_bytes)
# 4. 尾部追加备份数据+标识
f.seek(0, os.SEEK_END)
f.write(header_data + BACKUP_MARK)
# 5. 重命名文件,追加.lock后缀
new_file_path = str(file_path) + LOCK_SUFFIX
os.rename(file_path, new_file_path)
file_count += 1
print(f"加密完成:{new_file_path}")
except PermissionError:
print(f"权限不足,跳过:{file_path}")
except Exception as e:
print(f"处理失败 {file_path}:{str(e)}")
print("-" * 60)
print(f"加密完成!共加密:{file_count} 个,跳过:{skipped_count} 个")
if __name__ == "__main__":
if sys.platform != "win32":
print("警告:该脚本建议在Windows系统运行!")
encrypt_files()
input("按回车键退出...")
- 解密脚本(decrypt_files.py)
py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
from pathlib import Path
# 必须和加密脚本的配置完全一致!
HEADER_BYTES = 16
BACKUP_MARK = b"===FILE_HEADER_BACKUP==="
ENCRYPT_SUFFIX = [".bat", ".py"] # 跳过解密的文件类型
LOCK_SUFFIX = ".lock" # 加密后追加的后缀
def decrypt_files():
"""解密文件:移除.lock后缀+还原开头关键字节,恢复文件正常"""
current_dir = os.getcwd()
print(f"开始解密目录:{current_dir}")
print("-" * 60)
file_count = 0
skipped_count = 0
# 只遍历带.lock后缀的文件(精准匹配加密文件)
for locked_file_path in Path(current_dir).rglob(f"*{LOCK_SUFFIX}"):
# 跳过目录、指定后缀的文件(即使带.lock也跳过)
original_suffix = str(locked_file_path).replace(LOCK_SUFFIX, "").split(".")[-1]
if (not locked_file_path.is_file()
or f".{original_suffix}".lower() in ENCRYPT_SUFFIX):
skipped_count += 1
continue
# 原始文件名(移除.lock后缀)
original_file_path = str(locked_file_path).replace(LOCK_SUFFIX, "")
try:
file_size = os.path.getsize(locked_file_path)
if file_size == 0:
print(f"空文件,跳过:{locked_file_path}")
continue
with open(locked_file_path, "rb+") as f:
# 1. 检查是否有加密备份标识
f.seek(0, os.SEEK_END)
file_len = f.tell()
mark_len = len(BACKUP_MARK)
total_backup_len = HEADER_BYTES + mark_len
if file_len < total_backup_len:
print(f"未加密,跳过:{locked_file_path}")
continue
# 2. 读取尾部的备份数据和标识
f.seek(-total_backup_len, os.SEEK_END)
backup_data = f.read(HEADER_BYTES)
mark_data = f.read(mark_len)
if mark_data != BACKUP_MARK:
print(f"未加密,跳过:{locked_file_path}")
continue
# 3. 还原开头关键字节
f.seek(0)
f.write(backup_data)
# 4. 截断文件,删除尾部的备份数据和标识
f.seek(file_len - total_backup_len)
f.truncate()
# 5. 移除.lock后缀,恢复原始文件名
os.rename(locked_file_path, original_file_path)
file_count += 1
print(f"解密完成:{original_file_path}")
except PermissionError:
print(f"权限不足,跳过:{locked_file_path}")
except Exception as e:
print(f"处理失败 {locked_file_path}:{str(e)}")
print("-" * 60)
print(f"解密完成!共解密:{file_count} 个,跳过:{skipped_count} 个")
if __name__ == "__main__":
if sys.platform != "win32":
print("警告:该脚本建议在Windows系统运行!")
decrypt_files()
input("按回车键退出...")