1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
| import os
import base64
from cryptography.fernet import Fernet, InvalidToken
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
def generate_fernet_key(password: str, salt: bytes = b'system_design_salt_123') -> bytes:
"""
将易记密码转换为符合Fernet要求的32字节URL安全base64密钥
Args:
password: 原始密码(如"password")
salt: 盐值(增加安全性,建议自定义)
Returns:
符合Fernet要求的32字节URL安全base64密钥
"""
# 1. 将密码转换为字节串
password_bytes = password.encode('utf-8')
# 2. 使用PBKDF2HMAC进行密钥派生(比单纯hash更安全)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32, # Fernet要求32字节
salt=salt,
iterations=100000, # 迭代次数,越高越安全(但稍慢)
backend=default_backend()
)
key = kdf.derive(password_bytes)
# 3. 编码为URL安全的base64格式(Fernet要求的格式)
fernet_key = base64.urlsafe_b64encode(key)
return fernet_key
def process_files(
folder_path: str,
password: str,
mode: str = 'encrypt', # 'encrypt' 加密 / 'decrypt' 解密
file_ext: str = '.md', # 目标文件类型
encrypt_suffix: str = '.encrypted' # 加密文件后缀
):
"""
加密/解密指定文件夹中的目标文件
Args:
folder_path: 目标文件夹路径
password: 加密/解密密码
mode: 操作模式(encrypt/decrypt)
file_ext: 要处理的文件扩展名(如.md)
encrypt_suffix: 加密文件的后缀(解密时会移除)
"""
# 验证文件夹是否存在
if not os.path.isdir(folder_path):
print(f"错误:文件夹 '{folder_path}' 不存在!")
return
# 验证操作模式
if mode not in ['encrypt', 'decrypt']:
print("错误:mode只能是 'encrypt' 或 'decrypt'")
return
# 生成Fernet密钥
try:
key = generate_fernet_key(password)
fernet = Fernet(key)
print(f"✅ 密钥生成成功(基于密码:{password})")
except Exception as e:
print(f"❌ 密钥生成失败:{str(e)}")
return
# 遍历文件夹中的文件
processed_count = 0
failed_files = []
for filename in os.listdir(folder_path):
file_path = os.path.join(folder_path, filename)
# 跳过文件夹,只处理文件
if os.path.isdir(file_path):
continue
# 筛选目标文件(加密:匹配扩展名;解密:匹配加密后缀)
if mode == 'encrypt':
if not filename.lower().endswith(file_ext.lower()):
continue # 只处理指定扩展名的文件
target_file = file_path + encrypt_suffix # 加密后的文件名
else:
if not filename.endswith(encrypt_suffix):
continue # 只处理带加密后缀的文件
# 解密:移除加密后缀,还原原文件名
target_file = filename[:-len(encrypt_suffix)]
target_file = os.path.join(folder_path, target_file)
# 跳过已存在的目标文件(避免覆盖)
if os.path.exists(target_file):
print(f"⚠️ 跳过:目标文件 '{target_file}' 已存在,避免覆盖")
continue
# 读取原文件内容
try:
with open(file_path, 'rb') as f:
content = f.read()
except Exception as e:
print(f"❌ 读取文件失败 '{file_path}':{str(e)}")
failed_files.append(file_path)
continue
# 加密/解密处理
try:
if mode == 'encrypt':
processed_content = fernet.encrypt(content)
print(f"🔒 加密中:{filename} -> {os.path.basename(target_file)}")
else:
processed_content = fernet.decrypt(content)
print(f"🔓 解密中:{filename} -> {os.path.basename(target_file)}")
except InvalidToken:
print(f"❌ 解密失败 '{file_path}':密码错误或文件已被篡改")
failed_files.append(file_path)
continue
except Exception as e:
print(f"❌ 处理失败 '{file_path}':{str(e)}")
failed_files.append(file_path)
continue
# 写入处理后的内容
try:
with open(target_file, 'wb') as f:
f.write(processed_content)
processed_count += 1
except Exception as e:
print(f"❌ 写入文件失败 '{target_file}':{str(e)}")
failed_files.append(file_path)
continue
# 输出处理结果
print("\n" + "="*50)
print(f"处理完成!")
print(f"✅ 成功处理文件数:{processed_count}")
if failed_files:
print(f"❌ 失败文件数:{len(failed_files)}")
print(f"失败列表:{failed_files}")
else:
print(f"🎉 所有目标文件处理成功!")
if __name__ == "__main__":
# -------------------------- 配置参数 --------------------------
# 你需要根据实际情况修改以下参数
FOLDER_PATH = "./System-Design" # 要处理的文件夹路径
PASSWORD = "password123" # 易记密码(自定义)
OPERATION_MODE = "encrypt" # encrypt=加密 / decrypt=解密
TARGET_FILE_EXT = ".md" # 要处理的文件类型(如.md/.txt)
ENCRYPT_SUFFIX = ".encrypted" # 加密文件后缀(解密时自动移除)
# --------------------------------------------------------------
# 执行文件处理
process_files(
folder_path=FOLDER_PATH,
password=PASSWORD,
mode=OPERATION_MODE,
file_ext=TARGET_FILE_EXT,
encrypt_suffix=ENCRYPT_SUFFIX
)
|