PyGPGME Cookbook¶
The following recipes illustrate typical use cases of PyGPGME. For a detailed documentation of the individual classes and methods please refer to the API documentation.
Listing All Keys¶
Use Context.keylist()
without arguments to get all keys:
from __future__ import print_function
import gpgme
c = gpgme.Context()
for key in c.keylist():
user = key.uids[0]
print("Keys for %s (%s):" % (user.name, user.email))
for subkey in key.subkeys:
features = []
if subkey.can_authenticate:
features.append('auth')
if subkey.can_certify:
features.append('cert')
if subkey.can_encrypt:
features.append('encrypt')
if subkey.can_sign:
features.append('sign')
print(' %s %s' %(subkey.fpr, ','.join(features)))
Searching for a Specific Key¶
To search for a key using parts of the key owner’s name or e-mail address, pass
a query to gpgme.Context.keylist()
:
from __future__ import print_function
import gpgme
c = gpgme.Context()
for key in c.keylist('john'):
print(key.subkeys[0].fpr)
To get a key via its fingerprint, use gpgme.Context.get_key()
instead
(note that you must pass the full fingerprint):
from __future__ import print_function
import gpgme
c = gpgme.Context()
fingerprint = 'key fingerprint to search for'
try:
key = c.get_key(fingerprint)
print('%s (%s)' % (key.uids[0].name, key.uids[0].email))
except gpgme.GpgmeError:
print("No key for fingerprint '%s'." % fingerprint)
Encrypting and Decrypting Files¶
By default, gpgme.Context.encrypt()
returns the encrypted data in binary
form, so make sure to open the ciphertext files in binary mode:
import gpgme
c = gpgme.Context()
recipient = c.get_key("fingerprint of recipient's key")
# Encrypt
with open('foo.txt', 'r') as input_file:
with open('foo.txt.gpg', 'wb') as output_file:
c.encrypt([recipient], 0, input_file, output_file)
# Decrypt
with open('foo.txt.gpg', 'rb') as input_file:
with open('foo2.txt', 'w') as output_file:
c.decrypt(input_file, output_file)
If you set gpgme.Context.armor
to True
then the ciphertext is
encoded in a so-called ASCII-armor string. In that case, the ciphertext file
should be opened in text mode.
The example above uses asymmetric encryption, i.e. the data is encrypted
using a public key and can only be decrypted using the corresponding private
key. If you want to use symmetric encryption instead (where encryption
and decryption use the same passphrase) then pass None
as the first
argument to gpgme.Context.encrypt()
. In that case you will be prompted
for the passphrase.
Encrypting and Decrypting Bytes and Strings¶
gpgme.Context.encrypt()
and gpgme.Context.decrypt()
operate
on streams of data (i.e. file-like objects). If you want to encrypt or decrypt
data from bytes variables instead then you need to wrap them in a
suitable buffer (e.g. io.BytesIO
):
import io
import gpgme
c = gpgme.Context()
recipient = c.get_key("fingerprint of recipient's key")
plaintext_bytes = io.BytesIO(b'plain binary data')
encrypted_bytes = io.BytesIO()
c.encrypt([recipient], 0, plaintext_bytes, encrypted_bytes)
encrypted_bytes.seek(0) # Return file pointer to beginning of file
decrypted_bytes = io.BytesIO()
c.decrypt(encrypted_bytes, decrypted_bytes)
assert decrypted_bytes.getvalue() == plaintext_bytes.getvalue()
Note that gpgme.Context.encrypt()
only accepts binary buffers – passing
text buffers like io.StringIO
raises gpgme.GpgmeError
.
To encrypt string data, you therefore need to encode it to binary first:
import io
import gpgme
c = gpgme.Context()
recipient = c.get_key("fingerprint of recipient's key")
plaintext_string = u'plain text data'
plaintext_bytes = io.BytesIO(plaintext_string.encode('utf8'))
encrypted_bytes = io.BytesIO()
c.encrypt([recipient], 0, plaintext_bytes, encrypted_bytes)
encrypted_bytes.seek(0) # Return file pointer to beginning of file
decrypted_bytes = io.BytesIO()
c.decrypt(encrypted_bytes, decrypted_bytes)
decrypted_string = decrypted_bytes.getvalue().decode('utf8')
assert decrypted_string == plaintext_string
Even if gpgme.Context.armor
is true and the encrypted output is text
you still need to use binary buffers. That is not a problem, however, since the
armor uses plain ASCII:
from __future__ import print_function
import io
import gpgme
c = gpgme.Context()
recipient = c.get_key("fingerprint of recipient's key")
c.armor = True # Use ASCII-armor output
plaintext_string = u'plain text data'
plaintext_bytes = io.BytesIO(plaintext_string.encode('utf8'))
encrypted_bytes = io.BytesIO()
c.encrypt([recipient], 0, plaintext_bytes, encrypted_bytes)
encrypted_string = encrypted_bytes.getvalue().decode('ascii')
print(encrypted_string) # Display ASCII armored ciphertext
# Re-initialize encrypted bytes data from ASCII armor
encrypted_bytes = io.BytesIO(encrypted_string.encode('ascii'))
decrypted_bytes = io.BytesIO()
c.decrypt(encrypted_bytes, decrypted_bytes)
decrypted_string = decrypted_bytes.getvalue().decode('utf8')
assert decrypted_string == plaintext_string
Signing¶
FIXME
Verifying a Signature¶
FIXME
Generating Keys¶
FIXME
Using a Passphrase Callback¶
FIXME
Using a Different GPG Base Directory¶
FIXME