Commit b98603ac13b1090537bf8a7c5793da1c14020cb3

Authored by Christian Herdtweck
1 parent 99ff607c

crypto: improve decrypt after some testing

Showing 1 changed file with 18 additions and 17 deletions
oletools/crypto.py
@@ -204,17 +204,26 @@ def decrypt(filename, passwords=None, **temp_file_args): @@ -204,17 +204,26 @@ def decrypt(filename, passwords=None, **temp_file_args):
204 :type passwords: iterable or str or None 204 :type passwords: iterable or str or None
205 :param temp_file_args: arguments for :py:func:`tempfile.mkstemp` e.g., 205 :param temp_file_args: arguments for :py:func:`tempfile.mkstemp` e.g.,
206 `dirname` or `prefix`. `suffix` will default to 206 `dirname` or `prefix`. `suffix` will default to
207 - suffix of input `filename`; `text` will be ignored 207 + suffix of input `filename`, `prefix` defaults to
  208 + `oletools-decrypt-`; `text` will be ignored
208 :returns: name of the decrypted temporary file. 209 :returns: name of the decrypted temporary file.
209 :raises: :py:class:`ImportError` if :py:mod:`msoffcrypto-tools` not found 210 :raises: :py:class:`ImportError` if :py:mod:`msoffcrypto-tools` not found
210 :raises: :py:class:`ValueError` if the given file is not encrypted 211 :raises: :py:class:`ValueError` if the given file is not encrypted
211 """ 212 """
212 _check_msoffcrypto() 213 _check_msoffcrypto()
213 214
214 - if passwords is None:  
215 - passwords = (WRITE_PROTECT_ENCRYPTION_PASSWORD, )  
216 - elif isinstance(passwords, str): 215 + # normalize password so we always have a list/tuple
  216 + if isinstance(passwords, str):
217 passwords = (passwords, ) 217 passwords = (passwords, )
  218 + elif not passwords:
  219 + passwords = (WRITE_PROTECT_ENCRYPTION_PASSWORD, )
  220 +
  221 + # check temp file args
  222 + if 'prefix' not in temp_file_args:
  223 + temp_file_args['prefix'] = 'oletools-decrypt-'
  224 + if 'suffix' not in temp_file_args:
  225 + temp_file_args['suffix'] = splitext(filename)[1]
  226 + temp_file_args['text'] = False
218 227
219 decrypt_file = None 228 decrypt_file = None
220 with open(filename, 'rb') as reader: 229 with open(filename, 'rb') as reader:
@@ -224,19 +233,13 @@ def decrypt(filename, passwords=None, **temp_file_args): @@ -224,19 +233,13 @@ def decrypt(filename, passwords=None, **temp_file_args):
224 .format(filename)) 233 .format(filename))
225 234
226 for password in passwords: 235 for password in passwords:
227 - try:  
228 - crypto_file.load_key(password=password)  
229 - except Exception:  
230 - continue # password verification failed, try next  
231 -  
232 - # create temp file  
233 - if 'suffix' not in temp_file_args:  
234 - temp_file_args['suffix'] = splitext(filename)[1]  
235 - temp_file_args['text'] = False  
236 -  
237 write_descriptor = None 236 write_descriptor = None
238 write_handle = None 237 write_handle = None
  238 + decrypt_file = None
239 try: 239 try:
  240 + crypto_file.load_key(password=password)
  241 +
  242 + # create temp file
240 write_descriptor, decrypt_file = mkstemp(**temp_file_args) 243 write_descriptor, decrypt_file = mkstemp(**temp_file_args)
241 write_handle = os.fdopen(write_descriptor, 'wb') 244 write_handle = os.fdopen(write_descriptor, 'wb')
242 write_descriptor = None # is now handled via write_handle 245 write_descriptor = None # is now handled via write_handle
@@ -247,8 +250,7 @@ def decrypt(filename, passwords=None, **temp_file_args): @@ -247,8 +250,7 @@ def decrypt(filename, passwords=None, **temp_file_args):
247 write_handle = None 250 write_handle = None
248 break 251 break
249 except Exception: 252 except Exception:
250 - # error: clean up: close everything and del file ignoring errors;  
251 - # then re-raise original exception 253 + # error-clean up: close everything and del temp file
252 if write_handle: 254 if write_handle:
253 write_handle.close() 255 write_handle.close()
254 elif write_descriptor: 256 elif write_descriptor:
@@ -256,6 +258,5 @@ def decrypt(filename, passwords=None, **temp_file_args): @@ -256,6 +258,5 @@ def decrypt(filename, passwords=None, **temp_file_args):
256 if decrypt_file and isfile(decrypt_file): 258 if decrypt_file and isfile(decrypt_file):
257 os.unlink(decrypt_file) 259 os.unlink(decrypt_file)
258 decrypt_file = None 260 decrypt_file = None
259 - raise  
260 # if we reach this, all passwords were tried without success 261 # if we reach this, all passwords were tried without success
261 return decrypt_file 262 return decrypt_file