'How to choose encryption/decryption key in python-gnupg?
I am trying to use alternate secret key in python-gnupg, equivalent to -u switch for commands:
gpg --encrypt --armor -r <<theirkeyid>> -u <<my_nondefault_key_id>>
gpg --decrypt -r <<theirkeyid>> -u <<my_nondefault_key_id>>
but cannot figure it out, python-gnupg always uses my default private key. Only thing I figured out is maybe to use another keyring, or is there a way? Or does another py library support multiple private keys?
Solution 1:[1]
In python-gnupg the recipient keys "-r <<theirkeyid>>" accepts a list, with a convenience to allow you to just use a string.
Add your nondefaultkeyid to the list for the recipients and python-gnupg seems to notice the included private and uses this for the default key. Example:
recipients=["<<theirkeyid>>", "<<nondefault_key_id>>"]
encrypt_file(file, recipients)
The above is working for me, although it is not obvious 'why'?
Hint: I add myself to the recipient list, so I can decrypt the file to validate that the encrypted file is not corrupted (and restore the original file if the raw original has disappeared.)
Two other options (if you are looking for more certainty)
- sign
- extra_args
sign
Setting the 'default-key' is explicitly supported when you sign the encrypted file.
For example, your function call would look like the below:
encrypt_file( file, "<<theirkeyid>>", armor=True, sign="<<nondefault_key_id>>")
A snippet from the python-gnupg code tells us that to 'sign' a file, python-gnupg sets the command-line option for '--sign' and then sets the '--default-key' to the identity specified for the 'sign'ing.
if sign is True: # pragma: no cover
args.append('--sign')
elif sign: # pragma: no cover
args.extend(['--sign', '--default-key', no_quote(sign)])
Ref: https://bitbucket.org/vinay.sajip/python-gnupg/src/master/gnupg.py
extra_args
What if you don't want to sign, and walk your own path?
What we want, is to add the following command-line options to 'gpg'
--default-key <<nondefault_key_id>>
From the same above documentation, it seems you could also get away by using the extra_args option:
The documentation parameters for encrypt_file, and extra_args is:
def encrypt_file(self,
file,
recipients,
sign=None,
always_trust=False,
passphrase=None,
armor=True,
output=None,
symmetric=False,
extra_args=None):
...
...
if extra_args:
args.extend(extra_args)
Where extra_args is a python list of command-line options.
We can use extra_args to pass further customised options for encrypt_file. Below is an example:
encrypt_file( file, "<<theirkeyid>>", armor=True, extra_args=["--default-key", "<<nondefault_key_id>>"])
Let us know which works best for you.
Solution 2:[2]
- when
--encrypting only the other party's public key is used, in this case the-uoption is ignored - the recipient's keys can be set in the
options.recipientslist. - likewise when
--decrypting the-roption is ignored. Usually the key used to decrypt is auomatically determined from the key id in the message. Unless of yours the message is encrypted with more then one public keys, and you have more then one matching private keys in your keystore. - you can set the default key on
options.default_key if you want to use a different keystore file, you can either add it to the extra arguments or use it directyl in the
callargument list:gpg = GnuPGIntreface.GnuPG() # ... gpg.options.recipients += ['spam', 'eggs'] gpg.options.extra_args += ['--keyring', 'keyringfile'] # ... # or: gpg.call(['--encrypt', '--keyring', 'keyringfile']) # ...
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | mata |
