Skip to main content

rpgp-py

Supported versions PyPI Downloads GitHub stars pyrefly License: MIT

Selected native Python bindings for rPGP, exposed as the openpgp package.

Installation

pip install rpgp-py

Requires Python 3.10 or newer.

API layout

Exposed rPGP types live in the namespace that matches their upstream Rust module. The upstream documentation is therefore useful for the exposed names and their OpenPGP semantics, but this package is not a complete projection of every rPGP module or trait.

Python namespace Purpose
openpgp.armor Native rPGP ASCII armor reader, writer, block types, and CRC status.
openpgp.composed Transferable keys, messages, signatures, message builders, and key-generation builders.
openpgp.packet Packet-shaped objects such as key packets, signatures, session-key packets, features, flags, and encrypted data packets.
openpgp.types Public-parameter objects, S2K configuration, packet header versions, and shared type helpers.
openpgp.crypto Crypto algorithm namespaces.
openpgp.errors The native rPGP binding exception.
openpgp.ser Native serialization helpers corresponding to rPGP's Serialize trait.
openpgp.util Binding-specific helper functions built on top of the Rust-shaped API.

Functionality

rpgp-py can:

  • parse armored and binary public keys, secret keys, detached signatures, and OpenPGP messages,
  • inspect transferable key details, users, subkeys, signatures, packet versions, key flags, features, public parameters, and S2K metadata,
  • verify key bindings, signed messages, detached signatures, and cleartext signatures,
  • build signed, compressed, password-encrypted, and recipient-encrypted messages,
  • decrypt messages with secret keys, passwords, or caller-supplied session keys,
  • generate modern OpenPGP key material, including v6 Ed25519/X25519 keys,
  • use RFC 9580-era features exposed by rPGP, including SEIPD v2, OCB, and Argon2 S2K,
  • parse and serialize individual native packet values and verify individual key and subkey signature packets,
  • use native armor, error, serialization, value-type, and algorithm bindings,
  • use convenience helpers from openpgp.util when you want one-call signing or encryption.

Usage

Parse and inspect keys

from openpgp.composed import SignedPublicKey, SignedSecretKey

public_key, headers = SignedPublicKey.from_armor(public_key_armor)
secret_key, _ = SignedSecretKey.from_armor(secret_key_armor)

public_key.verify_bindings()
secret_key.verify_bindings()

assert secret_key.to_public_key().fingerprint == public_key.fingerprint
assert public_key.primary_key.fingerprint == public_key.fingerprint
assert public_key.details.users[0].id == public_key.user_ids[0]

for signed_subkey in public_key.public_subkeys:
    print(signed_subkey.key.fingerprint)
    print(signed_subkey.signatures[0].typ())

params = public_key.public_params
print(params.kind)

Sign and verify a message

from openpgp.composed import Message, MessageBuilder

armored = (
    MessageBuilder.from_bytes("message.txt", b"hello world")
    .sign(secret_key, None, "sha256")
    .to_armored_string()
)

message, _ = Message.from_armor(armored)
signature = message.verify(public_key)

assert signature.hash_alg() == "sha256"
assert message.as_data_string() == "hello world"

Create and verify a detached signature

import os

from openpgp.composed import DetachedSignature


class SecureRandom:
    def randbytes(self, n: int) -> bytes:
        return os.urandom(n)


signature = DetachedSignature.sign_binary_data(
    SecureRandom(),
    secret_key,
    None,
    "sha512",
    b"payload",
)

signature.verify(public_key, b"payload")
assert signature.signature.hash_alg() == "sha512"

Work with cleartext signatures

from openpgp.composed import CleartextSignedMessage

cleartext = CleartextSignedMessage.sign("hello\n-world\n", secret_key)
armored = cleartext.to_armored()

reparsed, _ = CleartextSignedMessage.from_armor(armored)
reparsed.verify(public_key)

assert reparsed.signed_text() == "hello\r\n-world\r\n"
assert reparsed.signature_count() == 1

Encrypt to a recipient

from openpgp.composed import Message, MessageBuilder

armored = (
    MessageBuilder.from_bytes("secret.txt", b"secret payload")
    .seipd_v2("aes256", "ocb")
    .encrypt_to_key(public_key)
    .to_armored_string()
)

message, _ = Message.from_armor(armored)
decrypted = message.decrypt(None, secret_key)

assert decrypted.as_data_vec() == b"secret payload"

For anonymous recipients or multi-recipient messages, keep chaining recipient operations:

armored = (
    MessageBuilder.from_bytes("shared.txt", b"shared payload")
    .seipd_v2("aes256", "ocb")
    .encrypt_to_key_anonymous(first_public_key)
    .encrypt_to_key(second_public_key)
    .to_armored_string()
)

Encrypt with a password

from openpgp.composed import Message, MessageBuilder
from openpgp.types import StringToKey

armored = (
    MessageBuilder.from_bytes("", b"password protected")
    .seipd_v2("aes256", "ocb")
    .encrypt_with_password(StringToKey.argon2(1, 4, 21), "hunter2")
    .to_armored_string()
)

message, _ = Message.from_armor(armored)
decrypted = message.decrypt_with_password("hunter2")

assert decrypted.as_data_string() == "password protected"

Inspect encrypted packets and use a session key

from openpgp.composed import Message, MessageBuilder

session_key = bytes(range(16))
message_bytes = (
    MessageBuilder.from_bytes("", b"packet payload")
    .seipd_v2("aes128", "ocb")
    .set_session_key(session_key)
    .encrypt_to_key(public_key)
    .to_vec()
)

message = Message.from_bytes(message_bytes)
pkesk = message.public_key_encrypted_session_key_packets()[0]
edata = message.encrypted_data_packet()

assert pkesk.recipient_is_anonymous is False
assert edata.kind == "seipd-v2"
assert message.decrypt_with_session_key(session_key).as_data_vec() == b"packet payload"

Generate key material

from openpgp.composed import (
    EncryptionCaps,
    KeyType,
    SecretKeyParamsBuilder,
    SubkeyParamsBuilder,
)
from openpgp.types import PacketHeaderVersion, S2kParams, StringToKey

secret_key = (
    SecretKeyParamsBuilder()
    .version(6)
    .key_type(KeyType.ed25519())
    .packet_version(PacketHeaderVersion.new())
    .can_certify(True)
    .can_sign(True)
    .feature_seipd_v2(True)
    .primary_user_id("Me <me@example.com>")
    .passphrase("hunter2")
    .s2k(S2kParams.aead("aes256", "ocb", StringToKey.argon2(3, 4, 16)))
    .subkey(
        SubkeyParamsBuilder()
        .version(6)
        .key_type(KeyType.x25519())
        .packet_version(PacketHeaderVersion.new())
        .can_encrypt(EncryptionCaps.all())
        .build()
    )
    .generate()
)

public_key = secret_key.to_public_key()

secret_key.verify_bindings()
public_key.verify_bindings()

assert public_key.public_key_algorithm == "ed25519"
assert public_key.public_params.kind == "ed25519"

Use convenience helpers

Use openpgp.util when you want compact helpers instead of manually building a message pipeline:

from openpgp.util import encrypt_message_to_recipient, sign_message

signed = sign_message(b"hello", secret_key)
encrypted = encrypt_message_to_recipient(b"secret", public_key)

The helper namespace also includes multi-signer, cleartext, byte-output, multi-recipient, password-encryption, and session-key helpers.

Reference documentation

Versioning

rpgp-py follows the major and minor version of the underlying pgp crate. The patch version is incremented for Python-facing API changes and Rust-core build updates such as dependency updates or bug fixes.

Acknowledgements

Thanks to the rPGP contributors and maintainers for the Rust OpenPGP implementation that powers this package.

License

This repository is distributed under the MIT License.

Metadata

Release files for rpgp-py 0.20.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rpgp-py 0.20.0
File Size Uploaded
rpgp_py-0.20.0.tar.gz 144.2 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for rpgp-py 0.20.0
File
rpgp_py-0.20.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
rpgp_py-0.20.0-cp310-abi3-win32.whl CPython 3.10 abi3 Windows x86-32 Details
rpgp_py-0.20.0-cp310-abi3-musllinux_1_2_x86_64.whl CPython 3.10 abi3 Linux musl 1.2+ x86-64 Details
rpgp_py-0.20.0-cp310-abi3-musllinux_1_2_aarch64.whl CPython 3.10 abi3 Linux musl 1.2+ ARM64 Details
rpgp_py-0.20.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
rpgp_py-0.20.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details
rpgp_py-0.20.0-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details
rpgp_py-0.20.0-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details

Total release size: 25.8 MB

Release files / rpgp_py-0.20.0.tar.gz

Download URL rpgp_py-0.20.0.tar.gz
Size 144.2 kB
Tags Source
SHA-256 checksum
How to use checksums
2a072023dfd034f914266e34b91d54b415565a12a2a177c23e720714c1ebf8a1
BLAKE2b-256 checksum
How to use checksums
d107761c1c03da215f1db06f63af56a10f700e7158b1676669324b236cbef935
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / rpgp_py-0.20.0-cp310-abi3-win_amd64.whl

Download URL rpgp_py-0.20.0-cp310-abi3-win_amd64.whl
Size 3.1 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
278d002db1a91a709f5fdc423e06adba0852e1ed2ad363ecb1b70decc9e80516
BLAKE2b-256 checksum
How to use checksums
bf3f868a9f090ecec6ec26d52522aab0f33e25184ec48a4ce260cf834fda48be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / rpgp_py-0.20.0-cp310-abi3-win32.whl

Download URL rpgp_py-0.20.0-cp310-abi3-win32.whl
Size 2.8 MB
Tags CPython 3.10 Windows x86-32 abi3
SHA-256 checksum
How to use checksums
f4802be4265103aa3ac5ac7882ac7388fe4b3bd3ad2257500f6ab5a8f2879637
BLAKE2b-256 checksum
How to use checksums
bf7cad594a2810bb7093958d0ca9a4693db773c775f833510435e3a49ab33274
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / rpgp_py-0.20.0-cp310-abi3-musllinux_1_2_x86_64.whl

Download URL rpgp_py-0.20.0-cp310-abi3-musllinux_1_2_x86_64.whl
Size 3.6 MB
Tags CPython 3.10 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
659475b9ba64cc42596e2bfa953f9cb7fd271486b2e2a957d3a7660baa6712d5
BLAKE2b-256 checksum
How to use checksums
f2027f953e4c2b681c917f1d27aa204042b9552a9eb674d7cefa0233b2302eac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / rpgp_py-0.20.0-cp310-abi3-musllinux_1_2_aarch64.whl

Download URL rpgp_py-0.20.0-cp310-abi3-musllinux_1_2_aarch64.whl
Size 3.5 MB
Tags CPython 3.10 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
95881d16420949c6b893bff60276aa5da0683ae86e4cab98506b54f7b293c8f2
BLAKE2b-256 checksum
How to use checksums
8ca1b122189c65bce7bdd60d1e2861b663c32d583f6c259c1ddd1da56d0aee50
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / rpgp_py-0.20.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL rpgp_py-0.20.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.3 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
499c28ba70b2e2da214e9463369a6d929062e8e7037447b6d45a9d2663f3ba43
BLAKE2b-256 checksum
How to use checksums
e6f9d53041547713dfec33f035d029e15b4127c4d02dcab8fbeb4af8795fd16e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / rpgp_py-0.20.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL rpgp_py-0.20.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 3.3 MB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
fca326cbcbe0102bba1c2628ccaee2d75229fe50195c90bb646d79a55a330b0e
BLAKE2b-256 checksum
How to use checksums
4e5a480757bf4495abd7649c35580aa59ada149c57ae386349ad8eab08d8ad6d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / rpgp_py-0.20.0-cp310-abi3-macosx_11_0_arm64.whl

Download URL rpgp_py-0.20.0-cp310-abi3-macosx_11_0_arm64.whl
Size 3.0 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
63286e891a0910f9d2e407b94cb21b274dcdc5d3f1e60d101b884667ce0a3c70
BLAKE2b-256 checksum
How to use checksums
6cbd45bbe117b7a56e1ab8cd6742becaadffc879f460be6a89d16d0fd9765ecc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / rpgp_py-0.20.0-cp310-abi3-macosx_10_12_x86_64.whl

Download URL rpgp_py-0.20.0-cp310-abi3-macosx_10_12_x86_64.whl
Size 3.1 MB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
618354b938c629661f9a19e290d06dbd41c20ca908cf47058c25aa629c7ccb82
BLAKE2b-256 checksum
How to use checksums
0d10e14898866810360e5394d10997660500e080224a57b8df1a95a9b30d54d7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.20.0 This release

9 release files

0.19.8

9 release files

0.19.7

9 release files

0.19.6

9 release files

0.19.5

9 release files

0.19.4

9 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page