Module sequoia_openpgp::serialize::stream

source ·
Expand description

Streaming packet serialization.

This interface provides a convenient way to create signed and/or encrypted OpenPGP messages (see Section 11.3 of RFC 4880) and is the preferred interface to generate messages using Sequoia. It takes advantage of OpenPGP’s streaming nature to avoid unnecessary buffering.

To use this interface, a sink implementing io::Write is wrapped by Message::new returning a streaming Message. The writer stack is a structure to compose filters that create the desired message structure. There are a number of filters that can be freely combined:

The most common structure is an optionally encrypted, optionally compressed, and optionally signed message. This structure is supported by all OpenPGP implementations, and applications should only create messages of that structure to increase compatibility. See the example below on how to create this structure. This is a sketch of such a message:

[ encryption layer: [ compression layer: [ signature group: [ literal data ]]]]

§Examples

This example demonstrates how to create the simplest possible OpenPGP message (see Section 11.3 of RFC 4880) containing just a literal data packet (see Section 5.9 of RFC 4880):

use std::io::Write;
use sequoia_openpgp as openpgp;
use openpgp::serialize::stream::{Message, LiteralWriter};

let mut sink = vec![];
{
    let message = Message::new(&mut sink);
    let mut message = LiteralWriter::new(message).build()?;
    message.write_all(b"Hello world.")?;
    message.finalize()?;
}
assert_eq!(b"\xcb\x12b\x00\x00\x00\x00\x00Hello world.", sink.as_slice());

This example demonstrates how to create the most common OpenPGP message structure (see Section 11.3 of RFC 4880). The plaintext is first signed, then encrypted, and finally ASCII armored.

use std::io::Write;
use sequoia_openpgp as openpgp;
use openpgp::policy::StandardPolicy;
use openpgp::cert::prelude::*;
use openpgp::serialize::stream::{
    Message, Armorer, Encryptor2, Signer, LiteralWriter,
};

let p = &StandardPolicy::new();

let sender: Cert = // ...
let signing_keypair = sender.keys().secret()
    .with_policy(p, None).supported().alive().revoked(false).for_signing()
    .nth(0).unwrap()
    .key().clone().into_keypair()?;

let recipient: Cert = // ...
// Note: One certificate may contain several suitable encryption keys.
let recipients =
    recipient.keys().with_policy(p, None).supported().alive().revoked(false)
    // Or `for_storage_encryption()`, for data at rest.
    .for_transport_encryption();

let message = Message::new(&mut sink);
let message = Armorer::new(message).build()?;
let message = Encryptor2::for_recipients(message, recipients).build()?;
// Reduce metadata leakage by concealing the message size.
let message = Signer::new(message, signing_keypair)
    // Prevent Surreptitious Forwarding.
    .add_intended_recipient(&recipient)
    .build()?;
let mut message = LiteralWriter::new(message).build()?;
message.write_all(b"Hello world.")?;
message.finalize()?;

Modules§

  • Padding for OpenPGP messages.

Structs§