2323
2424from .c import CObfuscator
2525from .core import MappingManager , NameGenerator
26+ from .encrypt import EncryptionManager
2627from .python import PythonObfuscator
2728
2829
@@ -44,8 +45,14 @@ class CLIError(Exception):
4445 pass
4546
4647
47- class FileNotFoundError (CLIError ):
48- pass
48+ class FileNotFound (CLIError ):
49+ """Custom FileNotFound to avoid conflict with built-in FileNotFoundError"""
50+
51+ def __init__ (self , filepath : str = "" ):
52+ self .filepath = filepath
53+ super ().__init__ (
54+ f"File not found: { filepath } " if filepath else "File not found"
55+ )
4956
5057
5158class ObfuscationError (CLIError ):
@@ -58,6 +65,7 @@ class Options:
5865 input_file : Path
5966 output_file : Optional [Path ] = None
6067 key_file : Optional [Path ] = None
68+ password : Optional [str ] = None
6169 seed : Optional [int ] = None
6270 style : str = "similar"
6371 length : int = 16
@@ -69,9 +77,17 @@ class ObfuscationService:
6977 def __init__ (self , options : Options ):
7078 self .options = options
7179 self .mm = MappingManager ()
72- self .gen = NameGenerator (
73- length = options .length , style = options .style , seed = options .seed
74- )
80+ # If seed is not provided but password is, derive seed from password
81+ seed = options .seed
82+ if seed is None and options .password :
83+ # Deterministic seed from password for consistent obfuscation
84+ import hashlib
85+
86+ seed = int .from_bytes (
87+ hashlib .sha256 (options .password .encode ()).digest ()[:8 ], "big"
88+ )
89+
90+ self .gen = NameGenerator (length = options .length , style = options .style , seed = seed )
7591 self .stats_data = {}
7692
7793 def execute (self ) -> None :
@@ -90,7 +106,9 @@ def _obfuscate(self) -> None:
90106 if options .language == Language .PYTHON :
91107 obfuscator = PythonObfuscator (self .mm , self .gen , options .input_file .name )
92108 key_path = str (options .key_file ) if options .key_file else None
93- result = obfuscator .obfuscate (content , key_path ) # type: ignore
109+ result = obfuscator .obfuscate (
110+ content , key_path , encryption_key = options .password
111+ )
94112 else :
95113 obfuscator = CObfuscator (self .mm , self .gen , options .input_file .name )
96114 result = obfuscator .obfuscate (content )
@@ -128,7 +146,9 @@ def _restore(self) -> None:
128146 self .mm , self .gen , options .input_file .name
129147 )
130148 key_path = str (options .key_file ) if options .key_file else None
131- result = obfuscator .restore (key_path , content ) # type: ignore
149+ result = obfuscator .restore (
150+ key_path , content , encryption_key = options .password
151+ )
132152 else :
133153 obfuscator = CObfuscator (self .mm , self .gen , options .input_file .name )
134154 result = obfuscator .restore (content )
@@ -146,25 +166,23 @@ def _restore(self) -> None:
146166 def _read_file (self , path : Path ) -> str :
147167 try :
148168 return path .read_text (encoding = "utf-8" )
149- except FileNotFoundError :
150- raise FileNotFoundError (
169+ except OSError : # Catch file not found and other OS errors
170+ raise FileNotFound (
151171 f"❌ Error: Input file not found: { path } \n "
152172 f"💡 Hint: Check if the file path is correct or use an absolute path"
153173 )
154174 except PermissionError :
155- raise FileNotFoundError (
175+ raise FileNotFound (
156176 f"❌ Error: Permission denied: { path } \n "
157177 f"💡 Hint: Check file permissions or try running with appropriate rights"
158178 )
159179 except UnicodeDecodeError :
160- raise FileNotFoundError (
180+ raise FileNotFound (
161181 f"❌ Error: File encoding issue: { path } \n "
162182 f"💡 Hint: Ensure the file is a valid text file with UTF-8 encoding"
163183 )
164184 except Exception as e :
165- raise FileNotFoundError (
166- f"❌ Error: Failed to read { path } \n " f"💡 Details: { e } "
167- )
185+ raise FileNotFound (f"❌ Error: Failed to read { path } \n " f"💡 Details: { e } " )
168186
169187 def _write_file (self , path : Path , content : str ) -> None :
170188 try :
@@ -189,7 +207,7 @@ def _write_file(self, path: Path, content: str) -> None:
189207 def _load_mapping (self , key_file : Path ) -> None :
190208 try :
191209 self .mm .load_mapping (key_file )
192- except FileNotFoundError :
210+ except OSError : # Catch file not found and other OS errors
193211 raise ObfuscationError (
194212 f"❌ Error: Key file not found: { key_file } \n "
195213 f"💡 Hint: Ensure the key file exists or try restoration without --key (using embedded metadata)"
@@ -339,7 +357,10 @@ def _add_obfuscate_command(self, subparsers) -> None:
339357 )
340358 obf .add_argument ("input_file" , help = "Path to input source file" )
341359 obf .add_argument ("--out" , "-o" , help = "Path to output file" )
342- obf .add_argument ("--key" , "-k" , help = "Path to key file" )
360+ obf .add_argument ("--key" , "-k" , help = "Path to key file (JSON map)" )
361+ obf .add_argument (
362+ "--password" , "-p" , "--pwd" , help = "Password for encryption/decryption"
363+ )
343364 obf .add_argument ("--seed" , "-s" , type = int , help = "Random seed" )
344365 obf .add_argument (
345366 "--style" ,
@@ -368,7 +389,10 @@ def _add_restore_command(self, subparsers) -> None:
368389 )
369390 res .add_argument ("input_file" , help = "Path to obfuscated file" )
370391 res .add_argument ("--out" , "-o" , help = "Path to output file" )
371- res .add_argument ("--key" , "-k" , help = "Path to key file" )
392+ res .add_argument ("--key" , "-k" , help = "Path to key file (JSON map)" )
393+ res .add_argument (
394+ "--password" , "-p" , "--pwd" , help = "Password for encryption/decryption"
395+ )
372396 res .add_argument (
373397 "--stats" ,
374398 action = "store_true" ,
@@ -401,6 +425,11 @@ def _convert_to_options(self, raw) -> Options:
401425 if hasattr (raw , "seed" ) and raw .seed is not None
402426 else config .get ("seed" , None )
403427 ),
428+ password = (
429+ raw .password
430+ if hasattr (raw , "password" )
431+ else config .get ("password" , None )
432+ ),
404433 style = (
405434 raw .style
406435 if hasattr (raw , "style" ) and raw .style is not None
@@ -494,7 +523,7 @@ def run() -> None:
494523
495524 try :
496525 service .execute ()
497- except FileNotFoundError as e :
526+ except FileNotFound as e :
498527 print (f"{ e } " )
499528 sys .exit (1 )
500529 except ObfuscationError as e :
0 commit comments