Skip to content

Commit 8c815a1

Browse files
authored
Update file_hider.py
1 parent bde0846 commit 8c815a1

File tree

1 file changed

+61
-77
lines changed

1 file changed

+61
-77
lines changed

file_hider.py

Lines changed: 61 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -10,50 +10,55 @@
1010
import argparse
1111
import sys
1212
import io
13+
import base64
14+
import zlib
1315

14-
# Dummy stream to handle write calls when sys.stderr is None
1516
class DummyStream(io.StringIO):
1617
def write(self, txt):
1718
pass
1819

19-
# Check if stderr is None and replace it with the dummy stream
2020
if sys.stderr is None:
2121
sys.stderr = DummyStream()
2222

23-
# Constants
2423
SALT_SIZE = 16
2524
NUM_ITERATIONS = 100000
26-
KEY_SIZE = 32 # 256 bits for AES-256
25+
KEY_SIZE = 32
2726
IV_SIZE = 16
2827
NUM_LAYERS = 7
29-
FILENAME_SIZE = 255 # Maximum filename length
28+
FILENAME_SIZE = 255
3029

31-
# Function to encrypt data with AES and then encrypt AES key with RSA
3230
def encrypt_data(data, public_key_path):
3331
with open(public_key_path, 'rb') as f:
3432
public_key = RSA.import_key(f.read())
3533
cipher_rsa = PKCS1_OAEP.new(public_key)
3634

37-
session_key = get_random_bytes(16) # AES key length (128 bits)
35+
session_key = get_random_bytes(16)
3836
salt = get_random_bytes(SALT_SIZE)
3937
key = PBKDF2(session_key, salt, dkLen=KEY_SIZE, count=NUM_ITERATIONS)
4038

39+
data = zlib.compress(data)
40+
4141
for _ in range(NUM_LAYERS):
4242
iv = get_random_bytes(IV_SIZE)
4343
cipher_aes = AES.new(key, AES.MODE_CBC, iv)
4444
data = cipher_aes.encrypt(pad(data, AES.block_size))
45-
data = iv + data # Prepend IV to the ciphertext for each layer
45+
data = iv + data
4646

4747
enc_session_key = cipher_rsa.encrypt(session_key)
48-
return enc_session_key, salt, data
48+
enc_session_key_b64 = base64.b64encode(enc_session_key).decode('utf-8')
49+
salt_b64 = base64.b64encode(salt).decode('utf-8')
50+
data_b64 = base64.b64encode(data).decode('utf-8')
51+
return enc_session_key_b64, salt_b64, data_b64
4952

50-
# Function to decrypt AES key with RSA and then decrypt data with AES
51-
def decrypt_data(enc_session_key, salt, data, private_key_path, passphrase):
53+
def decrypt_data(enc_session_key_b64, salt_b64, data_b64, private_key_path, passphrase):
5254
with open(private_key_path, 'rb') as f:
5355
private_key = RSA.import_key(f.read(), passphrase=passphrase)
5456
cipher_rsa = PKCS1_OAEP.new(private_key)
5557

56-
session_key = cipher_rsa.decrypt(enc_session_key)
58+
session_key = cipher_rsa.decrypt(base64.b64decode(enc_session_key_b64))
59+
salt = base64.b64decode(salt_b64)
60+
data = base64.b64decode(data_b64)
61+
5762
key = PBKDF2(session_key, salt, dkLen=KEY_SIZE, count=NUM_ITERATIONS)
5863

5964
for _ in range(NUM_LAYERS):
@@ -62,21 +67,16 @@ def decrypt_data(enc_session_key, salt, data, private_key_path, passphrase):
6267
cipher_aes = AES.new(key, AES.MODE_CBC, iv)
6368
data = unpad(cipher_aes.decrypt(data), AES.block_size)
6469

70+
# Decompress the data after decrypting
71+
data = zlib.decompress(data)
72+
6573
return data
6674

67-
68-
69-
7075
if __name__ == '__main__':
71-
7276
root = tk.Tk()
73-
root.withdraw() # Hide the root window
77+
root.withdraw()
7478

75-
# Check if any arguments were provided
7679
if len(sys.argv) > 1:
77-
78-
79-
# Add command line argument parsing
8080
parser = argparse.ArgumentParser(description="File Hider")
8181
parser.add_argument('--hide', action='store_true', help='Hide and encrypt a file')
8282
parser.add_argument('--unhide', action='store_true', help='Decrypt and unhide a file')
@@ -86,13 +86,7 @@ def decrypt_data(enc_session_key, salt, data, private_key_path, passphrase):
8686
parser.add_argument('--private-key', type=str, help='Path to the private key file')
8787
parser.add_argument('--output', type=str, help='Path to save the modified host file or extracted file')
8888
parser.add_argument('--passphrase', type=str, help='Passphrase for the private key', default='')
89-
try:
90-
args = parser.parse_args()
91-
except SystemExit:
92-
# When bad arguments are provided, show the help message in a messagebox
93-
error_message = parser.format_help()
94-
messagebox.showerror("Argument Error", error_message)
95-
sys.exit(1)
89+
args = parser.parse_args()
9690

9791
if args.hide and args.host and args.file and args.public_key and args.output:
9892
try:
@@ -102,23 +96,24 @@ def decrypt_data(enc_session_key, salt, data, private_key_path, passphrase):
10296
with open(args.file, 'rb') as hidden_file:
10397
hidden_data = hidden_file.read()
10498

105-
enc_session_key, salt, encrypted_hidden_data = encrypt_data(hidden_data, args.public_key)
99+
enc_session_key_b64, salt_b64, encrypted_hidden_data_b64 = encrypt_data(hidden_data, args.public_key)
106100

107101
full_filename = os.path.basename(args.file).encode('utf-8')
108-
full_filename += b' ' * (FILENAME_SIZE - len(full_filename))
102+
full_filename_b64 = base64.b64encode(full_filename).decode('utf-8')
103+
full_filename_b64 += ' ' * (FILENAME_SIZE - len(full_filename_b64))
109104

110105
with open(args.output, 'wb') as output_file:
111106
output_file.write(host_data)
112-
output_file.write(enc_session_key)
113-
output_file.write(salt)
114-
output_file.write(full_filename)
115-
output_file.write(encrypted_hidden_data)
116-
output_file.write(struct.pack('<IIII', len(enc_session_key), len(salt), FILENAME_SIZE, len(encrypted_hidden_data)))
107+
output_file.write(enc_session_key_b64.encode('utf-8'))
108+
output_file.write(salt_b64.encode('utf-8'))
109+
output_file.write(full_filename_b64.encode('utf-8'))
110+
output_file.write(encrypted_hidden_data_b64.encode('utf-8'))
111+
output_file.write(struct.pack('<IIII', len(enc_session_key_b64), len(salt_b64), FILENAME_SIZE, len(encrypted_hidden_data_b64)))
117112

118113
print("The file has been successfully hidden and encrypted within the host file!")
119114
except Exception as e:
120115
print("Error:", str(e))
121-
messagebox.showerror("Argument Error", "Missing arguments for hiding a file.")
116+
messagebox.showerror("Error", "An error occurred while hiding the file.")
122117
sys.exit()
123118

124119
elif args.unhide and args.host and args.private_key and args.output:
@@ -128,45 +123,39 @@ def decrypt_data(enc_session_key, salt, data, private_key_path, passphrase):
128123
enc_session_key_size, salt_size, filename_size, encrypted_hidden_data_size = struct.unpack('<IIII', host_file.read(16))
129124
host_file.seek(0)
130125
host_data = host_file.read()
131-
enc_session_key = host_data[-(16 + enc_session_key_size + salt_size + filename_size + encrypted_hidden_data_size):-16 - salt_size - filename_size - encrypted_hidden_data_size]
132-
salt = host_data[-(16 + salt_size + filename_size + encrypted_hidden_data_size):-16 - filename_size - encrypted_hidden_data_size]
133-
full_filename = host_data[-(16 + filename_size + encrypted_hidden_data_size):-16 - encrypted_hidden_data_size].rstrip(b' ')
134-
encrypted_hidden_data = host_data[-(16 + encrypted_hidden_data_size):-16]
126+
enc_session_key_b64 = host_data[-(16 + enc_session_key_size + salt_size + filename_size + encrypted_hidden_data_size):-16 - salt_size - filename_size - encrypted_hidden_data_size].decode('utf-8')
127+
salt_b64 = host_data[-(16 + salt_size + filename_size + encrypted_hidden_data_size):-16 - filename_size - encrypted_hidden_data_size].decode('utf-8')
128+
full_filename_b64 = host_data[-(16 + filename_size + encrypted_hidden_data_size):-16 - encrypted_hidden_data_size].decode('utf-8').rstrip(' ')
129+
encrypted_hidden_data_b64 = host_data[-(16 + encrypted_hidden_data_size):-16].decode('utf-8')
135130

136-
decrypted_data = decrypt_data(enc_session_key, salt, encrypted_hidden_data, args.private_key, args.passphrase)
131+
decrypted_data = decrypt_data(enc_session_key_b64, salt_b64, encrypted_hidden_data_b64, args.private_key, args.passphrase)
137132

138133
with open(args.output, 'wb') as output_file:
139134
output_file.write(decrypted_data)
140135

141136
print(f"Hidden file was successfully decrypted and extracted to {args.output}!")
142137
except Exception as e:
143138
print("Error:", str(e))
144-
messagebox.showerror("Argument Error", "Missing arguments for unhiding a file.")
145-
139+
messagebox.showerror("Error", "An error occurred while unhiding the file.")
146140
sys.exit()
147141

148142
else:
149-
messagebox.showerror("Argument Error", "Missing arguments")
150-
151-
sys.exit()
143+
messagebox.showerror("Error", "Missing arguments")
144+
sys.exit()
152145

153146
else:
154-
155-
156-
157147
root = tk.Tk()
158148
root.title("File Hider")
159149

160150
# Center the window on the screen
161-
window_width = 400
162-
window_height = 150
151+
window_width = 300
152+
window_height = 100
163153
screen_width = root.winfo_screenwidth()
164154
screen_height = root.winfo_screenheight()
165155
center_x = int(screen_width / 2 - window_width / 2)
166156
center_y = int(screen_height / 2 - window_height / 2)
167157
root.geometry(f'{window_width}x{window_height}+{center_x}+{center_y}')
168158

169-
# Function to hide and encrypt a file within another file
170159
def hide_file():
171160
host_file_path = filedialog.askopenfilename(title="Select the host file", filetypes=[("All Files", "*.*")])
172161
if not host_file_path:
@@ -191,26 +180,24 @@ def hide_file():
191180
with open(hidden_file_path, 'rb') as hidden_file:
192181
hidden_data = hidden_file.read()
193182

194-
enc_session_key, salt, encrypted_hidden_data = encrypt_data(hidden_data, public_key_path)
183+
enc_session_key_b64, salt_b64, encrypted_hidden_data_b64 = encrypt_data(hidden_data, public_key_path)
195184

196-
# Save the file extension and filename of the hidden file
197185
full_filename = os.path.basename(hidden_file_path).encode('utf-8')
198-
full_filename += b' ' * (FILENAME_SIZE - len(full_filename)) # Pad the full filename to FILENAME_SIZE
186+
full_filename_b64 = base64.b64encode(full_filename).decode('utf-8')
187+
full_filename_b64 += ' ' * (FILENAME_SIZE - len(full_filename_b64))
199188

200189
with open(output_path, 'wb') as output_file:
201190
output_file.write(host_data)
202-
output_file.write(enc_session_key)
203-
output_file.write(salt)
204-
output_file.write(full_filename) # Write the padded full filename
205-
output_file.write(encrypted_hidden_data)
206-
# Store the sizes of the encrypted session key, salt, full filename, and encrypted hidden data
207-
output_file.write(struct.pack('<IIII', len(enc_session_key), len(salt), FILENAME_SIZE, len(encrypted_hidden_data)))
191+
output_file.write(enc_session_key_b64.encode('utf-8'))
192+
output_file.write(salt_b64.encode('utf-8'))
193+
output_file.write(full_filename_b64.encode('utf-8'))
194+
output_file.write(encrypted_hidden_data_b64.encode('utf-8'))
195+
output_file.write(struct.pack('<IIII', len(enc_session_key_b64), len(salt_b64), FILENAME_SIZE, len(encrypted_hidden_data_b64)))
208196

209197
messagebox.showinfo("Success", "The file has been successfully hidden and encrypted within the host file!")
210198
except Exception as e:
211-
messagebox.showerror("Error", str(e))
199+
messagebox.showerror("Error", "An error occurred while hiding the file: " + str(e))
212200

213-
# Function to extract and decrypt the hidden file from the host file
214201
def unhide_file():
215202
host_file_path = filedialog.askopenfilename(title="Select the modified host file", filetypes=[("All Files", "*.*")])
216203
if not host_file_path:
@@ -221,45 +208,42 @@ def unhide_file():
221208
return
222209

223210
passphrase = simpledialog.askstring("Passphrase", "Enter the passphrase for the private key:", show="*")
224-
if passphrase is None: # Allow empty passphrase (not recommended)
211+
if passphrase is None:
225212
passphrase = ''
226213

227214
try:
228215
with open(host_file_path, 'rb') as host_file:
229-
host_file.seek(-16, os.SEEK_END) # Seek to the last 16 bytes where the sizes are stored
216+
host_file.seek(-16, os.SEEK_END)
230217
enc_session_key_size, salt_size, filename_size, encrypted_hidden_data_size = struct.unpack('<IIII', host_file.read(16))
231218
host_file.seek(0)
232219
host_data = host_file.read()
233-
# Extract the encrypted session key, salt, full filename, and encrypted hidden data
234-
enc_session_key = host_data[-(16 + enc_session_key_size + salt_size + filename_size + encrypted_hidden_data_size):-16 - salt_size - filename_size - encrypted_hidden_data_size]
235-
salt = host_data[-(16 + salt_size + filename_size + encrypted_hidden_data_size):-16 - filename_size - encrypted_hidden_data_size]
236-
full_filename = host_data[-(16 + filename_size + encrypted_hidden_data_size):-16 - encrypted_hidden_data_size].rstrip(b' ') # Remove padding
237-
encrypted_hidden_data = host_data[-(16 + encrypted_hidden_data_size):-16]
220+
enc_session_key_b64 = host_data[-(16 + enc_session_key_size + salt_size + filename_size + encrypted_hidden_data_size):-16 - salt_size - filename_size - encrypted_hidden_data_size].decode('utf-8')
221+
salt_b64 = host_data[-(16 + salt_size + filename_size + encrypted_hidden_data_size):-16 - filename_size - encrypted_hidden_data_size].decode('utf-8')
222+
full_filename_b64 = host_data[-(16 + filename_size + encrypted_hidden_data_size):-16 - encrypted_hidden_data_size].decode('utf-8').rstrip(' ')
223+
encrypted_hidden_data_b64 = host_data[-(16 + encrypted_hidden_data_size):-16].decode('utf-8')
238224

239-
decrypted_data = decrypt_data(enc_session_key, salt, encrypted_hidden_data, private_key_path, passphrase)
225+
decrypted_data = decrypt_data(enc_session_key_b64, salt_b64, encrypted_hidden_data_b64, private_key_path, passphrase)
226+
227+
original_filename = base64.b64decode(full_filename_b64).decode('utf-8')
240228

241-
# Ask for the directory to save the file
242229
output_directory = filedialog.askdirectory(title="Select the output directory")
243230
if not output_directory:
244231
return
245232

246-
# Ask for the new filename, providing the original as the default
247-
original_filename = full_filename.decode('utf-8')
248233
new_filename = simpledialog.askstring("New Filename", "Enter a new filename or use the original:", initialvalue=original_filename)
249234
if new_filename is None:
250235
return
251236

252-
# Automatically generate the output path with the new filename and extension
253237
output_path = os.path.join(output_directory, new_filename)
254238

255239
with open(output_path, 'wb') as output_file:
256240
output_file.write(decrypted_data)
257241

258242
messagebox.showinfo("Success", f"Hidden file was successfully decrypted and extracted to {output_path}!")
259243
except Exception as e:
260-
messagebox.showerror("Error", str(e))
244+
messagebox.showerror("Error", "An error occurred while unhiding the file: " + str(e))
245+
261246

262-
# GUI buttons
263247
hide_button = tk.Button(root, text="Hide and Encrypt File", command=hide_file)
264248
hide_button.pack(fill=tk.X, expand=True, padx=10, pady=5)
265249

0 commit comments

Comments
 (0)