python-gnupg

0.5.6 · active · verified Sun Apr 05

The `python-gnupg` library provides a Python wrapper for the GNU Privacy Guard (GnuPG or GPG), enabling Python programs to encrypt, decrypt, sign data, verify signatures, and manage GPG keys. It is actively maintained by Vinay Sajip with frequent bug-fix and enhancement releases. The current version is 0.5.6.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to initialize `python-gnupg`, generate a new GPG key, encrypt a string using that key, and then decrypt it. It uses a temporary `gnupghome` to avoid affecting your existing GnuPG setup and includes a check for the `gpg` executable. Remember that key generation requires sufficient system entropy, and passphrase handling can be complex with GnuPG versions >= 2.1.

import gnupg
import os
import tempfile
import shutil
import subprocess

def check_gpg_installed():
    try:
        subprocess.run(['gpg', '--version'], check=True, capture_output=True)
        return True
    except (subprocess.CalledProcessError, FileNotFoundError):
        return False

if not check_gpg_installed():
    print("GnuPG (gpg) executable not found. Please install GnuPG first.")
    exit(1)

# Create a temporary directory for GnuPG home to avoid interfering with user's keyring
try:
    temp_gnupghome = tempfile.mkdtemp()
    print(f"Using temporary GnuPG home: {temp_gnupghome}")

    gpg = gnupg.GPG(gnupghome=temp_gnupghome)
    # For GnuPG >= 2.1, passphrases might require 'allow-loopback-pinentry' in gpg-agent.conf
    # For a quickstart, we generate a key without protection for simplicity if supported by GnuPG version.
    # However, 'passphrase' is generally required for security.
    
    # Generate a key
    # Note: Real key generation might require sufficient entropy on your system
    input_data = gpg.gen_key_input(
        key_type='RSA',
        key_length=2048,
        name_real='Test User',
        name_email='test@example.com',
        passphrase='mysecretpassword',
        no_protection=False # Keep True for keys without passphrase, False for password-protected
    )
    key = gpg.gen_key(input_data)

    if not key.ok:
        print(f"Key generation failed: {key.status} - {key.stderr}")
        if "no_protection" in key.stderr and "passphrase" in key.stderr and gpg.version[0] >= 2:
            print("Hint: For GnuPG >= 2.1, generating keys with an empty passphrase (no_protection=True) or without `allow-loopback-pinentry` might fail. Try providing a passphrase.")
        exit(1)

    print(f"Generated key: {key.fingerprint}")

    # List keys to confirm
    public_keys = gpg.list_keys()
    print("Public keys:")
    for k in public_keys:
        print(f"  {k['keyid']} - {k['uids']}")

    # Encrypt a message
    unencrypted_string = "This is a secret message."
    encrypted_data = gpg.encrypt(
        unencrypted_string,
        recipients=[key.fingerprint],
        always_trust=True  # Use --trust-model always in newer gpg, but always_trust is for this library.
    )

    if not encrypted_data.ok:
        print(f"Encryption failed: {encrypted_data.status} - {encrypted_data.stderr}")
        exit(1)

    print(f"Encrypted message: {encrypted_data.data.decode('utf-8')[:50]}...")

    # Decrypt the message
    decrypted_data = gpg.decrypt(
        encrypted_data.data,
        passphrase='mysecretpassword'
    )

    if not decrypted_data.ok:
        print(f"Decryption failed: {decrypted_data.status} - {decrypted_data.stderr}")
        exit(1)

    print(f"Decrypted message: {decrypted_data.data.decode('utf-8')}")
    assert decrypted_data.data.decode('utf-8') == unencrypted_string
    print("Encryption and decryption successful!")

finally:
    # Clean up the temporary directory
    if 'temp_gnupghome' in locals() and os.path.exists(temp_gnupghome):
        print(f"Cleaning up temporary GnuPG home: {temp_gnupghome}")
        shutil.rmtree(temp_gnupghome)

view raw JSON →