encrypto
This commit is contained in:
314
encrypto.py
Normal file
314
encrypto.py
Normal file
@ -0,0 +1,314 @@
|
||||
import tkinter as tk
|
||||
from tkinter import ttk, filedialog, messagebox
|
||||
import os
|
||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||
from cryptography.hazmat.primitives import hashes, padding
|
||||
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
import secrets
|
||||
|
||||
|
||||
class Encrypto:
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
self.root.title("Encrypto")
|
||||
self.root.geometry("500x500")
|
||||
self.root.resizable(True, True)
|
||||
|
||||
self.selected_file = tk.StringVar()
|
||||
self.password = tk.StringVar()
|
||||
self.algorithm = tk.StringVar(value="AES-256")
|
||||
self.operation = tk.StringVar(value="encrypt")
|
||||
|
||||
self.setup_ui()
|
||||
|
||||
def setup_ui(self):
|
||||
main_frame = ttk.Frame(self.root, padding="20")
|
||||
main_frame.grid(row=0, column=0, sticky="nsew")
|
||||
|
||||
self.root.columnconfigure(0, weight=1)
|
||||
self.root.rowconfigure(0, weight=1)
|
||||
main_frame.columnconfigure(1, weight=1)
|
||||
|
||||
ttk.Label(main_frame, text="Select File:").grid(
|
||||
row=0, column=0, sticky="w", pady=5
|
||||
)
|
||||
|
||||
file_frame = ttk.Frame(main_frame)
|
||||
file_frame.grid(row=0, column=1, sticky="ew", pady=5)
|
||||
file_frame.columnconfigure(0, weight=1)
|
||||
|
||||
self.file_entry = ttk.Entry(
|
||||
file_frame, textvariable=self.selected_file, state="readonly"
|
||||
)
|
||||
self.file_entry.grid(row=0, column=0, sticky="ew", padx=(0, 5))
|
||||
|
||||
ttk.Button(file_frame, text="Browse", command=self.browse_file).grid(
|
||||
row=0, column=1
|
||||
)
|
||||
|
||||
ttk.Label(main_frame, text="Algorithm:").grid(
|
||||
row=1, column=0, sticky="w", pady=5
|
||||
)
|
||||
|
||||
algo_combo = ttk.Combobox(
|
||||
main_frame,
|
||||
textvariable=self.algorithm,
|
||||
values=["AES-256", "AES-128"],
|
||||
state="readonly",
|
||||
)
|
||||
algo_combo.grid(row=1, column=1, sticky="ew", pady=5)
|
||||
|
||||
ttk.Label(main_frame, text="Operation:").grid(
|
||||
row=2, column=0, sticky="w", pady=5
|
||||
)
|
||||
|
||||
op_frame = ttk.Frame(main_frame)
|
||||
op_frame.grid(row=2, column=1, sticky="ew", pady=5)
|
||||
|
||||
ttk.Radiobutton(
|
||||
op_frame, text="Encrypt", variable=self.operation, value="encrypt"
|
||||
).grid(row=0, column=0, sticky="w")
|
||||
ttk.Radiobutton(
|
||||
op_frame, text="Decrypt", variable=self.operation, value="decrypt"
|
||||
).grid(row=0, column=1, sticky="w", padx=(20, 0))
|
||||
|
||||
ttk.Label(main_frame, text="Password:").grid(
|
||||
row=3, column=0, sticky="w", pady=5
|
||||
)
|
||||
|
||||
self.password_entry = ttk.Entry(
|
||||
main_frame, textvariable=self.password, show="*"
|
||||
)
|
||||
self.password_entry.grid(row=3, column=1, sticky="ew", pady=5)
|
||||
|
||||
self.show_password = tk.BooleanVar()
|
||||
ttk.Checkbutton(
|
||||
main_frame,
|
||||
text="Show password",
|
||||
variable=self.show_password,
|
||||
command=self.toggle_password,
|
||||
).grid(row=4, column=1, sticky="w", pady=5)
|
||||
|
||||
self.process_btn = ttk.Button(
|
||||
main_frame, text="Encrypt", command=self.process_file
|
||||
)
|
||||
self.process_btn.grid(row=5, column=0, columnspan=2, sticky="ew", pady=20)
|
||||
|
||||
self.progress = ttk.Progressbar(main_frame, mode="indeterminate")
|
||||
self.progress.grid(row=6, column=0, columnspan=2, sticky="ew", pady=5)
|
||||
|
||||
self.status_text = tk.Text(main_frame, height=8, width=50)
|
||||
self.status_text.grid(row=7, column=0, columnspan=2, sticky="nsew", pady=5)
|
||||
|
||||
scrollbar = ttk.Scrollbar(
|
||||
main_frame, orient="vertical", command=self.status_text.yview
|
||||
)
|
||||
scrollbar.grid(row=7, column=2, sticky="ns", pady=5)
|
||||
self.status_text.configure(yscrollcommand=scrollbar.set)
|
||||
|
||||
main_frame.rowconfigure(7, weight=1)
|
||||
|
||||
self.operation.trace_add("write", self.update_button_text)
|
||||
|
||||
def browse_file(self):
|
||||
if self.operation.get() == "encrypt":
|
||||
filename = filedialog.askopenfilename(
|
||||
title="Select file to encrypt", filetypes=[("All files", "*.*")]
|
||||
)
|
||||
else:
|
||||
filename = filedialog.askopenfilename(
|
||||
title="Select file to decrypt",
|
||||
filetypes=[("Encrypted files", "*.enc"), ("All files", "*.*")],
|
||||
)
|
||||
|
||||
if filename:
|
||||
self.selected_file.set(filename)
|
||||
|
||||
def toggle_password(self):
|
||||
if self.show_password.get():
|
||||
self.password_entry.configure(show="")
|
||||
else:
|
||||
self.password_entry.configure(show="*")
|
||||
|
||||
def update_button_text(self, *args):
|
||||
if self.operation.get() == "encrypt":
|
||||
self.process_btn.configure(text="Encrypt")
|
||||
else:
|
||||
self.process_btn.configure(text="Decrypt")
|
||||
|
||||
def log_status(self, message):
|
||||
self.status_text.insert(tk.END, message + "\n")
|
||||
self.status_text.see(tk.END)
|
||||
self.root.update()
|
||||
|
||||
def derive_key(self, password, salt):
|
||||
key_length = 32 if self.algorithm.get() == "AES-256" else 16
|
||||
kdf = PBKDF2HMAC(
|
||||
algorithm=hashes.SHA256(),
|
||||
length=key_length,
|
||||
salt=salt,
|
||||
iterations=100000,
|
||||
backend=default_backend(),
|
||||
)
|
||||
return kdf.derive(password.encode())
|
||||
|
||||
def encrypt_file(self, input_file, output_file, password):
|
||||
try:
|
||||
salt = secrets.token_bytes(16)
|
||||
iv = secrets.token_bytes(16)
|
||||
|
||||
key = self.derive_key(password, salt)
|
||||
|
||||
cipher = Cipher(
|
||||
algorithms.AES(key), modes.CBC(iv), backend=default_backend()
|
||||
)
|
||||
encryptor = cipher.encryptor()
|
||||
|
||||
padder = padding.PKCS7(128).padder()
|
||||
|
||||
with open(input_file, "rb") as infile, open(output_file, "wb") as outfile:
|
||||
outfile.write(salt)
|
||||
outfile.write(iv)
|
||||
|
||||
while True:
|
||||
chunk = infile.read(8192)
|
||||
if not chunk:
|
||||
padded_data = padder.finalize()
|
||||
if padded_data:
|
||||
outfile.write(encryptor.update(padded_data))
|
||||
outfile.write(encryptor.finalize())
|
||||
break
|
||||
|
||||
padded_chunk = padder.update(chunk)
|
||||
outfile.write(encryptor.update(padded_chunk))
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
self.log_status(f"Encryption error: {str(e)}")
|
||||
return False
|
||||
|
||||
def decrypt_file(self, input_file, output_file, password):
|
||||
try:
|
||||
with open(input_file, "rb") as infile:
|
||||
salt = infile.read(16)
|
||||
iv = infile.read(16)
|
||||
|
||||
key = self.derive_key(password, salt)
|
||||
|
||||
cipher = Cipher(
|
||||
algorithms.AES(key), modes.CBC(iv), backend=default_backend()
|
||||
)
|
||||
decryptor = cipher.decryptor()
|
||||
|
||||
unpadder = padding.PKCS7(128).unpadder()
|
||||
|
||||
with open(output_file, "wb") as outfile:
|
||||
while True:
|
||||
chunk = infile.read(8192)
|
||||
if not chunk:
|
||||
break
|
||||
|
||||
decrypted_chunk = decryptor.update(chunk)
|
||||
|
||||
if decrypted_chunk:
|
||||
unpadded_chunk = unpadder.update(decrypted_chunk)
|
||||
if unpadded_chunk:
|
||||
outfile.write(unpadded_chunk)
|
||||
|
||||
if hasattr(self, "root"):
|
||||
self.root.update()
|
||||
|
||||
final_decrypted = decryptor.finalize()
|
||||
if final_decrypted:
|
||||
final_unpadded = unpadder.update(final_decrypted)
|
||||
if final_unpadded:
|
||||
outfile.write(final_unpadded)
|
||||
|
||||
final_unpadded = unpadder.finalize()
|
||||
if final_unpadded:
|
||||
outfile.write(final_unpadded)
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
self.log_status(f"Decryption error: {str(e)}")
|
||||
return False
|
||||
|
||||
def process_file(self):
|
||||
if not self.selected_file.get():
|
||||
messagebox.showerror("Error", "Please select a file")
|
||||
return
|
||||
|
||||
if not self.password.get():
|
||||
messagebox.showerror("Error", "Please enter a password")
|
||||
return
|
||||
|
||||
if not os.path.exists(self.selected_file.get()):
|
||||
messagebox.showerror("Error", "Selected file does not exist")
|
||||
return
|
||||
|
||||
self.progress.start()
|
||||
self.process_btn.configure(state="disabled")
|
||||
|
||||
input_file = self.selected_file.get()
|
||||
operation = self.operation.get()
|
||||
|
||||
if operation == "encrypt":
|
||||
output_file = input_file + ".enc"
|
||||
self.log_status(
|
||||
f"Starting encryption of: {os.path.basename(input_file)}..."
|
||||
)
|
||||
self.log_status(f"Algorithm: {self.algorithm.get()}")
|
||||
|
||||
success = self.encrypt_file(input_file, output_file, self.password.get())
|
||||
|
||||
if success:
|
||||
self.log_status("✓ File encrypted successfully!")
|
||||
self.log_status(
|
||||
f"Encrypted file saved as: {os.path.basename(output_file)}"
|
||||
)
|
||||
messagebox.showinfo(
|
||||
"Success", f"File encrypted successfully!\nSaved as: {output_file}"
|
||||
)
|
||||
else:
|
||||
messagebox.showerror(
|
||||
"Error", "Encryption failed. Check the status log for details."
|
||||
)
|
||||
|
||||
else:
|
||||
if input_file.endswith(".enc"):
|
||||
output_file = input_file[:-4]
|
||||
else:
|
||||
output_file = input_file + ".decrypted"
|
||||
|
||||
self.log_status(
|
||||
f"Starting decryption of: {os.path.basename(input_file)}..."
|
||||
)
|
||||
|
||||
success = self.decrypt_file(input_file, output_file, self.password.get())
|
||||
|
||||
if success:
|
||||
self.log_status("✓ File decrypted successfully!")
|
||||
self.log_status(
|
||||
f"Decrypted file saved as: {os.path.basename(output_file)}"
|
||||
)
|
||||
messagebox.showinfo(
|
||||
"Success", f"File decrypted successfully!\nSaved as: {output_file}"
|
||||
)
|
||||
else:
|
||||
messagebox.showerror(
|
||||
"Error", "Decryption failed. Check password and try again."
|
||||
)
|
||||
|
||||
self.progress.stop()
|
||||
self.process_btn.configure(state="normal")
|
||||
|
||||
|
||||
def main():
|
||||
root = tk.Tk()
|
||||
Encrypto(root)
|
||||
root.mainloop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Reference in New Issue
Block a user