|
| 1 | +# Author: Danu Pratama |
| 2 | +import tkinter as tk |
| 3 | +from tkinter import filedialog, messagebox |
| 4 | +from tkinter import ttk |
| 5 | +from Crypto.Cipher import AES |
| 6 | +from Crypto.Util.Padding import pad, unpad |
| 7 | +import os |
| 8 | +import time |
| 9 | + |
| 10 | +class AESEncryptor: # Kelas untuk enkripsi dan dekripsi menggunakan AES |
| 11 | + def __init__(self, key): |
| 12 | + self.key = key.encode() # Mengkode kunci ke dalam bytes |
| 13 | + |
| 14 | + def encrypt(self, plaintext): |
| 15 | + cipher = AES.new(self.key, AES.MODE_CBC) # Buat cipher baru untuk setiap enkripsi |
| 16 | + iv = cipher.iv |
| 17 | + ciphertext = cipher.encrypt(pad(plaintext, AES.block_size)) |
| 18 | + return iv + ciphertext # Kembalikan IV yang digabungkan dengan ciphertext |
| 19 | + |
| 20 | + def decrypt(self, iv, ciphertext): |
| 21 | + cipher = AES.new(self.key, AES.MODE_CBC, iv) |
| 22 | + plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size) |
| 23 | + return plaintext |
| 24 | + |
| 25 | +class FileEncryptor: # Kelas untuk menangani proses enkripsi dan dekripsi file |
| 26 | + def __init__(self, entry_file, entry_key, label_result): |
| 27 | + self.entry_file = entry_file |
| 28 | + self.entry_key = entry_key |
| 29 | + self.label_result = label_result |
| 30 | + self.file_handler = None |
| 31 | + self.timer = Timer() # Timer untuk menghitung waktu proses |
| 32 | + |
| 33 | + def browse_file(self): # Membuka dialog untuk memilih file |
| 34 | + filename = filedialog.askopenfilename(initialdir="/", title="Pilih file", filetypes=(("All files", "*.*"),)) |
| 35 | + self.entry_file.delete(0, tk.END) |
| 36 | + self.entry_file.insert(0, filename) |
| 37 | + |
| 38 | + def get_file_type(self, filename): # Mendapatkan tipe file berdasarkan ekstensi |
| 39 | + return FileHandler.get_file_type(filename) |
| 40 | + |
| 41 | + def encrypt_file(self): # Proses enkripsi file |
| 42 | + filename = self.entry_file.get() |
| 43 | + key = self.entry_key.get() |
| 44 | + |
| 45 | + self.file_handler = FileHandler(filename, key) |
| 46 | + |
| 47 | + if not filename: |
| 48 | + messagebox.showerror("Error", "Masukkan file terlebih dahulu") |
| 49 | + return |
| 50 | + |
| 51 | + if not self.file_handler.validate_key(): |
| 52 | + messagebox.showerror("Error", "Panjang kunci harus 16, 24, atau 32 karakter") |
| 53 | + return |
| 54 | + |
| 55 | + try: |
| 56 | + self.timer.start() |
| 57 | + plaintext = self.file_handler.read_file() |
| 58 | + |
| 59 | + aes_cipher = AESEncryptor(key) # Inisialisasi AESEncryptor |
| 60 | + encrypted_data = aes_cipher.encrypt(plaintext) # Enkripsi data |
| 61 | + |
| 62 | + output_filename = filename + ".encrypted" |
| 63 | + self.file_handler.filename = output_filename |
| 64 | + self.file_handler.write_file(encrypted_data) |
| 65 | + |
| 66 | + self.timer.stop() |
| 67 | + elapsed_time = self.timer.elapsed_time() |
| 68 | + file_type = self.get_file_type(filename) |
| 69 | + |
| 70 | + self.label_result.config(text=f"Status: Berhasil Enkripsi | Waktu Proses: {elapsed_time:.2f} detik | Tipe: {file_type}") |
| 71 | + except Exception as e: |
| 72 | + messagebox.showerror("Error", str(e)) |
| 73 | + |
| 74 | + def decrypt_file(self): # Proses dekripsi file |
| 75 | + filename = self.entry_file.get() |
| 76 | + key = self.entry_key.get() |
| 77 | + |
| 78 | + self.file_handler = FileHandler(filename, key) |
| 79 | + |
| 80 | + if not filename: |
| 81 | + messagebox.showerror("Error", "Masukkan file terlebih dahulu") |
| 82 | + return |
| 83 | + |
| 84 | + if not self.file_handler.validate_key(): |
| 85 | + messagebox.showerror("Error", "Panjang kunci harus 16, 24, atau 32 karakter") |
| 86 | + return |
| 87 | + |
| 88 | + if not filename.endswith(".encrypted"): |
| 89 | + messagebox.showerror("Error", "File yang dipilih bukan file terenkripsi (.encrypted)") |
| 90 | + return |
| 91 | + |
| 92 | + try: |
| 93 | + self.timer.start() |
| 94 | + iv_and_ciphertext = self.file_handler.read_file() |
| 95 | + iv = iv_and_ciphertext[:16] |
| 96 | + ciphertext = iv_and_ciphertext[16:] |
| 97 | + |
| 98 | + aes_cipher = AESEncryptor(key) # Inisialisasi AESEncryptor |
| 99 | + plaintext = aes_cipher.decrypt(iv, ciphertext) # Dekripsi data |
| 100 | + |
| 101 | + output_filename = filename[:-10] |
| 102 | + self.file_handler.filename = output_filename |
| 103 | + self.file_handler.write_file(plaintext) |
| 104 | + |
| 105 | + self.timer.stop() |
| 106 | + elapsed_time = self.timer.elapsed_time() |
| 107 | + file_type = self.get_file_type(output_filename) |
| 108 | + |
| 109 | + self.label_result.config(text=f"Status: Berhasil Dekripsi | Waktu Proses: {elapsed_time:.2f} detik | Tipe: {file_type}") |
| 110 | + except ValueError as e: |
| 111 | + messagebox.showerror("Error", "Dekripsi gagal: Kunci salah atau file rusak") |
| 112 | + except Exception as e: |
| 113 | + messagebox.showerror("Error", str(e)) |
| 114 | + |
| 115 | + def refresh(self): # Mengatur ulang input dan status |
| 116 | + self.entry_file.delete(0, tk.END) |
| 117 | + self.entry_key.delete(0, tk.END) |
| 118 | + self.label_result.config(text="Status: - | Waktu Proses: - | Tipe: -") |
| 119 | + |
| 120 | +class FileHandler: # Kelas untuk membaca dan menulis file |
| 121 | + def __init__(self, filename='', key=''): |
| 122 | + self.filename = filename |
| 123 | + self.key = key |
| 124 | + |
| 125 | + def read_file(self): # Membaca isi file |
| 126 | + with open(self.filename, "rb") as f: |
| 127 | + return f.read() |
| 128 | + |
| 129 | + def write_file(self, data): # Menulis data ke file |
| 130 | + with open(self.filename, "wb") as f: |
| 131 | + f.write(data) |
| 132 | + |
| 133 | + def validate_key(self): # Memvalidasi panjang kunci |
| 134 | + return len(self.key) in (16, 24, 32) |
| 135 | + |
| 136 | + @staticmethod |
| 137 | + def get_file_type(filename): # Mendapatkan tipe file berdasarkan ekstensi |
| 138 | + ext = os.path.splitext(filename)[1].lower() |
| 139 | + if ext in ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff']: |
| 140 | + return "Gambar" |
| 141 | + elif ext in ['.pdf']: |
| 142 | + return "PDF" |
| 143 | + elif ext in ['.doc', '.docx']: |
| 144 | + return "Word" |
| 145 | + elif ext in ['.xlsx', '.xls']: |
| 146 | + return "Excel" |
| 147 | + elif ext in ['.ppt', '.pptx']: |
| 148 | + return "PowerPoint" |
| 149 | + elif ext in ['.mp4', '.avi', '.mov', '.mkv', '.flv']: |
| 150 | + return "Video" |
| 151 | + elif ext in ['.txt']: |
| 152 | + return "Teks" |
| 153 | + else: |
| 154 | + return "Tak dikenal" |
| 155 | + |
| 156 | +class Timer: # Kelas untuk menghitung waktu |
| 157 | + def __init__(self): |
| 158 | + self.start_time = 0 |
| 159 | + self.end_time = 0 |
| 160 | + |
| 161 | + def start(self): # Memulai timer |
| 162 | + self.start_time = time.time() |
| 163 | + |
| 164 | + def stop(self): # Menghentikan timer |
| 165 | + self.end_time = time.time() |
| 166 | + |
| 167 | + def elapsed_time(self): # Menghitung waktu yang telah berlalu |
| 168 | + return self.end_time - self.start_time |
| 169 | + |
| 170 | +# Kelas Tk untuk menginisialisasi jendela aplikasi |
| 171 | +class Tk(tk.Tk): |
| 172 | + def __init__(self, *args, **kwargs): |
| 173 | + super().__init__(*args, **kwargs) |
| 174 | + # Tambahkan atribut di sini, misalnya: |
| 175 | + self.configure(bg="#ededed") # Mengatur warna latar belakang |
| 176 | + |
| 177 | +# Kelas TTk untuk memperluas Frame dari ttk |
| 178 | +class TTk(ttk.Frame): |
| 179 | + def __init__(self, *args, **kwargs): |
| 180 | + super().__init__(*args, **kwargs) |
| 181 | + # Tambahkan atribut di sini, misalnya: |
| 182 | + self.configure(bg="#ededed") # Mengatur warna latar belakang |
| 183 | + |
| 184 | +class App: # Kelas utama untuk aplikasi |
| 185 | + def __init__(self, root): |
| 186 | + self.root = root |
| 187 | + self.root.title("FileGuard - Danu Pratama - Enkripsi dan Dekripsi File") |
| 188 | + self.root.geometry("420x560") |
| 189 | + self.root.configure(bg="#ededed") |
| 190 | + |
| 191 | + # Membuat instance FileEncryptor |
| 192 | + self.entry_file = ttk.Entry(root, width=50, font=("Arial", 12)) |
| 193 | + self.entry_key = ttk.Entry(root, width=50, font=("Arial", 12)) |
| 194 | + self.label_result = tk.Label(root, text="Status: - | Waktu Proses: - | Tipe: -", font=("Arial", 11, "bold"), bg="#ededed", fg="black") |
| 195 | + self.file_encryptor = FileEncryptor(self.entry_file, self.entry_key, self.label_result) |
| 196 | + |
| 197 | + # Membuat komponen GUI |
| 198 | + self.create_widgets() |
| 199 | + |
| 200 | + def create_widgets(self): # Membuat dan menata komponen GUI |
| 201 | + label_file = tk.Label(self.root, text="Advanced Encryption Standard", font=("Arial", 15), bg="#ededed", fg="#000000") |
| 202 | + label_file.pack(pady=30) |
| 203 | + |
| 204 | + self.entry_file.pack(padx=20, pady=10, ipady=5) |
| 205 | + |
| 206 | + button_browse = tk.Button(self.root, text="Upload File", command=self.file_encryptor.browse_file, bg="yellow", fg="black", width=15, font=("Arial", 11, "bold")) |
| 207 | + button_browse.pack(pady=30) |
| 208 | + |
| 209 | + label_key = tk.Label(self.root, text="Kunci Rahasia*", font=("Arial", 12, "bold"), bg="#ededed", fg="#000000") |
| 210 | + label_key.pack(pady=20) |
| 211 | + |
| 212 | + self.entry_key.pack(padx=20, pady=10, ipady=5) |
| 213 | + |
| 214 | + # Frame untuk tombol-tombol |
| 215 | + button_frame = tk.Frame(self.root, bg="#ededed") |
| 216 | + button_frame.pack(pady=20) |
| 217 | + |
| 218 | + button_encrypt = tk.Button(button_frame, text="Enkripsi", command=self.file_encryptor.encrypt_file, bg="blue", fg="white", width=10, font=("Arial", 11, "bold")) |
| 219 | + button_encrypt.pack(side=tk.LEFT, padx=15) |
| 220 | + |
| 221 | + button_decrypt = tk.Button(button_frame, text="Dekripsi", command=self.file_encryptor.decrypt_file, bg="green", fg="white", width=10, font=("Arial", 11, "bold")) |
| 222 | + button_decrypt.pack(side=tk.LEFT, padx=15) |
| 223 | + |
| 224 | + button_refresh = tk.Button(button_frame, text="Refresh", command=self.file_encryptor.refresh, bg="red", fg="white", width=10, font=("Arial", 11, "bold")) |
| 225 | + button_refresh.pack(side=tk.LEFT, padx=15) |
| 226 | + |
| 227 | + self.label_result.pack(pady=30) |
| 228 | + |
| 229 | + |
| 230 | +if __name__ == "__main__": |
| 231 | + root = Tk() |
| 232 | + app = App(root) |
| 233 | + root.mainloop() |
0 commit comments