Packet-related data types.
OpenPGP data structures are packet based. This module defines the corresponding data structures.
Most users of this library will not need to generate these packets
themselves. Instead, the packets are instantiated as a side
effect of parsing a message, or creating a message. The main
current exception are
Signature packets. Working with
Signature packets is, however, simplified by using the
Many OpenPGP packets include a version field. Versioning is used
to make it easier to change the standard. For instance, using
versioning, it is possible to remove a field from a packet without
introducing a new packet type, which would also require changing
the grammar. Versioning also enables a degree of forward
compatibility when a new version of a packet can be safely
ignored. For instance, there are currently two versions of the
Signature packet with completely different layouts: v3 and
v4. An implementation that does not understand the latest
version of the packet can still parse and display a message using
them; it will just be unable to verify that signature.
In Sequoia, packets that have a version field are represented by
enums, and each supported version of the packet has a variant,
and a corresponding
struct. This is the case even when only one
version of the packet is currently defined, as is the case with
OnePassSig packet. The
enums implement forwarders for
common operations. As such, users of this library can often
ignore that there are multiple versions of a given packet.
Sequoia gracefully handles unsupported packets by storing them as
Unknown packets. There are several types of unknown packets:
Packets that are known, but explicitly not supported.
The two major examples are the
SEDpacket type and v3
Signaturepackets, which have both been considered insecure for well over a decade.
Note: future versions of Sequoia may add limited support for these packets to enable parsing archived messages.
Packets that are known about, but that use unsupported options, e.g., a
Compressed Datapacket using an unknown or unsupported algorithm.
Packets that are unknown, e.g., future or private extensions.
When Sequoia parses a message containing these packets, it
doesn’t fail. Instead, Sequoia stores them in the
data structure. This allows applications to not only continue to
process such messages (albeit with degraded performance), but to
losslessly reserialize the messages, should that be required.
Packets can be divided into two categories: containers and
non-containers. A container is a packet that contains other
OpenPGP packets. For instance, by definition, a
Compressed Data packet contains an OpenPGP Message. It is possible to
iterate over a container’s descendants using the
Container::descendants method. (Note:
Conceptually, packets have zero or more headers and an optional
body. The headers are small, and have a known upper bound. The
version field is, for instance, 4 bytes, and although
SubpacketArea areas are variable in size,
they are limited to 64 KB. In contrast the body, can be unbounded
To limit memory use, and enable streaming processing (i.e.,
ensuring that processing a message can be done using a fixed size
buffer), Sequoia does not require that a packet’s body be present
in memory. For instance, the body of a literal data packet may be
streamed. And, at the end, a
Literal packet is still
returned. This allows the caller to examine the message
structure, and the message headers in in toto even when
streaming. It is even possible to compare two streamed version of
a packet: Sequoia stores a hash of the body. See the
data structure for more details.
There are several reasonable ways to define equality for
Packets. Unfortunately, none of them are appropriate in all
situations. This makes choosing a general-purpose equality
Eq as the equivalence of two
serialized forms. If an application naively deduplicates
signatures, then an attacker can potentially perform a denial of
service attack by causing the application to process many
Signatures by varying the content of one
Signature’s unhashed area. This attack
can be prevented by only comparing data that is protected by the
signature. But this means that naively deduplicating
packets will return in “a random” variant being used. So, again,
an attacker could create variants of a cryptographically-valid
Signature to get the implementation to incorrectly drop a useful
These issues are also relevant when comparing
Keys: should the
secret key material be compared? Usually we want to merge the
secret key material. But, again, if done naively, the incorrect
secret key material may be retained or dropped completely.
Instead of trying to come up with a definition of equality that is
reasonable for all situations, we use a conservative definition:
two packets are considered equal if the serialized forms of their
packet bodies as defined by RFC 4880 are equal. That is, two
packets are considered equal if and only if their serialized forms
are equal modulo the OpenPGP framing (
CTB and length style,
potential partial body encoding). This definition will avoid
unintentionally dropping information when naively deduplicating
packets, but it will result in potential redundancies.
For some packets, we provide additional variants of equality. For
Key::public_cmp compares just the public parts of
AEAD encrypted data packets.
OpenPGP packet headers.
One-pass signature packets.
PublicKey-Encrypted Session Key packets.
Brings the most relevant types and traits into scope for working with packets.
Symmetrically Encrypted Integrity Protected data packets.
Symmetric-Key Encrypted Session Key Packets.
User Attribute packets and subpackets.
Fields used by multiple packet types.
Holds a compressed data packet.
Holds packet bodies.
An iterator over the contents of a packet in depth-first order.
Holds a literal packet.
Holds an MDC packet.
Holds a Marker packet.
Holds a Trust packet.
Holds an unknown packet.
Holds a UserID packet.
Holds an AEAD encrypted data packet.
A packet’s body holds either unprocessed bytes, processed bytes, or packets.
Holds a public key, public subkey, private key or private subkey packet.
Holds a one-pass signature packet.
Holds an asymmetrically encrypted session key.
Enumeration of packet types.
Holds a SEIP packet.
Holds a symmetrically encrypted session key.
Holds a signature packet.
Convenient downcasting from Packets to Packet Bodies.