Commit 1f04b96d5eb601fa84e97274d84136d78d6ab0e2
1 parent
826bee0b
crypto: layout how to best integrate crypto into code
Showing
1 changed file
with
37 additions
and
0 deletions
oletools/crypto.py
| ... | ... | @@ -8,6 +8,43 @@ information on encryption in OLE files. |
| 8 | 8 | Uses :py:mod:`msoffcrypto-tool` to decrypt if it is available. Otherwise |
| 9 | 9 | decryption will fail with an ImportError. |
| 10 | 10 | |
| 11 | +Encryption/Write-Protection can be realized in many different ways. They range | |
| 12 | +from setting a single flag in an otherwise unprotected file to embedding a | |
| 13 | +regular file (e.g. xlsx) in an EncryptedStream inside an OLE file. That means | |
| 14 | +that (1) that lots of bad things are accesible even if no encryption password | |
| 15 | +is known, and (2) even basic attributes like the file type can change by | |
| 16 | +decryption. Therefore I suggest the following general routine to deal with | |
| 17 | +potentially encrypted files:: | |
| 18 | + | |
| 19 | + def script_main_function(input_file, args): | |
| 20 | + '''Wrapper around main function to deal with encrypted files.''' | |
| 21 | + initial_stuff(input_file, args) | |
| 22 | + result = None | |
| 23 | + try: | |
| 24 | + result = do_your_thing_assuming_no_encryption(input_file) | |
| 25 | + if not crypto_is_encrypted(input_file): | |
| 26 | + return result | |
| 27 | + except Exception: | |
| 28 | + if not crypto_is_encrypted(input_file): | |
| 29 | + raise | |
| 30 | + decrypted_file = None | |
| 31 | + try: | |
| 32 | + decrypted_file = crypto.decrypt(input_file) | |
| 33 | + except Exception: | |
| 34 | + raise | |
| 35 | + finally: # clean up | |
| 36 | + try: # (maybe file was not yet created) | |
| 37 | + os.unlink(decrypted_file) | |
| 38 | + except Exception: | |
| 39 | + pass | |
| 40 | + | |
| 41 | +That means that caller code needs another wrapper around its main function. I | |
| 42 | +did try it another way first (a transparent on-demand unencrypt) but for the | |
| 43 | +above reasons I believe this is the better way. Also, non-top-level-code can | |
| 44 | +just assume that it works on unencrypted data and fail with an exception if | |
| 45 | +encrypted data makes its work impossible. No need to check `if is_encrypted()` | |
| 46 | +at the start of functions. | |
| 47 | + | |
| 11 | 48 | .. seealso:: [MS-OFFCRYPTO] |
| 12 | 49 | .. seealso:: https://github.com/nolze/msoffcrypto-tool |
| 13 | 50 | ... | ... |