当前位置: 代码网 > it编程>前端脚本>Python > Python如何实现按文件夹加密解密其中文件

Python如何实现按文件夹加密解密其中文件

2025年04月25日 Python 我要评论
python实现按文件夹加密解密其中文件工具一个使用python实现的按文件夹加密解密其中文件的程序,包含gui界面和较为完善的功能。我们将使用pyqt6来创建gui,使用cryptography库进

python实现按文件夹加密解密其中文件工具

一个使用python实现的按文件夹加密解密其中文件的程序,包含gui界面和较为完善的功能。我们将使用pyqt6来创建gui,使用cryptography库进行加密操作。该程序用到一些模块/库:

pyqt6 库是第三方库,需要安装,用于创建图形用户界面(gui)的库。pyqt6的简介与安装,可参见pyside6 安装和简单界面开发过程详细介绍

cryptography 是第三方库,需要安装,用于加密和解密的库。

sys、os 和 base64是python自带的标准库模块,不需要安装。

运行效果

源码如下:

import sys
import os
from pyqt6.qtwidgets import (qapplication, qwidget, qpushbutton, qvboxlayout, 
                            qhboxlayout, qfiledialog, qlineedit, qlabel, qmessagebox,
                            qprogressbar, qtextedit, qsplitter)
from pyqt6.qtcore import qt, qthread, pyqtsignal
from pyqt6.qtgui import qfont, qcolor
from cryptography.fernet import fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import pbkdf2hmac
import base64
 
class cryptoworker(qthread):
    progress = pyqtsignal(int)
    finished = pyqtsignal()
    error = pyqtsignal(str)
    status = pyqtsignal(str)  # 新增状态信号
 
    def __init__(self, folder, password, mode):
        super().__init__()
        self.folder = folder
        self.password = password
        self.mode = mode  # 'encrypt' or 'decrypt'
 
    def run(self):
        try:
            key = self.get_key(self.password)
            fernet = fernet(key)
 
            total_files = sum([len(files) for r, d, files in os.walk(self.folder)])
            processed_files = 0
            
            self.status.emit(f"开始{'加密' if self.mode == 'encrypt' else '解密'}操作...\n")
 
            for root, dirs, files in os.walk(self.folder):
                for file in files:
                    file_path = os.path.join(root, file)
                    relative_path = os.path.relpath(file_path, self.folder)
                    
                    if self.mode == 'encrypt':
                        if file.endswith('.enc'):
                            self.status.emit(f"跳过已加密文件: {relative_path}")
                        else:
                            self.encrypt_file(fernet, file_path)
                            self.status.emit(f"已加密: {relative_path}")
                    else:  # decrypt
                        if not file.endswith('.enc'):
                            self.status.emit(f"跳过未加密文件: {relative_path}")
                        else:
                            self.decrypt_file(fernet, file_path)
                            self.status.emit(f"已解密: {relative_path}")
                    
                    processed_files += 1
                    self.progress.emit(int(processed_files / total_files * 100))
 
            self.status.emit("\n操作完成!")
            self.finished.emit()
        except exception as e:
            self.error.emit(str(e))
 
    def get_key(self, password):
        password = password.encode()
        salt = b'salt_'
        kdf = pbkdf2hmac(
            algorithm=hashes.sha256(),
            length=32,
            salt=salt,
            iterations=100000,
        )
        key = base64.urlsafe_b64encode(kdf.derive(password))
        return key
 
    def encrypt_file(self, fernet, file_path):
        with open(file_path, 'rb') as f:
            data = f.read()
        encrypted = fernet.encrypt(data)
        encrypted_path = file_path + '.enc'
        with open(encrypted_path, 'wb') as f:
            f.write(encrypted)
        os.remove(file_path)
 
    def decrypt_file(self, fernet, file_path):
        with open(file_path, 'rb') as f:
            data = f.read()
        try:
            decrypted = fernet.decrypt(data)
            decrypted_path = file_path[:-4]  # 移除 '.enc'
            with open(decrypted_path, 'wb') as f:
                f.write(decrypted)
            os.remove(file_path)
        except:
            raise exception(f'解密 {file_path} 失败,可能密码错误')
 
class encryptor(qwidget):
    def __init__(self):
        super().__init__()
        self.initui()
 
    def initui(self):
        self.setwindowtitle('文件夹加密器')
        self.setgeometry(300, 200, 700, 600)
 
        main_layout = qvboxlayout()
 
        # 上半部分:控制面板
        control_panel = qwidget()
        control_layout = qvboxlayout()
 
        # 文件夹选择
        folder_layout = qhboxlayout()
        self.folder_input = qlineedit()
        folder_button = qpushbutton('选择文件夹')
        folder_button.clicked.connect(self.select_folder)
        folder_layout.addwidget(self.folder_input)
        folder_layout.addwidget(folder_button)
        control_layout.addlayout(folder_layout)
 
        # 密码输入
        password_layout = qhboxlayout()
        password_label = qlabel('密码:')
        self.password_input = qlineedit()
        self.password_input.setechomode(qlineedit.echomode.password)
        password_layout.addwidget(password_label)
        password_layout.addwidget(self.password_input)
        control_layout.addlayout(password_layout)
 
        # 进度条
        self.progress_bar = qprogressbar()
        control_layout.addwidget(self.progress_bar)
 
        # 加密解密按钮
        button_layout = qhboxlayout()
        encrypt_button = qpushbutton('加密')
        decrypt_button = qpushbutton('解密')
        encrypt_button.clicked.connect(lambda: self.process_folder('encrypt'))
        decrypt_button.clicked.connect(lambda: self.process_folder('decrypt'))
        button_layout.addwidget(encrypt_button)
        button_layout.addwidget(decrypt_button)
        control_layout.addlayout(button_layout)
 
        control_panel.setlayout(control_layout)
        main_layout.addwidget(control_panel)
 
        # 分割线
        splitter = qsplitter(qt.orientation.vertical)
 
        # 注意事项面板
        notice_panel = qwidget()
        notice_layout = qvboxlayout()
        notice_label = qlabel("注意事项:")
        notice_label.setfont(qfont("arial", 12, qfont.weight.bold))
        notice_label.setstylesheet("color: red;")
        notice_text = qtextedit()
        notice_text.setplaintext(
            "1. 请确保记住密码,否则将无法解密文件。\n"
            "2. 请慎重操作!该程序会直接在原文件夹中操作,谨防误操作。\n"
            "3. 加密后删除原文件,解密后删除加密文件。加密后的文件会有 .enc 扩展名。\n"
            "4. 本程序支持加密/解密文件夹中的所有文件。\n"
            "5. 已加密的文件不会被重复加密,未加密的文件不会被解密。"
        )
        notice_text.setreadonly(true)
        notice_text.setfont(qfont("arial", 11))
        notice_text.setstylesheet("color: #d32f2f;")  # 深红色
        notice_layout.addwidget(notice_label)
        notice_layout.addwidget(notice_text)
        notice_panel.setlayout(notice_layout)
 
        # 日志面板
        log_panel = qwidget()
        log_layout = qvboxlayout()
        log_label = qlabel("处理日志:")
        #log_label.setfont(qfont("arial", 10, qfont.weight.bold))
        self.log_text = qtextedit()
        self.log_text.setreadonly(true)
        #self.log_text.setfont(qfont("arial", 10))
        log_layout.addwidget(log_label)
        log_layout.addwidget(self.log_text)
        log_panel.setlayout(log_layout)
 
        # 添加面板到分割器
        splitter.addwidget(notice_panel)
        splitter.addwidget(log_panel)
        main_layout.addwidget(splitter)
 
        self.setlayout(main_layout)
 
    def select_folder(self):
        folder = qfiledialog.getexistingdirectory(self, "选择文件夹")
        self.folder_input.settext(folder)
 
    def process_folder(self, mode):
        folder = self.folder_input.text()
        password = self.password_input.text()
        if not folder or not password:
            qmessagebox.warning(self, '警告', '请选择文件夹并输入密码')
            return
 
        # 清空日志
        self.log_text.clear()
        
        self.worker = cryptoworker(folder, password, mode)
        self.worker.progress.connect(self.update_progress)
        self.worker.finished.connect(self.process_finished)
        self.worker.error.connect(self.process_error)
        self.worker.status.connect(self.update_log)  # 连接状态信号
        self.worker.start()
 
    def update_progress(self, value):
        self.progress_bar.setvalue(value)
 
    def update_log(self, message):
        self.log_text.append(message)
 
    def process_finished(self):
        qmessagebox.information(self, '成功', '操作完成')
        self.progress_bar.setvalue(0)
 
    def process_error(self, error_msg):
        qmessagebox.critical(self, '错误', f'发生错误:{error_msg}')
        self.progress_bar.setvalue(0)
        self.log_text.append(f"\n错误: {error_msg}")
 
if __name__ == '__main__':
    app = qapplication(sys.argv)
    ex = encryptor()
    ex.show()
    sys.exit(app.exec())

到此这篇关于python如何实现按文件夹加密解密其中文件的文章就介绍到这了,更多相关python加密解密文件内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com