Skip to main content

Crate vitaminc_prf

Crate vitaminc_prf 

Source
Expand description

§vitaminc-prf

vitaminc-prf provides a serde-style API for deriving structured, domain-separated pseudorandom values. Inputs cross backend boundaries in Protected containers, maps bind their keys into the derivation context, and backend output is always awaitable so local and remote batched implementations share one interface.

This crate defines only the abstraction: the PrfValue, Prf, and PrfKeyInit traits, context and encoding domains, and the visitor machinery. It contains no cryptography. Concrete backends live in their own crates; the local HMAC-SHA256 backend is vitaminc-hmac, and its documentation carries runnable end-to-end examples.

Key ownership lives in exactly one place. PrfKeyInit constructs a backend from key material taken by value, so the key moves into the backend and is wiped when the backend drops. Every Prf derivation method then borrows the backend (&self): a derivation is a pure function of the key and the input, so nothing is consumed and one instance serves any number of derivations without being cloned.

Every protected leaf carries an explicit PrfEncoding domain. Built-in text, bytes, and fixed-width integers are separated even when their byte representations happen to match. Custom leaf implementations must provide a stable, namespaced encoding identifier, preventing accidental untagged derivation.

§Implementing PrfValue for a struct

Struct implementations describe their fields with a map driver. The final visitor receives resolved child nodes, so each field can produce a different owned output while a deferred backend still executes the structure as one batch.

use vitaminc_prf::{
    BlockVisitor, IntoPrfContext, MapAccess, MapPrf, Prf,
    PrfValue, PrfVisitor, PrfVisitorError, SeqAccess,
};

struct User {
    email: String,
    aliases: Vec<String>,
}

impl PrfValue for User {
    fn prf_visit_with_context<'a, P, V, C>(
        self,
        prf: &P,
        context: C,
        visitor: V,
    ) -> P::Ok<V::Value>
    where
        P: Prf,
        V: PrfVisitor<P::Block, P::Passthrough>,
        C: IntoPrfContext<'a>,
    {
        let context = context.into_prf_context().into_owned();
        prf.prf_map(Some(2))
            .prf_entry("email", self.email, context.clone())
            .prf_entry("aliases", self.aliases, context)
            .end(visitor)
    }
}

struct BlockListVisitor;

impl<P> PrfVisitor<[u8; 32], P> for BlockListVisitor {
    type Value = Vec<[u8; 32]>;

    fn visit_seq(self, seq: SeqAccess<[u8; 32], P>) -> Result<Self::Value, PrfVisitorError> {
        seq.map(|node| node.visit(BlockVisitor)).collect()
    }
}

#[derive(Debug, PartialEq, Eq)]
struct UserTerms {
    email: [u8; 32],
    aliases: Vec<[u8; 32]>,
}

struct UserTermsVisitor;

impl<P> PrfVisitor<[u8; 32], P> for UserTermsVisitor {
    type Value = UserTerms;

    fn visit_map(
        self,
        mut map: MapAccess<[u8; 32], P>,
    ) -> Result<Self::Value, PrfVisitorError> {
        let (email_key, email) = map.next_entry().ok_or(PrfVisitorError::InvalidValue)?;
        let (aliases_key, aliases) = map.next_entry().ok_or(PrfVisitorError::InvalidValue)?;

        if email_key != "email" || aliases_key != "aliases" || map.next_entry().is_some() {
            return Err(PrfVisitorError::InvalidValue);
        }

        Ok(UserTerms {
            email: email.visit(BlockVisitor)?,
            aliases: aliases.visit(BlockListVisitor)?,
        })
    }
}

Executing the derivation requires a backend; with vitaminc-hmac in scope the value above resolves through user.prf_visit_with_context(&prf, "tenant/acme/users/v1", UserTermsVisitor).await.

Structs§

BlockVisitor
Visitor that returns one raw backend block.
Context
The canonical encoding of a context, as bytes.
MapAccess
Pull-style access to resolved string-keyed map children.
Passthrough
Marks an explicitly non-secret value that should pass through unchanged.
PrfEncoding
A stable semantic domain for encoding a protected PRF leaf.
ReadyPrf
An immediately available, awaitable PRF result.
ResolvedVisitor
SeqAccess
Pull-style access to resolved sequence children.

Enums§

ContextPiece
One part of a context, or a list of parts.
PrfBuildError
Errors detected while a structured PRF program is being built.
PrfError
A structured PRF failure.
PrfVisitorError
Errors produced when a visitor is used with the wrong resolved shape.
ResolvedPrf
A fully resolved node supplied to sequence and map visitors.

Traits§

IntoContext
Types that describe themselves as a context.
IntoPrfContext
Types that can be used as the domain-separation context of a PRF derivation.
MapPrf
Map driver. See SeqPrf for the ownership convention.
Prf
Backend for structured pseudorandom derivation.
PrfKeyInit
Construction of a Prf backend from key material.
PrfValue
A type that can describe its structure to a Prf backend.
PrfVisitor
Interprets a resolved PRF result.
SeqPrf
Sequence driver. A driver is owned by one caller for the length of one derivation, so its builder methods consume and return Self; it borrows the backend it was created from.

Type Aliases§

PrfContextDeprecated
The context a PRF derives under. Kept as a name for the transition; it is Context.