Fuzzu FastEncrypt – AES-256-GCM File Encryptor/Decryptor in Python (Fast GUI)

Demo :


Click Video πŸ‘‡πŸ‘‡πŸ‘‡






























Features:

  • Large Thumbnail Image

  • Auto Read More Jump Break

  • SEO-friendly Meta Tags with keywords "Python AES-256 Encryption GUI, Fast File Encryptor, FuzzuTech


Code :


# Fuzzu FastEncrypt – AES-256-GCM File Encryptor/Decryptor (Fast + GUI)

# Author: FuzzuTech (fixed)

# Requires: pip install cryptography customtkinter


import os

import threading

import time

from tkinter import filedialog, messagebox

import customtkinter as ctk

import base64


from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

from cryptography.hazmat.primitives import hashes

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

from cryptography.hazmat.backends import default_backend


# --- constants ---

MAGIC = b"FZENC1\n\x00"  # 8 bytes (file signature)

SALT_LEN = 16

NONCE_LEN = 12

TAG_LEN = 16

CHUNK_SIZE = 8 * 1024 * 1024  # 8 MB

PBKDF2_ITERS = 300_000


backend = default_backend()



def rand_bytes(n: int) -> bytes:

    return os.urandom(n)



def derive_key(password: str, salt: bytes) -> bytes:

    kdf = PBKDF2HMAC(

        algorithm=hashes.SHA256(),

        length=32,

        salt=salt,

        iterations=PBKDF2_ITERS,

        backend=backend,

    )

    return kdf.derive(password.encode("utf-8"))



def human_bytes(n: int) -> str:

    n_float = float(n)

    for unit in ["B", "KB", "MB", "GB", "TB"]:

        if n_float < 1024.0 or unit == "TB":

            return f"{n_float:.2f} {unit}"

        n_float /= 1024.0

    return f"{n:.2f} B"



def encrypt_file(in_path: str, out_path: str, password: str, progress_cb=None, speed_cb=None, cancel_cb=None):

    total = os.path.getsize(in_path)

    salt = rand_bytes(SALT_LEN)

    key = derive_key(password, salt)

    nonce = rand_bytes(NONCE_LEN)


    cipher = Cipher(algorithms.AES(key), modes.GCM(nonce), backend=backend)

    encryptor = cipher.encryptor()


    t0 = time.time()

    bytes_done = 0


    with open(in_path, "rb", buffering=0) as fin, open(out_path, "wb", buffering=0) as fout:

        # header

        fout.write(MAGIC)

        fout.write(salt)

        fout.write(nonce)


        while True:

            if cancel_cb and cancel_cb():

                raise Exception("Operation cancelled by user")

            chunk = fin.read(CHUNK_SIZE)

            if not chunk:

                break

            ct = encryptor.update(chunk)

            if ct:

                fout.write(ct)

            bytes_done += len(chunk)

            if progress_cb and total > 0:

                progress_cb(bytes_done / total)

            if speed_cb:

                dt = time.time() - t0

                if dt > 0:

                    speed_cb(bytes_done / dt)


        encryptor.finalize()

        tag = encryptor.tag

        fout.write(tag)



def decrypt_file(in_path: str, out_path: str, password: str, progress_cb=None, speed_cb=None, cancel_cb=None):

    total = os.path.getsize(in_path)

    min_size = len(MAGIC) + SALT_LEN + NONCE_LEN + TAG_LEN

    if total < min_size:

        raise ValueError("File too small or not an FZENC1 file")


    with open(in_path, "rb", buffering=0) as fin:

        header = fin.read(len(MAGIC) + SALT_LEN + NONCE_LEN)

        magic = header[: len(MAGIC)]

        if magic != MAGIC:

            raise ValueError("Invalid file header (not FZENC1)")

        salt = header[len(MAGIC) : len(MAGIC) + SALT_LEN]

        nonce = header[len(MAGIC) + SALT_LEN : len(MAGIC) + SALT_LEN + NONCE_LEN]


        key = derive_key(password, salt)


        ct_len = total - (len(MAGIC) + SALT_LEN + NONCE_LEN + TAG_LEN)

        if ct_len < 0:

            raise ValueError("Corrupted file: negative ciphertext length")


        with open(in_path, "rb", buffering=0) as ftag:

            ftag.seek(total - TAG_LEN)

            tag = ftag.read(TAG_LEN)


        cipher = Cipher(algorithms.AES(key), modes.GCM(nonce, tag), backend=backend)

        decryptor = cipher.decryptor()


        t0 = time.time()

        bytes_done = 0

        remaining = ct_len


        fin.seek(len(MAGIC) + SALT_LEN + NONCE_LEN)


        with open(out_path, "wb", buffering=0) as fout:

            while remaining > 0:

                if cancel_cb and cancel_cb():

                    raise Exception("Operation cancelled by user")

                to_read = CHUNK_SIZE if remaining >= CHUNK_SIZE else remaining

                chunk = fin.read(to_read)

                if not chunk:

                    break

                pt = decryptor.update(chunk)

                if pt:

                    fout.write(pt)

                bytes_done += len(chunk)

                remaining -= len(chunk)

                if progress_cb and ct_len > 0:

                    progress_cb(bytes_done / ct_len)

                if speed_cb:

                    dt = time.time() - t0

                    if dt > 0:

                        speed_cb(bytes_done / dt)


            decryptor.finalize()



# --------------------- GUI (CustomTkinter) ---------------------

class FastEncryptGUI(ctk.CTk):

    def __init__(self):

        super().__init__()

        ctk.set_appearance_mode("dark")

        ctk.set_default_color_theme("green")

        self.title("Fuzzu FastEncrypt – AES-256-GCM")

        self.geometry("500x520")

        self.minsize(500, 480)


        self.file_path = ctk.StringVar()

        self.out_dir = ctk.StringVar()

        self.password = ctk.StringVar()

        self.mode = ctk.StringVar(value="Encrypt")

        self.status = ctk.StringVar(value="Ready")

        self.speed = ctk.StringVar(value="Speed: 0 MB/s")

        self.size_info = ctk.StringVar(value="File: –")


        self.job_thread = None

        self.cancel_requested = False

        self.showing = False


        self.build_ui()


    def build_ui(self):

        pad = 12

        title = ctk.CTkLabel(self, text="Fuzzu FastEncrypt", font=("Segoe UI", 26, "bold"))

        title.pack(pady=(16, 6))

        subtitle = ctk.CTkLabel(self, text="AES-256-GCM • Fast Encrypt/Decrypt • Authenticated", font=("Segoe UI", 14))

        subtitle.pack(pady=(0, 14))


        row = ctk.CTkFrame(self)

        row.pack(fill="x", padx=pad, pady=(0, pad))


        entry = ctk.CTkEntry(row, textvariable=self.file_path, placeholder_text="Choose file to encrypt/decrypt")

        entry.pack(side="left", fill="x", expand=True, padx=(pad, 6), pady=pad)

        pick = ctk.CTkButton(row, text="Browse", command=self.choose_file)

        pick.pack(side="right", padx=(0, pad), pady=pad)


        row2 = ctk.CTkFrame(self)

        row2.pack(fill="x", padx=pad, pady=(0, pad))

        out_entry = ctk.CTkEntry(row2, textvariable=self.out_dir, placeholder_text="Select output folder (optional)")

        out_entry.pack(side="left", fill="x", expand=True, padx=(pad, 6), pady=pad)

        pick2 = ctk.CTkButton(row2, text="Folder", command=self.choose_dir)

        pick2.pack(side="right", padx=(0, pad), pady=pad)


        row3 = ctk.CTkFrame(self)

        row3.pack(fill="x", padx=pad, pady=(0, pad))

        pwd = ctk.CTkEntry(row3, textvariable=self.password, show="*", placeholder_text="Enter strong password")

        pwd.pack(side="left", fill="x", expand=True, padx=(pad, 6), pady=pad)

        eye = ctk.CTkButton(row3, text="πŸ‘", width=48, command=lambda: self.toggle_pwd(pwd))

        eye.pack(side="right", padx=(0, pad), pady=pad)


        row4 = ctk.CTkFrame(self)

        row4.pack(fill="x", padx=pad, pady=(0, pad))

        mode_opt = ctk.CTkOptionMenu(row4, values=["Encrypt", "Decrypt"], variable=self.mode)

        mode_opt.pack(side="left", padx=(pad, 6), pady=pad)

        go = ctk.CTkButton(row4, text="Start", command=self.start_action)

        go.pack(side="left", padx=(0, 6), pady=pad)

        cancel = ctk.CTkButton(row4, text="Cancel", fg_color="#444", command=self.cancel_job)

        cancel.pack(side="left", padx=(0, pad), pady=pad)


        self.progress = ctk.CTkProgressBar(self)

        self.progress.set(0)

        self.progress.pack(fill="x", padx=pad, pady=(6, 6))


        info_row = ctk.CTkFrame(self)

        info_row.pack(fill="x", padx=pad, pady=(0, 6))

        self.status_lbl = ctk.CTkLabel(info_row, textvariable=self.status)

        self.status_lbl.pack(side="left", padx=(pad, 6), pady=6)

        self.speed_lbl = ctk.CTkLabel(info_row, textvariable=self.speed)

        self.speed_lbl.pack(side="right", padx=(6, pad), pady=6)


        self.size_lbl = ctk.CTkLabel(self, textvariable=self.size_info, font=("Segoe UI", 12))

        self.size_lbl.pack(pady=(0, 10))


        foot = ctk.CTkLabel(self, text="Tip: AES-GCM is hardware-accelerated on most CPUs. Use SSD for maximum speed.")

        foot.pack(pady=(0, 10))


    def toggle_pwd(self, entry):

        self.showing = not self.showing

        entry.configure(show="" if self.showing else "*")


    def choose_file(self):

        p = filedialog.askopenfilename()

        if p:

            self.file_path.set(p)

            try:

                sz = os.path.getsize(p)

                self.size_info.set(f"File: {os.path.basename(p)} ({human_bytes(sz)})")

            except Exception:

                self.size_info.set("File: –")


    def choose_dir(self):

        d = filedialog.askdirectory()

        if d:

            self.out_dir.set(d)


    def update_progress(self, frac):

        frac = max(0.0, min(1.0, frac))

        self.after(0, lambda: self.progress.set(frac))


    def update_speed(self, bps):

        mbps = bps / (1024 * 1024)

        text = f"Speed: {mbps:.2f} MB/s"

        self.after(0, lambda: self.speed.set(text))


    def set_status(self, text):

        self.after(0, lambda: self.status.set(text))


    def start_action(self):

        path = self.file_path.get().strip()

        if not path:

            messagebox.showwarning("Select file", "Please choose a file first.")

            return

        if not os.path.isfile(path):

            messagebox.showerror("Invalid", "Selected file does not exist.")

            return

        pwd = self.password.get()

        if not pwd or len(pwd) < 6:

            messagebox.showwarning("Weak Password", "Please enter a strong password (6+ characters).")

            return


        out_dir = self.out_dir.get().strip() or os.path.dirname(path)

        base = os.path.basename(path)


        mode = self.mode.get()

        if mode == "Encrypt":

            out_name = base + ".fzenc"

            out_path = os.path.join(out_dir, out_name)

            action_func = lambda cancel_cb: encrypt_file(path, out_path, pwd, self.update_progress, self.update_speed, cancel_cb)

        else:

            if base.endswith(".fzenc"):

                out_name = base[:-6]

            else:

                out_name = base + ".dec"

            out_path = os.path.join(out_dir, out_name)

            action_func = lambda cancel_cb: decrypt_file(path, out_path, pwd, self.update_progress, self.update_speed, cancel_cb)


        if os.path.abspath(path) == os.path.abspath(out_path):

            messagebox.showerror("Output conflict", "Output file would overwrite input. Choose a different folder.")

            return


        self.cancel_requested = False

        self.set_status(f"{mode}ing…")

        self.progress.set(0)

        self.speed.set("Speed: 0 MB/s")


        def worker():

            try:

                action_func(lambda: self.cancel_requested)

                self.set_status(f"{mode} complete ✓")

                self.after(0, lambda: self.progress.set(1.0))

            except Exception as e:

                if str(e) == "Operation cancelled by user":

                    self.set_status("Cancelled")

                    messagebox.showinfo("Cancelled", "Operation cancelled.")

                else:

                    self.set_status(f"Error: {e}")

                    messagebox.showerror("Failed", str(e))

            finally:

                self.job_thread = None

                self.cancel_requested = False


        self.job_thread = threading.Thread(target=worker, daemon=True)

        self.job_thread.start()


    def cancel_job(self):

        if self.job_thread and self.job_thread.is_alive():

            self.cancel_requested = True

            self.set_status("Cancelling… (waiting for current chunk to finish)")

        else:

            messagebox.showinfo("Cancel", "No active job to cancel.")



if __name__ == "__main__":

    app = FastEncryptGUI()

    app.mainloop()

Comments

Popular posts from this blog

Is This News Real or Fake? πŸ€– AI Exposes the Truth | FuzzuTech Python App Demo

🚨 Python Intrusion Detection System (IDS) – Real-Time ML + Tkinter GUI Project | FuzzuTech

Educational File Encryptor GUI (Python AES Project) | FuzzuTech