1

I'm able to embed the original filename using python-gnupg when encrypting a file using below:

filename = 'test.tim'
with open(filename, 'rb) as fh:
    status = gpg.encrypt_file(fh, recipients='somerecipient', output='test.tim.gpg',\
        sign='somesignature', extra_args=['--set-filename', os.path.basename(filename)])

This can be verified by using gpg from the command line:

$ gpg2 --list-packets test.tim.gpg | grep name

I am however unable to preserve the original filename when decrypting the file:

with open(filename, 'rb') as fh:
    status = gpg.decrypt_file(fh, extra_args['--use-embedded-filename'])

I am aware about the output parameter (which specifies the filename to save contents to) in the decrypt_file function, but i want to preserve the original filename (which i won't always know)

It seems the decrypt_file function always passes the --decrypt flag to gpg which always ouputs the contents to stdout (unless used in conjunction with output parameter) as in:

$ gpg --decrypt --use-embedded-filename test.tim.gpg

Below command will decrypt and save output to original filename:

$ gpg --use-embedded-filename test.tim.gpg

Any ideas?

Tim

Timmah
  • 2,001
  • 19
  • 18

1 Answers1

1

The functionality to do what you want doesn't exist in the original python-gnupg.

There's a modified version here by isislovecruft (which is what you get if you pip install gnupg) that adds support for --list-packets with gpg.listpackets but still doesn't support --use-embeded-file-name

So my approach, if I were to insist on using python only, would probably be to start with isislovecruft's version and then subclass GPG like this:

import gnupg
import os

GPGBINARY = os.environ.get('GPGBINARY', 'gpg')
hd = os.path.join(os.getcwd(), 'keys')

class myGPG(gnupg.GPG):

    def decrypt_file_original_name(self, file, always_trust=False, passphrase=None, extra_args=None):
        args = ["--use-embedded-filename"]
        output = calculate_the_file_name_using_list_packets()
        self.set_output_without_confirmation(args, output)
        if always_trust:  # pragma: no cover
            args.append("--always-trust")
        if extra_args:
            args.extend(extra_args)
        result = self.result_map['crypt'](self)
        self._handle_io(args, file, result, passphrase, binary=True)
        # logger.debug('decrypt result: %r', result.data)
        return result

gpg = myGPG(gnupghome=hd, gpgbinary=GPGBINARY)

Bear in mind, at this point it is almost certainly much easier to just use subprocess and run the gpg binary directly from the shell, especially as you don't care about the output.

Anyway, I got this far and have run out of time for now, so I leave implementing calculate_the_file_name_using_list_packets up to you, if you choose to go the 'pure python' route. Hopefully it is a bit easier now you have gpg.list-packets. Good luck!

Rob Bricheno
  • 4,467
  • 15
  • 29