[−][src]Module sequoia_openpgp::parse
OpenPGP packet parser.
An OpenPGP message is a sequence of packets. Some of the packets contain other packets. These containers include encrypted packets (the SED and SEIP packets), and compressed packets. This structure results in a tree, which is laid out in depth-first order.
There are two major concerns that inform the design of the parsing API.
First, when processing a container, it is possible to either
recurse into the container, and process its children, or treat the
contents of the container as an opaque byte stream, and process
the packet following the container. The low-level
PacketParser
and mid-level PacketPileParser
abstractions
allow the caller to choose the behavior by either calling the
recurse()
method or the next()
method, as appropriate.
OpenPGP doesn't impose any restrictions on the amount of nesting.
So, to prevent a denial of service attack, the parsers doesn't
recurse more than MAX_RECURSION_DEPTH
times, by default.
Second, packets can contain an effectively unbounded amount of
data. To avoid errors due to memory exhaustion, the
PacketParser
and PacketPileParser
abstractions support
parsing packets in a streaming manner, i.e., never buffering more
than O(1) bytes of data. To do this, the parsers initially only
parse a packet's header (which is rarely more than a few kilobytes
of data), and return control to the caller. After inspecting that
data, the caller can decide how to handle the packet's contents.
If the content is deemed interesting, it can be streamed or
buffered. Otherwise, it can be dropped. Streaming is possible
not only for literal data packets, but also containers (other
packets also support the interface, but just return EOF). For
instance, encryption can be stripped by saving the decrypted
content of an encryption packet, which is just an OpenPGP message.
We explicitly chose to not use a callback-based API, but something
that is closer to Rust's iterator API. Unfortunately, because a
PacketParser
needs mutable access to the input stream (so that
the content can be streamed), only a single PacketParser
item
can be live at a time (without a fair amount of unsafe nastiness).
This is incompatible with Rust's iterator concept, which allows
any number of items to be live at any time. For instance:
let mut v = vec![1, 2, 3, 4]; let mut iter = v.iter_mut(); let x = iter.next().unwrap(); let y = iter.next().unwrap(); *x += 10; // This does not cause an error! *y += 10;
This crate provide three abstractions for parsing OpenPGP messages:
-
The
PacketParser
abstraction produces one packet at a time. What is done with those packets is completely up to the caller. -
The
PacketPileParser
abstraction builds on thePacketParser
abstraction and provides a similar interface. However, after each iteration, thePacketPileParser
adds the packet to aPacketPile
, which is returned once the packets are completely processed.This interface should only be used if the caller actually wants a
PacketPile
; if the OpenPGP message is parsed in place, then using aPacketParser
is better. -
The
PacketPile::from_file
(and related methods) is the most convenient, but least flexible way to parse a sequence of OpenPGP packets. Whereas aPacketPileParser
allows the caller to determine how to handle individual packets, thePacketPile::from_file
parses the whole message at once and returns aPacketPile
.This interface should only be used if the caller is certain that the parsed message will fit in memory.
In all cases, the default behavior can be configured using a
PacketParserBuilder
.
Modules
map | Packet maps. |
stream | Streaming decryption and verification. |
Structs
PacketParser | A low-level OpenPGP message parser. |
PacketParserBuilder | A builder for configuring a |
PacketParserEOF | Information about the stream of packets parsed by the
|
PacketPileParser | A |
Enums
Dearmor | How to decode the input. |
PacketParserResult | The return type of |
Traits
Parse | Parsing of packets and related structures. |