Struct sequoia_openpgp::serialize::stream::Encryptor2

source ·
pub struct Encryptor2<'a, 'b>
where 'b: 'a,
{ /* private fields */ }
Expand description

Encrypts a message.

The stream will be encrypted using a generated session key, which will be encrypted using the given passwords, and for all given recipients.

An Recipient is an encryption-capable (sub)key. Note that a certificate may have more than one encryption-capable subkey, and even the primary key may be encryption-capable.

To encrypt for more than one certificate, iterate over the certificates and select encryption-capable keys, making sure that at least one key is selected from each certificate.

§Examples

This demonstrates encrypting for multiple certificates.

use openpgp::serialize::stream::{
    Message, Encryptor2, LiteralWriter,
};
use openpgp::policy::StandardPolicy;
let p = &StandardPolicy::new();

let recipient_certs = vec![cert_0, cert_1];
let mut recipients = Vec::new();
for cert in recipient_certs.iter() {
    // Make sure we add at least one subkey from every
    // certificate.
    let mut found_one = false;
    for key in cert.keys().with_policy(p, None)
        .supported().alive().revoked(false).for_transport_encryption()
    {
        recipients.push(key);
        found_one = true;
    }

    if ! found_one {
        return Err(anyhow::anyhow!("No suitable encryption subkey for {}",
                                   cert));
    }
}

let message = Message::new(&mut sink);
let message = Encryptor2::for_recipients(message, recipients).build()?;
let mut w = LiteralWriter::new(message).build()?;
w.write_all(b"Hello world.")?;
w.finalize()?;

Implementations§

source§

impl<'a, 'b> Encryptor2<'a, 'b>

source

pub fn for_recipients<R>(inner: Message<'a>, recipients: R) -> Self
where R: IntoIterator, R::Item: Into<Recipient<'b>>,

Creates a new encryptor for the given recipients.

To add more recipients, use Encryptor2::add_recipients. To add passwords, use Encryptor2::add_passwords. To change the symmetric encryption algorithm, use Encryptor2::symmetric_algo.

§Examples
use std::io::Write;
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::serialize::stream::{
    Message, Encryptor2, LiteralWriter,
};
use openpgp::policy::StandardPolicy;
let p = &StandardPolicy::new();

let cert = Cert::from_bytes(
    "-----BEGIN PGP PUBLIC KEY BLOCK-----

     xjMEWlNvABYJKwYBBAHaRw8BAQdA+EC2pvebpEbzPA9YplVgVXzkIG5eK+7wEAez
     ...
     -----END PGP PUBLIC KEY BLOCK-----"
)?;

let recipients =
    cert.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 = Encryptor2::for_recipients(message, recipients).build()?;
let mut w = LiteralWriter::new(message).build()?;
w.write_all(b"Hello world.")?;
w.finalize()?;
source

pub fn with_passwords<P>(inner: Message<'a>, passwords: P) -> Self
where P: IntoIterator, P::Item: Into<Password>,

Creates a new encryptor for the given passwords.

To add more passwords, use Encryptor2::add_passwords. To add recipients, use Encryptor2::add_recipients. To change the symmetric encryption algorithm, use Encryptor2::symmetric_algo.

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

let message = Message::new(&mut sink);
let message = Encryptor2::with_passwords(
    message, Some("совершенно секретно")).build()?;
let mut w = LiteralWriter::new(message).build()?;
w.write_all(b"Hello world.")?;
w.finalize()?;
source

pub fn with_session_key( inner: Message<'a>, sym_algo: SymmetricAlgorithm, session_key: SessionKey ) -> Result<Self>

Creates a new encryptor for the given algorithm and session key.

Usually, the encryptor creates a session key and decrypts it for the given recipients and passwords. Using this function, the session key can be supplied instead. There are two main use cases for this:

  • Replying to an encrypted message usually requires the encryption (sub)keys for every recipient. If even one key is not available, it is not possible to encrypt the new session key. Rather than falling back to replying unencrypted, one can reuse the original message’s session key that was encrypted for every recipient and reuse the original PKESKs.

  • Using the encryptor if the session key is transmitted or derived using a scheme not supported by Sequoia.

To add more passwords, use Encryptor2::add_passwords. To add recipients, use Encryptor2::add_recipients.

§Examples

This example demonstrates how to fall back to the original message’s session key in order to encrypt a reply.

// Generate two keys.
let (alice, _) = CertBuilder::general_purpose(
        None, Some("Alice Lovelace <alice@example.org>")).generate()?;
let (bob, _) = CertBuilder::general_purpose(
        None, Some("Bob Babbage <bob@example.org>")).generate()?;

// Encrypt a message for both keys.
let recipients = vec![&alice, &bob].into_iter().flat_map(|cert| {
    cert.keys().with_policy(p, None).supported().alive().revoked(false)
        .for_transport_encryption()
});

let mut original = vec![];
let message = Message::new(&mut original);
let message = Encryptor2::for_recipients(message, recipients).build()?;
let mut w = LiteralWriter::new(message).build()?;
w.write_all(b"Original message")?;
w.finalize()?;

// Decrypt original message using Alice's key.
let mut decryptor = DecryptorBuilder::from_bytes(&original)?
    .with_policy(p, None, Helper::new(alice))?;
io::copy(&mut decryptor, &mut io::sink())?;
let (algo, sk, pkesks) = decryptor.into_helper().recycling_bin.unwrap();

// Compose the reply using the same session key.
let mut reply = vec![];
let mut message = Message::new(&mut reply);
for p in pkesks { // Emit the stashed PKESK packets.
    Packet::from(p).serialize(&mut message)?;
}
let message = Encryptor2::with_session_key(message, algo, sk)?.build()?;
let mut w = LiteralWriter::new(message).build()?;
w.write_all(b"Encrypted reply")?;
w.finalize()?;

// Check that Bob can decrypt it.
let mut decryptor = DecryptorBuilder::from_bytes(&reply)?
    .with_policy(p, None, Helper::new(bob))?;
io::copy(&mut decryptor, &mut io::sink())?;

/// Decrypts the message preserving algo, session key, and PKESKs.
struct Helper {
    key: Cert,
    recycling_bin: Option<(SymmetricAlgorithm, SessionKey, Vec<PKESK>)>,
}

impl DecryptionHelper for Helper {
    fn decrypt<D>(&mut self, pkesks: &[PKESK], _skesks: &[SKESK],
                  sym_algo: Option<SymmetricAlgorithm>, mut decrypt: D)
                  -> Result<Option<Fingerprint>>
        where D: FnMut(SymmetricAlgorithm, &SessionKey) -> bool
    {
        let p = &StandardPolicy::new();
        let mut encryption_context = None;

        for pkesk in pkesks { // Try each PKESK until we succeed.
            for ka in self.key.keys().with_policy(p, None)
                .supported().unencrypted_secret()
                .key_handle(pkesk.recipient())
                .for_storage_encryption().for_transport_encryption()
            {
                let mut pair = ka.key().clone().into_keypair().unwrap();
                if pkesk.decrypt(&mut pair, sym_algo)
                    .map(|(algo, session_key)| {
                        let success = decrypt(algo, &session_key);
                        if success {
                            // Copy algor, session key, and PKESKs.
                            encryption_context =
                                Some((algo, session_key.clone(),
                                      pkesks.iter().cloned().collect()));
                        }
                        success
                    })
                    .unwrap_or(false)
                {
                    break; // Decryption successful.
                }
            }
        }

        self.recycling_bin = encryption_context; // Store for the reply.
        Ok(Some(self.key.fingerprint()))
    }
}

impl VerificationHelper for Helper {
    // ...
}
source

pub fn add_recipients<R>(self, recipients: R) -> Self
where R: IntoIterator, R::Item: Into<Recipient<'b>>,

Adds recipients.

The resulting message can be encrypted by any recipient and with any password.

§Examples
use std::io::Write;
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::serialize::stream::{
    Message, Encryptor2, LiteralWriter,
};
use openpgp::policy::StandardPolicy;
let p = &StandardPolicy::new();

let cert = Cert::from_bytes(
    "-----BEGIN PGP PUBLIC KEY BLOCK-----

     mQENBFpxtsABCADZcBa1Q3ZLZnju18o0+t8LoQuIIeyeUQ0H45y6xUqyrD5HSkVM
     ...
     -----END PGP PUBLIC KEY BLOCK-----"
)?;

let recipients =
    cert.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 =
    Encryptor2::with_passwords(message, Some("совершенно секретно"))
    .add_recipients(recipients)
    .build()?;
let mut message = LiteralWriter::new(message).build()?;
message.write_all(b"Hello world.")?;
message.finalize()?;
source

pub fn add_passwords<P>(self, passwords: P) -> Self
where P: IntoIterator, P::Item: Into<Password>,

Adds passwords to encrypt with.

The resulting message can be encrypted with any password and by any recipient.

§Examples
use std::io::Write;
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::serialize::stream::{
    Message, Encryptor2, LiteralWriter,
};
use openpgp::policy::StandardPolicy;
let p = &StandardPolicy::new();

let cert = Cert::from_bytes(
    "-----BEGIN PGP PUBLIC KEY BLOCK-----

     mQENBFpxtsABCADZcBa1Q3ZLZnju18o0+t8LoQuIIeyeUQ0H45y6xUqyrD5HSkVM
     ...
     -----END PGP PUBLIC KEY BLOCK-----"
)?;

let recipients =
    cert.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 =
    Encryptor2::for_recipients(message, recipients)
        .add_passwords(Some("совершенно секретно"))
        .build()?;
let mut message = LiteralWriter::new(message).build()?;
message.write_all(b"Hello world.")?;
message.finalize()?;
source

pub fn symmetric_algo(self, algo: SymmetricAlgorithm) -> Self

Sets the symmetric algorithm to use.

§Examples
use std::io::Write;
use sequoia_openpgp as openpgp;
use openpgp::types::SymmetricAlgorithm;
use openpgp::serialize::stream::{
    Message, Encryptor2, LiteralWriter,
};

let message = Message::new(&mut sink);
let message =
    Encryptor2::with_passwords(message, Some("совершенно секретно"))
        .symmetric_algo(SymmetricAlgorithm::AES128)
        .build()?;
let mut message = LiteralWriter::new(message).build()?;
message.write_all(b"Hello world.")?;
message.finalize()?;
source

pub fn build(self) -> Result<Message<'a>>

Builds the encryptor, returning the writer stack.

The most useful filters to push to the writer stack next are the Padder or Compressor, and after that the Signer. Finally, literal data must be wrapped using the LiteralWriter.

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

let message = Message::new(&mut sink);
let message =
    Encryptor2::with_passwords(message, Some("совершенно секретно"))
        // Customize the `Encryptor2` here.
        .build()?;

// Optionally add a `Padder` or `Compressor` here.
// Optionally add a `Signer` here.

let mut message = LiteralWriter::new(message).build()?;
message.write_all(b"Hello world.")?;
message.finalize()?;

Trait Implementations§

source§

impl<'a, 'b> Debug for Encryptor2<'a, 'b>
where 'b: 'a,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'a, 'b> Write for Encryptor2<'a, 'b>
where 'b: 'a,

source§

fn write(&mut self, buf: &[u8]) -> Result<usize>

Write a buffer into this writer, returning how many bytes were written. Read more
source§

fn flush(&mut self) -> Result<()>

Flush this output stream, ensuring that all intermediately buffered contents reach their destination. Read more
1.36.0 · source§

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize, Error>

Like write, except that it writes from a slice of buffers. Read more
source§

fn is_write_vectored(&self) -> bool

🔬This is a nightly-only experimental API. (can_vector)
Determines if this Writer has an efficient write_vectored implementation. Read more
1.0.0 · source§

fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>

Attempts to write an entire buffer into this writer. Read more
source§

fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<(), Error>

🔬This is a nightly-only experimental API. (write_all_vectored)
Attempts to write multiple buffers into this writer. Read more
1.0.0 · source§

fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<(), Error>

Writes a formatted string into this writer, returning any error encountered. Read more
1.0.0 · source§

fn by_ref(&mut self) -> &mut Self
where Self: Sized,

Creates a “by reference” adapter for this instance of Write. Read more

Auto Trait Implementations§

§

impl<'a, 'b> Freeze for Encryptor2<'a, 'b>

§

impl<'a, 'b> !RefUnwindSafe for Encryptor2<'a, 'b>

§

impl<'a, 'b> Send for Encryptor2<'a, 'b>

§

impl<'a, 'b> Sync for Encryptor2<'a, 'b>

§

impl<'a, 'b> Unpin for Encryptor2<'a, 'b>

§

impl<'a, 'b> !UnwindSafe for Encryptor2<'a, 'b>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.