pub struct Context<'a>(/* private fields */);Expand description
The canonical encoding of a context, as bytes.
A context is the same value whether an AEAD authenticates it as
associated data or a PRF derives under it: x.into_aad() and
x.into_prf_context() both produce this type and both hold the same
bytes. Those bytes come from one place, the encoding of the context’s
ContextPiece tree, so no consumer can be given a different encoding
of the same context on one side than on the other.
The storage is copy-on-write. A context built from a borrowed encoded
slice (from_encoded) borrows it; anything the
encoder produces is owned.
§Raw bytes
Two methods take raw bytes rather than a typed value, and both mean something specific:
from_encodedtakes bytes this encoder already produced, for a context that was stored or crossed a language boundary and is now being handed back. Passing it something else, say the raw bytes of a string, gives a context that is not the encoding of that string:Context::from_encoded(b"7")and"7".into_aad()are different contexts.paeframes a list of byte pieces exactly as a composite context is framed. A crate that defines its own domain-separated context shapes builds them with it, leading with a domain label of its own.
Context deliberately does not implement MaybeEmpty. An encoded
context can only be judged on its bytes, and framing makes the encoding
of an empty value non-empty, so NonEmpty<Context> would certify exactly
the degenerate value it exists to exclude. Its parts view, the
ContextPiece::Encoded leaf, counts as empty for the same reason, so
routing bytes through into_context is not
a way around the rule. Prove non-emptiness on the value before it is
encoded: NonEmpty<T> where T: IntoContext.
Implementations§
Source§impl<'a> Context<'a>
impl<'a> Context<'a>
Sourcepub fn empty() -> Self
pub fn empty() -> Self
The empty context: no bytes at all. The same as ().into_context()
encoded, and the value Default gives.
Sourcepub fn from_encoded(bytes: impl Into<Cow<'a, [u8]>>) -> Self
pub fn from_encoded(bytes: impl Into<Cow<'a, [u8]>>) -> Self
A context from bytes this encoder already produced.
Use it to hand back a context that was stored, logged, or received
across an FFI boundary as bytes. It does not encode anything: the
bytes are the context, verbatim, and when the result is used as a
part of a larger context it is written as a
ContextPiece::Encoded leaf, untagged. Do not use it to turn a
value into a context; implement or call IntoContext for that.
use vitaminc_context::{Context, IntoContext};
let stored = ("users", 7u64).into_context().encode();
let restored = Context::from_encoded(stored.as_bytes());
assert_eq!(restored, stored);
// Re-encoding an encoded context leaves it unchanged.
assert_eq!(restored.clone().into_context().encode(), stored);Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Whether there are no bytes at all. Only the empty context and the
encoding of () are empty; every framed context has at least a count
word.
Sourcepub fn into_owned(self) -> Context<'static>
pub fn into_owned(self) -> Context<'static>
Copies the bytes if they are borrowed, so the context can outlive its source.
Sourcepub fn pae(pieces: &[&[u8]]) -> Context<'static>
pub fn pae(pieces: &[&[u8]]) -> Context<'static>
Pre-Authentication Encoding of a list of byte pieces, from the PASETO
specification: LE64(count) || (LE64(len(piece)) || piece)*.
Structurally distinct inputs always encode to distinct byte strings.
This is the framing every composite context in this crate uses, and
the building block a crate uses to define a domain-separated context
shape of its own. Lead such a shape with a domain label that is
yours; the labels this crate reserves all begin vitaminc/context/.
Sourcepub fn refine<'b, C>(&self, component: C) -> Context<'static>where
C: IntoContext<'b>,
pub fn refine<'b, C>(&self, component: C) -> Context<'static>where
C: IntoContext<'b>,
Adds a component under this context, with a domain tag so the result cannot collide with any context this crate derives on its own.
The encoding is PAE(domain, self, component). Without the leading
domain, a caller could build the reserved option-some label as a
context and refine it by x to reach the same bytes
for_option_some assigns under x.
Sourcepub fn for_map_entry(&self, key: &str) -> Context<'static>
pub fn for_map_entry(&self, key: &str) -> Context<'static>
The context a map entry’s value is sealed or derived under, binding
the entry key to this context.
Map keys travel in the clear inside a ciphertext container, so without this binding an attacker holding a stored ciphertext could swap or rename keys undetected and silently reassign values to different fields. Every map cipher and map PRF derives each entry’s context through this method, on both the writing and the reading side.
The encoding is PAE(domain, self, key). The leading domain keeps
the result apart from a caller binding the tuple (context, key) as
a context of its own, which is a two-piece list of typed leaves and
so can never equal a three-piece labelled frame.
Sourcepub fn for_leaf(&self, version: u8) -> Context<'static>
pub fn for_leaf(&self, version: u8) -> Context<'static>
The context every sealed leaf is finally authenticated under, binding
the wire-format version byte that prefixes the stored leaf.
This is the outermost derivation. A cipher applies it at the AEAD
seal and open boundary, after every structural derivation
(for_map_entry,
for_sequence_element, the markers) has
produced the caller-visible context. Binding the version under the
tag is what makes it more than a parse hint: a stored leaf relabelled
with a different version byte fails verification instead of selecting
a different, perhaps weaker, set of parsing rules.
The domain label carries no /v1 suffix on purpose. The version is a
parameter here, not part of the label.
Sourcepub fn for_sequence_element(&self) -> Context<'static>
pub fn for_sequence_element(&self) -> Context<'static>
The context a sequence element is sealed or derived under.
Without this derivation a sequence element would share the caller’s bare context with a top-level single value, byte for byte, so an attacker holding a stored ciphertext could rewrap a single leaf as a one-element sequence and a self-describing decrypt path would verify it. Sealing elements under a labelled derivation means a leaf verifies only in the position it was sealed for.
The element index is deliberately not bound. Records are retrieved in a different order than they were inserted, so element order is a caller obligation, not an authenticated fact.
Sourcepub fn for_empty_sequence(&self) -> Context<'static>
pub fn for_empty_sequence(&self) -> Context<'static>
Marker context for an empty sequence. See
for_none for the marker rule.
Sourcepub fn for_empty_map(&self) -> Context<'static>
pub fn for_empty_map(&self) -> Context<'static>
Marker context for an empty map. See for_none
for the marker rule.
Sourcepub fn for_none(&self) -> Context<'static>
pub fn for_none(&self) -> Context<'static>
Marker context for an authenticated absent value, Option::None.
A marker is a sealed empty plaintext whose tag is the only thing
authenticating a structural fact. Each marker kind is derived under
its own labelled context, PAE(domain, self, kind), so a single leaf
sealed under the bare context can never be re-tagged as an absence
marker (silent authenticated deletion), an absence marker can never
validate as an encrypted empty byte string, and no marker can be
replayed as a different structural claim.
Sourcepub fn for_option_some(&self) -> Context<'static>
pub fn for_option_some(&self) -> Context<'static>
The context an optional value’s Some is derived under.
This is the value side of Option, distinct from the context side.
Some(x) as a context is the one-element list PAE([x]), untagged,
so that a runtime list of one part is the same context as the static
Some. A Some value being derived under a context c uses
PAE(domain, c) instead, keeping the derivation of an optional value
apart from the derivation of its inner value under the same c.
Trait Implementations§
impl<'a> Eq for Context<'a>
Source§impl<'a> IntoContext<'a> for Context<'a>
An encoded context is a context. As a part of a larger context it is
the Encoded leaf, written verbatim and
untagged, so re-encoding a context leaves its bytes unchanged.
impl<'a> IntoContext<'a> for Context<'a>
An encoded context is a context. As a part of a larger context it is
the Encoded leaf, written verbatim and
untagged, so re-encoding a context leaves its bytes unchanged.
Source§fn into_context(self) -> ContextPiece<'a>
fn into_context(self) -> ContextPiece<'a>
self as a tree of parts.