-
-
Notifications
You must be signed in to change notification settings - Fork 47
Expand file tree
/
Copy pathlazyenc.py
More file actions
131 lines (113 loc) · 4.57 KB
/
Copy pathlazyenc.py
File metadata and controls
131 lines (113 loc) · 4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import argparse
import base64
import getpass
import os
from cryptography.fernet import Fernet, InvalidToken
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
def derive_key(password: str, salt: bytes = b'lazyown_salt') -> bytes:
"""
Derive an AES key from the password using PBKDF2.
Args:
password (str): The user-provided password.
salt (bytes): Salt for key derivation. Defaults to b'lazyown_salt'.
Returns:
bytes: Base64-encoded key suitable for Fernet.
"""
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
)
key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
return key
def encrypt_directory(directory: str, cipher: Fernet, exclude_files: list) -> None:
"""
Encrypt all files in the specified directory.
Args:
directory (str): Path to the directory to encrypt.
cipher (Fernet): Fernet cipher instance for encryption.
exclude_files (list): List of file paths to exclude from encryption.
Raises:
Exception: If encryption fails for any file.
"""
for root, _, files in os.walk(directory):
for file in files:
file_path = os.path.join(root, file)
if file_path in exclude_files:
continue
try:
with open(file_path, 'rb') as f:
data = f.read()
encrypted_data = cipher.encrypt(data)
with open(file_path, 'wb') as f:
f.write(encrypted_data)
print(f"Encrypted: {file_path}")
except Exception as e:
print(f"Error encrypting {file_path}: {e}")
def decrypt_directory(directory: str, cipher: Fernet, exclude_files: list) -> None:
"""
Decrypt all files in the specified directory.
Args:
directory (str): Path to the directory to decrypt.
cipher (Fernet): Fernet cipher instance for decryption.
exclude_files (list): List of file paths to exclude from decryption.
Raises:
InvalidToken: If the decryption key is incorrect.
Exception: If decryption fails for any file.
"""
for root, _, files in os.walk(directory):
for file in files:
file_path = os.path.join(root, file)
if file_path in exclude_files:
continue
try:
with open(file_path, 'rb') as f:
encrypted_data = f.read()
decrypted_data = cipher.decrypt(encrypted_data)
with open(file_path, 'wb') as f:
f.write(decrypted_data)
print(f"Decrypted: {file_path}")
except InvalidToken:
print(f"Invalid key for {file_path}")
raise
except Exception as e:
print(f"Error decrypting {file_path}: {e}")
def main():
"""
Main function to encrypt or decrypt a directory using a password-derived key.
Parses command-line arguments for action, directory, and optional key file.
Prompts for a password and performs the requested operation.
"""
parser = argparse.ArgumentParser(description="Encrypt or decrypt a LazyOwn directory")
parser.add_argument('action', choices=['encrypt', 'decrypt'], help="Action to perform")
parser.add_argument('--directory', required=True, help="Path to the LazyOwn directory")
parser.add_argument('--key-file', help="Path to the AES key file (optional)")
args = parser.parse_args()
# Validate directory
if not os.path.isdir(args.directory):
print(f"Error: {args.directory} is not a valid directory")
exit(1)
exclude_files = [os.path.abspath(__file__)]
if args.key_file:
exclude_files.append(os.path.abspath(args.key_file))
password = getpass.getpass("Enter the password: ")
key = derive_key(password)
cipher = Fernet(key)
try:
if args.action == 'decrypt':
decrypt_directory(args.directory, cipher, exclude_files)
print("Directory decrypted successfully. You can now work with LazyOwn.")
print("Remember to encrypt the directory after your session.")
elif args.action == 'encrypt':
encrypt_directory(args.directory, cipher, exclude_files)
print("Directory encrypted successfully.")
except InvalidToken:
print("Incorrect password. Decryption failed.")
exit(1)
except Exception as e:
print(f"Error: {e}")
exit(1)
if __name__ == "__main__":
main()