Open-source project
rpgp/rpgp avatar
rpgp/rpgp

rPGP gives you OpenPGP building blocks, and no safety net

OpenPGP implemented in pure Rust, permissively licensed

1,089 stars103 forksRustApache-2.0

At a glance

What is it?
rPGP is an OpenPGP implementation in pure Rust that covers RFC 9580 alongside the older v4 formats, v6 keys and AEAD, and it is deliberately a low-level library rather than a tool. The readme states plainly that the APIs do not claim to be secure or to keep you inside the specification, which is the most important sentence in the project.
Who is it for?
rPGP is worth adopting if you are writing an application that has to speak OpenPGP and you want to do it in Rust without shelling out to GnuPG, because the format coverage is broad and the ecosystem around it, from Delta Chat to the RPM library, shows it is exercised on real workloads.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 17 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

OpenPGP as specified in RFC 9580, in Rust

rPGP is a pure Rust implementation of OpenPGP as specified in RFC 9580, and the project describes it as permissively licensed. The crate is published on crates.io as pgp, the API documentation is on docs.rs, the minimum supported Rust version is 1.88, and the licence is MIT OR Apache-2.0 with both licence files in the repository.

The format coverage is the headline. It supports the commonly used v4 formats, as well as the latest v6 key formats and AEAD encryption mechanisms, and it also supports all the formats specified in the historical RFCs, RFC 4880 and RFC 6637, including v3 keys and signatures.

That last point is the one that matters for adoption. An OpenPGP implementation that only handles the current specification is unusable against the corpus of keys and messages that exist in the wild, most of which predate it. rPGP reads the old formats as well as the new ones, which is the difference between a library you can point at real data and one you can only point at your own.

The repository is organised for a security sensitive library. There is a fuzz directory and a proptest-regressions directory for property based testing, a benches directory, a tests directory, and a deny.toml for cargo-deny, which is how a Rust project checks its dependency licences. The changelog is generated with cliff.toml, the git-cliff tool, and there is a SECURITY.md, a CONTRIBUTING.md and a Makefile.toml for task running.

The audience is application developers who need OpenPGP as a library rather than a command line tool, and who work in Rust.

The low-level API, and the sentence that warns you about it

The readme has a section titled rPGP is a library for application developers and another titled rPGP is a low-level OpenPGP library, and the second one carries the most important text in the project.

The claim is that rPGP offers abstractions for handling the formats and mechanisms specified in RFC 9580, but it offers them as relatively low-level building blocks and does not attempt to ensure that users can not apply them unsafely. The restatement in the blockquote is blunt: rPGP allows following almost all parts of the OpenPGP specification, but the APIs are low level building blocks and do not claim that using them is, in the readme's phrasing, secure or following the OpenPGP specification. Using the building blocks correctly and safely requires a solid understanding of OpenPGP and at least a basic understanding of cryptography.

That is a deliberate choice, not a warning about bugs. A low-level library that refuses to let you construct an insecure message is not a low-level library any more. The trade is that the correctness burden moves to the application, and the project says so before you write a line of code.

For orientation, the readme points at the text OpenPGP for application developers at openpgp.dev, and it explains that OpenPGP is a layered technology, starting with the wire format, the packet framing, the packet content and the ASCII armor, and it keeps that layering in the docs directory with an Overview of OpenPGP formats and mechanisms document.

So the expectation for a user is that you read the format overview first, then the implementation status, then the FAQ, and only then the API.

The feature flags, including one you should leave switched off

The Cargo features are listed in the readme, and they are a good map of the corners of the specification.

bzip2 enables bzip2 support for compressed messages, asm enables assembly based optimisations, and wasm allows building for wasm, which matters for anything running in a browser or a sandbox. large-rsa raises the RSA key size limit from 8192 to 16384 bit. pqc enables the implementation of post quantum cryptography as specified in RFC 9980, and the readme notes that this feature was previously called draft-pqc. And draft-wussler-openpgp-forwarding enables support for the formats and functionality from that draft.

The one to read carefully is malformed-artifact-compat. The description says it makes the library lenient towards some types of malformed artifacts, and it names three: erroneously formed ECDH PKESK, invalidly short first partial body segments, and embedded signatures that do not round-trip. Those signatures are kept verbatim as opaque subpackets so that the enclosing certificate remains importable, but the affected subkey binding will not verify. The readme then says that most users will NOT need this feature and that it should be disabled by default.

That is a security feature shaped as a convenience. It is the difference between your application refusing a broken certificate and accepting it with a subkey that silently will not verify. Keeping it off by default is the right call, and the readme is to be thanked for saying so plainly rather than burying it.

The dependency list in the manifest shows the rest of the shape: nom 8 for the parsing, snafu for the error type, the standard RustCrypto crates for the primitives, curve25519-dalek and ed25519-dalek for the modern curves, argon2 and aead for the AEAD work, and flate2 with the zlib-rs backend for compression.

Two examples: verify an inline signature, make a detached one

The usage section gives two runnable examples, and between them they show the shape of the API.

The first loads a public key and verifies an inline signed message:

rust
use pgp::composed::{Deserializable, Message, SignedPublicKey};

fn main() -> pgp::errors::Result<()> {
    let (public_key, _headers_public) = SignedPublicKey::from_armor_file("key.asc")?;

    let (mut msg, _headers_msg) = Message::from_armor_file("msg.asc")?;
    let payload = msg.as_data_string()?;
    if msg.verify(&public_key).is_ok() { // Verify using the primary (NOTE: This is not always the right key!)
        println!("Signed message: {:?}", payload);
    }

    Ok(())
}

The second creates a detached signature over a byte slice and verifies it:

rust
let (private_key, _headers) = SignedSecretKey::from_armor_file("key.sec.asc")?;
let sig = DetachedSignature::sign_binary_data(
   rand::thread_rng(),
   &private_key.primary_key, // Sign with the primary (NOTE: This is not always the right key!)
   &Password::empty(),
   HashAlgorithm::Sha256,
   DATA,
)?;

Two details deserve attention. The first is the shape of the API: everything returns a Result, the error type is pgp::errors::Result, and the reading functions come from the composed::Deserializable trait, which is how the library teaches you to parse armored files. The second is the parenthetical note that appears three times in the two examples, that using the primary key is not always the right key.

That note is the low-level API speaking. A real key has a primary key and subkeys, and the right one to verify with depends on which key actually made the signature and which one was certified to do so. The library will let you pick the wrong one, and it tells you so in the example rather than in a separate warning document.

The list of users is the real argument for it

The readme has a section titled Notable Users and Libraries built using rPGP, and it is the strongest evidence in the project that a low-level OpenPGP library in Rust is usable in production.

Delta Chat appears first, a cross-platform messaging app that works over e-mail, which is the hardest case: an app whose entire transport is e-mail and whose encryption is OpenPGP. GpgFrontend is a cross-platform OpenPGP desktop app with an optional rPGP backend, which is the case of a project that had an existing implementation and chose rPGP as an alternative backend. The debian-packaging crate is a library for dealing with Debian packages, and rpm is a pure Rust library for parsing and creating RPM files, which matters because package signing is one of the places where a signature implementation is used at scale.

The tooling side is well represented. himalaya is a CLI to manage e-mail and includes a pgp-lib component. oct-git is a Git signing and verification backend with a focus on OpenPGP cards, and prs-lib is a CLI password manager inspired by pass with an optional rPGP backend including OpenPGP card support. rsop and rsop-oct are SOP CLI tools, one of them for OpenPGP card devices, both based on rPGP and rpgpie, and rpgpie is an experimental OpenPGP semantics library. signstar is a signing enclave framework for HSM backends, which is a sign that the low-level API is usable as a building block inside a hardware security module. And voa-openpgp is an OpenPGP implementation for VOA.

The list spans secure mail, desktop tooling, package management, a password manager, hardware tokens and a specification implementation. That is a much better argument than any performance claim would be, and the readme asks projects that are not on the list to send a pull request.

Where the status documents matter more than the readme

There is a Current Status section, and its last updated line says September 2025. Below it are three links, and each one is the document a careful adopter should read before writing code.

IMPL_STATUS.md is the implementation status, the detail on which PGP features are implemented, and the readme points to it for more details on the implemented PGP features. SECURITY_STATUS.md is the security status, which is the one to read if you are about to put rPGP in a path that protects something. And PLATFORMS.md is the supported platforms list, which matters more than it sounds because this is a cryptography library and a platform you cannot test is a platform you should not ship on.

The FAQ lives in docs/FAQ.md, and the readme explicitly welcomes questions in the issue tracker.

There is a tension in the structure that is worth naming. The project ships an extensive list of users, a fuzzing directory, property based test regressions, a cargo-deny configuration and a SECURITY.md, and yet the status page was last updated in September 2025 while the code is on version 0.21.0. For a library where the API is deliberately low-level, the status documents are the contract, and a status document that is a year behind the release cadence is a gap a team should account for in its own review process rather than assume away.

The examples directory is small and telling: decrypt_seipdv1.rs and decrypt_seipdv2.rs for the two SEIPDv1 and SEIPDv2 variants, encrypt_decrypt.rs, generate_key.rs, and a README. Five examples for a low-level library is right. The point of the library is not that you copy an example, it is that the examples show the call sequence and the rest is yours to reason about.

Editorial conclusion

rPGP is worth adopting if you are writing an application that has to speak OpenPGP and you want to do it in Rust without shelling out to GnuPG, because the format coverage is broad and the ecosystem around it, from Delta Chat to the RPM library, shows it is exercised on real workloads. It is the wrong choice if you want a safe by default API, since the project states that it does not attempt to prevent unsafe use, and it is the wrong choice if you need an audited implementation. Before you depend on it, read docs/IMPL_STATUS.md and docs/SECURITY_STATUS.md, check the platform support list, and note that the current release is v0.21.0 from 2026-10-03 with the repository pushed to on 2026-10-06.

Frequently asked questions

What is rPGP and which OpenPGP formats does it support?

It is a pure Rust implementation of OpenPGP as specified in RFC 9580. It supports the commonly used v4 formats, the latest v6 key formats and AEAD encryption mechanisms, and also the historical formats from RFC 4880 and RFC 6637, including v3 keys and signatures.

Is rPGP safe to use directly?

The readme says rPGP offers relatively low-level building blocks and does not attempt to ensure that users can not apply them unsafely, and that using them correctly and safely requires a solid understanding of OpenPGP and at least a basic understanding of cryptography. It points at the OpenPGP for application developers text for orientation.

How do I add rPGP to a Rust project?

With cargo add pgp, which pulls the pgp crate. The readme's examples use the composed module, with Deserializable for parsing armored key and message files, Message for the payload, SignedPublicKey and SignedSecretKey for keys, and DetachedSignature for detached signatures.

What is the malformed-artifact-compat Cargo feature in rPGP?

It makes the library lenient towards some malformed artifacts, namely erroneously formed ECDH PKESK, invalidly short first partial body segments, and embedded signatures that do not round-trip, which are kept verbatim as opaque subpackets so the enclosing certificate stays importable although the affected subkey binding will not verify. The readme says most users do not need it and that it should be disabled by default.

Which projects use rPGP?

The readme lists Delta Chat, GpgFrontend, the debian-packaging crate, the rpm library, himalaya with its pgp-lib component, oct-git, prs-lib, rpgpie, rsop, rsop-oct, signstar for HSM backends and voa-openpgp. The current release is v0.21.0 from 2026-10-03.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. rpgp/rpgp on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rpgp-rpgp.svg)](https://hysenlabs.com/projects/rpgp-rpgp)

Was this useful?