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:
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():
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):
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', 'rb') 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', 'wb') 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:
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