Envelope

Struct Envelope 

Source
pub struct Envelope(/* private fields */);
Expand description

A flexible container for structured data with built-in integrity verification.

Gordian Envelope is the primary data structure of this crate. It provides a way to encapsulate and organize data with cryptographic integrity, privacy features, and selective disclosure capabilities.

Key characteristics of envelopes:

  • Immutability: Envelopes are immutable. Operations that appear to “modify” an envelope actually create a new envelope. This immutability is fundamental to maintaining the integrity of the envelope’s digest tree.

  • O(1) Cloning: Envelopes use reference counting (Rc or Arc when the multithreaded feature is enabled) and structure sharing to enable efficient O(1) cloning of an Envelope or recursively, any Envelopes it contains. Cloning an Envelope simply increments the reference count, allowing multiple owners without duplicating the underlying data.

  • Semantic Structure: Envelopes can represent various semantic relationships through subjects, predicates, and objects (similar to RDF triples).

  • Digest Tree: Each envelope maintains a Merkle-like digest tree that ensures the integrity of its contents and enables verification of individual parts.

  • Privacy Features: Envelopes support selective disclosure through elision, encryption, and compression of specific parts, while maintaining the overall integrity of the structure.

  • Deterministic Representation: Envelopes use deterministic CBOR encoding to ensure consistent serialization across platforms.

The Gordian Envelope specification is defined in an IETF Internet Draft, and this implementation closely follows that specification.

§Example

use bc_envelope::prelude::*;

// Create an envelope representing a person
let person = Envelope::new("person")
    .add_assertion("name", "Alice")
    .add_assertion("age", 30)
    .add_assertion("email", "alice@example.com");

// Create a partially redacted version by eliding the email
let redacted = person.elide_removing_target(
    &person.assertion_with_predicate("email").unwrap(),
);

// The digest of both envelopes remains the same
assert_eq!(person.digest(), redacted.digest());

Implementations§

Source§

impl Envelope

Support for adding assertions.

Assertions are predicate-object pairs that make statements about an envelope’s subject. This implementation provides methods for adding various types of assertions to envelopes.

Source

pub fn add_assertion( &self, predicate: impl EnvelopeEncodable, object: impl EnvelopeEncodable, ) -> Self

Returns a new envelope with the given assertion added.

This is the most common way to add an assertion to an envelope. It automatically creates an assertion envelope from the predicate and object, then adds it to the existing envelope. The resulting envelope has the same subject with the new assertion added.

§Examples
let envelope = Envelope::new("Alice")
    .add_assertion("name", "Alice Smith")
    .add_assertion("age", 30);

// The envelope now contains two assertions about Alice
Source

pub fn add_assertion_envelope( &self, assertion_envelope: impl EnvelopeEncodable, ) -> Result<Self>

Returns a new envelope with the given assertion envelope added.

This method allows adding a pre-constructed assertion envelope to an envelope. It’s useful when you have already created an assertion envelope separately or when working with elided, encrypted, or compressed assertion envelopes.

§Parameters
  • assertion_envelope - A valid assertion envelope (or an obscured variant) to add
§Returns

A new envelope with the assertion added, or an error if the provided envelope is not a valid assertion envelope.

§Errors

Returns EnvelopeError::InvalidFormat if the provided envelope is not a valid assertion envelope or an obscured variant of one.

§Examples
// Create a separate assertion envelope
let assertion = Envelope::new_assertion("knows", "Bob");

// Add it to an envelope
let envelope = Envelope::new("Alice")
    .add_assertion_envelope(assertion)
    .unwrap();
Source

pub fn add_assertion_envelopes(&self, assertions: &[Self]) -> Result<Self>

Returns a new envelope with multiple assertion envelopes added.

This is a convenience method for adding multiple assertions at once. Each assertion in the array must be a valid assertion envelope or an obscured variant of one.

§Parameters
  • assertions - An array of valid assertion envelopes to add
§Returns

A new envelope with all the assertions added, or an error if any of the provided envelopes are not valid assertion envelopes.

§Errors

Returns EnvelopeError::InvalidFormat if any of the provided envelopes are not valid assertion envelopes or obscured variants.

§Examples
// Create multiple assertion envelopes
let assertion1 = Envelope::new_assertion("name", "Alice Smith");
let assertion2 = Envelope::new_assertion("age", 30);
let assertion3 = Envelope::new_assertion("city", "Boston");

// Add them all at once to an envelope
let envelope = Envelope::new("person")
    .add_assertion_envelopes(&[assertion1, assertion2, assertion3])
    .unwrap();
Source

pub fn add_optional_assertion_envelope( &self, assertion: Option<Self>, ) -> Result<Self>

Adds an optional assertion envelope to this envelope.

If the optional assertion is present, adds it to the envelope. Otherwise, returns the envelope unchanged. This method is particularly useful when working with functions that may or may not return an assertion.

The method also ensures that duplicate assertions (with the same digest) are not added, making it idempotent.

§Parameters
  • assertion - An optional assertion envelope to add
§Returns

A new envelope with the assertion added if provided, or the original envelope if no assertion was provided or it was a duplicate.

§Errors

Returns EnvelopeError::InvalidFormat if the provided envelope is not a valid assertion envelope or an obscured variant.

§Examples
// A function that may return an assertion based on a condition
fn get_optional_assertion(include: bool) -> Option<Envelope> {
    if include {
        Some(Envelope::new_assertion("verified", true))
    } else {
        None
    }
}

// Add the assertion only if it's available
let envelope = Envelope::new("document")
    .add_optional_assertion_envelope(get_optional_assertion(true))
    .unwrap();
Source

pub fn add_optional_assertion( &self, predicate: impl EnvelopeEncodable, object: Option<impl EnvelopeEncodable>, ) -> Self

Adds an assertion with the given predicate and optional object.

This method is useful when you have a predicate but may or may not have an object value to associate with it. If the object is present, an assertion is created and added to the envelope. Otherwise, the envelope is returned unchanged.

§Parameters
  • predicate - The predicate for the assertion
  • object - An optional object value for the assertion
§Returns

A new envelope with the assertion added if the object was provided, or the original envelope if no object was provided.

§Examples
// A function that may return an optional value
fn get_optional_value(has_value: bool) -> Option<String> {
    if has_value {
        Some("John Smith".to_string())
    } else {
        None
    }
}

// Person with a name if provided
let person = Envelope::new("person")
    .add_optional_assertion("name", get_optional_value(true));

// Person without a name if not provided
let person_without_name = Envelope::new("person")
    .add_optional_assertion("name", get_optional_value(false));
Source

pub fn add_nonempty_string_assertion( &self, predicate: impl EnvelopeEncodable, str: impl AsRef<str>, ) -> Self

Adds an assertion with the given predicate and string value, but only if the string is non-empty.

This is a convenience method that only adds an assertion if the string value is non-empty. It’s particularly useful when working with user input or optional text fields that should only be included if they contain actual content.

§Parameters
  • predicate - The predicate for the assertion
  • str - The string value for the assertion
§Returns

A new envelope with the assertion added if the string is non-empty, or the original envelope if the string is empty.

§Examples
// Create a person with non-empty fields
let person = Envelope::new("person")
    .add_nonempty_string_assertion("name", "Alice Smith")
    .add_nonempty_string_assertion("notes", ""); // This won't be added

// Only the name assertion is added
assert_eq!(person.assertions().len(), 1);
Source

pub fn add_assertions(&self, envelopes: &[Self]) -> Self

Returns a new envelope with the given array of assertions added.

Similar to add_assertion_envelopes but ignores any errors that might occur. This is useful when you’re certain all envelopes in the array are valid assertion envelopes and don’t need to handle errors.

§Parameters
  • envelopes - An array of assertion envelopes to add
§Returns

A new envelope with all the valid assertions added

§Examples
// Create multiple assertion envelopes
let assertion1 = Envelope::new_assertion("name", "Alice Smith");
let assertion2 = Envelope::new_assertion("age", 30);

// Add them all at once to an envelope
let envelope =
    Envelope::new("person").add_assertions(&[assertion1, assertion2]);
Source§

impl Envelope

Support for adding conditional assertions.

These methods add assertions only when certain conditions are met.

Source

pub fn add_assertion_if( &self, condition: bool, predicate: impl EnvelopeEncodable, object: impl EnvelopeEncodable, ) -> Self

Adds an assertion only if the provided condition is true.

This method allows for conditional inclusion of assertions based on a boolean condition. It’s a convenient way to add assertions only in certain circumstances without requiring separate conditional logic.

§Parameters
  • condition - Boolean that determines whether to add the assertion
  • predicate - The predicate for the assertion
  • object - The object value for the assertion
§Returns

A new envelope with the assertion added if the condition is true, or the original envelope if the condition is false.

§Examples
let is_verified = true;
let is_expired = false;

let document = Envelope::new("document")
    .add_assertion_if(is_verified, "verified", true) // This will be added
    .add_assertion_if(is_expired, "expired", true); // This won't be added

// Only the verification assertion is present
assert_eq!(document.assertions().len(), 1);
Source

pub fn add_assertion_envelope_if( &self, condition: bool, assertion_envelope: Self, ) -> Result<Self>

Adds an assertion envelope only if the provided condition is true.

Similar to add_assertion_if but works with pre-constructed assertion envelopes. This is useful when you have already created an assertion envelope separately and want to conditionally add it.

§Parameters
  • condition - Boolean that determines whether to add the assertion envelope
  • assertion_envelope - The assertion envelope to add
§Returns

A new envelope with the assertion added if the condition is true, or the original envelope if the condition is false.

§Errors

Returns EnvelopeError::InvalidFormat if the provided envelope is not a valid assertion envelope or an obscured variant and the condition is true.

§Examples
let assertion = Envelope::new_assertion("verified", true);
let should_include = true;

let document = Envelope::new("document")
    .add_assertion_envelope_if(should_include, assertion)
    .unwrap();
Source§

impl Envelope

Support for adding assertions with salt.

Salting adds random data to an assertion to change its digest while preserving semantic meaning. This is useful for decorrelation - making it impossible to determine if two elided envelopes contain the same assertion by comparing their digests.

Source

pub fn add_assertion_salted<P, O>( &self, predicate: P, object: O, salted: bool, ) -> Self

Returns the result of adding the given assertion to the envelope, optionally salting it.

Source

pub fn add_assertion_envelope_salted( &self, assertion_envelope: Self, salted: bool, ) -> Result<Self>

Returns the result of adding the given assertion to the envelope, optionally salting it.

The assertion envelope must be a valid assertion envelope, or an obscured variant (elided, encrypted, compressed) of one.

Source

pub fn add_optional_assertion_envelope_salted( &self, assertion: Option<Self>, salted: bool, ) -> Result<Self>

If the optional assertion is present, returns the result of adding it to the envelope, optionally salting it. Otherwise, returns the envelope unchanged.

The assertion envelope must be a valid assertion envelope, or an obscured variant (elided, encrypted, compressed) of one.

Source

pub fn add_assertions_salted(&self, assertions: &[Self], salted: bool) -> Self

Source§

impl Envelope

Support for removing or replacing assertions.

These methods allow for modifying an envelope by removing or replacing existing assertions, while maintaining the envelope’s immutability model.

Source

pub fn remove_assertion(&self, target: Self) -> Self

Returns a new envelope with the given assertion removed.

Finds and removes an assertion matching the target assertion’s digest. If the assertion doesn’t exist, returns the same envelope unchanged. If removing the assertion would leave the envelope with no assertions, returns just the subject as a new envelope.

§Parameters
  • target - The assertion envelope to remove
§Returns

A new envelope with the specified assertion removed if found, or the original envelope if not found.

§Examples
// Create an envelope with assertions
let person = Envelope::new("Alice")
    .add_assertion("name", "Alice Smith")
    .add_assertion("age", 30);

// Create the assertion to remove
let name_assertion = Envelope::new_assertion("name", "Alice Smith");

// Remove the name assertion
let modified = person.remove_assertion(name_assertion);

// The envelope now only has the age assertion
assert_eq!(modified.assertions().len(), 1);
Source

pub fn replace_assertion( &self, assertion: Self, new_assertion: Self, ) -> Result<Self>

Returns a new envelope with the given assertion replaced by a new one.

This method removes the specified assertion and adds a new one in its place. If the targeted assertion does not exist, returns the same envelope with the new assertion added.

§Parameters
  • assertion - The assertion envelope to replace
  • new_assertion - The new assertion envelope to add
§Returns

A new envelope with the assertion replaced if found, or the original envelope with the new assertion added if not found.

§Errors

Returns EnvelopeError::InvalidFormat if the new assertion is not a valid assertion envelope or an obscured variant.

§Examples
// Create an envelope with assertions
let person = Envelope::new("Alice")
    .add_assertion("name", "Alice Smith")
    .add_assertion("age", 30);

// Create the assertion to replace and the new assertion
let old_name = Envelope::new_assertion("name", "Alice Smith");
let new_name = Envelope::new_assertion("name", "Alice Johnson");

// Replace the name assertion
let modified = person.replace_assertion(old_name, new_name).unwrap();
Source

pub fn replace_subject(&self, subject: Self) -> Self

Returns a new envelope with its subject replaced by the provided one.

This method preserves all assertions from the original envelope but applies them to a new subject. It effectively creates a new envelope with the provided subject and copies over all assertions from the current envelope.

§Parameters
  • subject - The new subject for the envelope
§Returns

A new envelope with the new subject and all assertions from the original envelope.

§Examples
// Create an envelope for Alice
let alice = Envelope::new("Alice")
    .add_assertion("age", 30)
    .add_assertion("city", "Boston");

// Replace the subject to create an envelope for Bob with the same assertions
let bob = alice.replace_subject(Envelope::new("Bob"));

// Bob now has the same assertions
assert_eq!(bob.extract_subject::<String>().unwrap(), "Bob");
assert_eq!(bob.assertions().len(), 2);
Source§

impl Envelope

Support for working with the digest tree of an Envelope.

Gordian Envelope’s structure includes a Merkle-like digest tree where each node has a cryptographic digest representing its content. These methods help navigate and utilize this digest tree.

Source

pub fn digests(&self, level_limit: usize) -> HashSet<Digest>

Returns the set of digests contained in the envelope’s elements, down to the specified level.

This method collects all digests from the envelope’s structure up to a certain depth. It’s extremely useful for selective elision or revelation, allowing you to gather digests of specific parts of the structure to target them for operations.

§Parameters
  • level_limit - Maximum level depth to include (0 means no digests, usize::MAX means all digests)
§Returns

A HashSet containing all the digests in the envelope structure up to the specified level. The digest of the envelope itself and its subject are both included (if they differ).

§Examples
let envelope = Envelope::new("Alice")
    .add_assertion("name", "Alice Smith")
    .add_assertion("age", 30);

// Level 0 returns an empty set
assert_eq!(envelope.digests(0).len(), 0);

// Level 1 returns just the envelope's digest
assert_eq!(envelope.digests(1).len(), 2); // Envelope and subject digests

// A deeper level includes assertion digests
assert!(envelope.digests(3).len() > 4); // Includes assertions plus their predicates and objects
Source

pub fn deep_digests(&self) -> HashSet<Digest>

Returns the set of all digests in the envelope, at all levels.

This is a convenience method that retrieves every digest in the envelope structure, no matter how deeply nested. It’s useful when you need to work with the complete digest tree, such as when verifying integrity or preparing for comprehensive elision.

§Returns

A HashSet containing all digests in the envelope structure.

§Examples
let envelope = Envelope::new("Alice")
    .add_assertion("name", "Alice Smith")
    .add_assertion("age", 30)
    .add_assertion(
        "address",
        Envelope::new("Address")
            .add_assertion("city", "Boston")
            .add_assertion("zip", "02108"),
    );

// Gets all digests from the entire structure
let digests = envelope.deep_digests();

// This includes nested assertions digests
assert!(digests.len() > 10);
Source

pub fn shallow_digests(&self) -> HashSet<Digest>

Returns the set of digests in the envelope, down to its second level only.

This is a convenience method that retrieves just the top-level digests in the envelope, including the envelope itself, its subject, and its immediate assertions, but not deeper nested content. It’s useful when you want to work with just the top-level structure without getting into nested details.

§Returns

A HashSet containing digests from the envelope’s first two levels.

§Examples
let envelope = Envelope::new("Alice")
    .add_assertion("name", "Alice Smith")
    .add_assertion(
        "address",
        Envelope::new("Address")
            .add_assertion("city", "Boston")
            .add_assertion("zip", "02108"),
    );

// Gets just the shallow digests
let shallow = envelope.shallow_digests();

// Gets all digests
let deep = envelope.deep_digests();

// The shallow set is smaller than the deep set
assert!(shallow.len() < deep.len());
Source

pub fn structural_digest(&self) -> Digest

Returns a digest that captures the structural form of an envelope, not just its semantic content.

While the regular digest() method provides a value for comparing semantic equivalence (whether two envelopes contain the same information), this method produces a digest that additionally captures the structural form of the envelope, including its elision patterns, encryption, and compression.

This allows distinguishing between envelopes that contain the same information but differ in how that information is structured or obscured.

§Semantic vs. Structural Comparison
  • Semantic equivalence (using digest() or is_equivalent_to()) - Two envelopes contain the same information in their unobscured form, complexity O(1)

  • Structural identity (using structural_digest() or is_identical_to()) - Two envelopes not only contain the same information but also have the same structure, including elision patterns, encryption, compression, etc., complexity O(m + n) where m and n are the number of elements in each envelope

§Returns

A Digest that uniquely identifies the envelope’s structure as well as its content.

§Examples
// Two envelopes with the same content but different structure
let envelope1 = Envelope::new("Alice").add_assertion("name", "Alice Smith");

let envelope2 = Envelope::new("Alice")
    .add_assertion("name", "Alice Smith")
    .elide_removing_target(&Envelope::new("Alice"));

// They are semantically equivalent
assert!(envelope1.is_equivalent_to(&envelope2));
assert_eq!(envelope1.digest(), envelope2.digest());

// But they are structurally different
assert!(!envelope1.is_identical_to(&envelope2));
assert_ne!(envelope1.structural_digest(), envelope2.structural_digest());
Source

pub fn is_equivalent_to(&self, other: &Self) -> bool

Tests if this envelope is semantically equivalent to another envelope.

Two envelopes are semantically equivalent if they contain the same information in their unobscured form, even if they have different structures (e.g., one is partially elided and the other is not).

This comparison has a complexity of O(1) as it simply compares the top-level digests.

§Parameters
  • other - The other envelope to compare with
§Returns

true if the envelopes are semantically equivalent, false otherwise.

§Examples
// Create two envelopes with the same semantic content but different structure
let original = Envelope::new("Hello world");
let elided = original.elide();

// They are semantically equivalent (contain the same information)
assert!(original.is_equivalent_to(&elided));

// But they have different structures
assert!(!original.is_identical_to(&elided));
Source

pub fn is_identical_to(&self, other: &Self) -> bool

Tests if two envelopes are structurally identical.

This function determines whether two envelopes are structurally identical. The comparison follows these rules:

  1. If the envelopes are not semantically equivalent (different digests), returns false - different content means they cannot be identical

  2. If the envelopes are semantically equivalent (same digests), then it compares their structural digests to check if they have the same structure (elision patterns, encryption, etc.)

The comparison has a complexity of O(1) if the envelopes are not semantically equivalent, and O(m + n) if they are, where m and n are the number of elements in each envelope.

§Parameters
  • other - The other envelope to compare with
§Returns

true if and only if the envelopes have both the same content (semantically equivalent) AND the same structure, false otherwise.

§Examples
// Two envelopes with identical structure
let env1 = Envelope::new("Alice");
let env2 = Envelope::new("Alice");
let env3 = Envelope::new("Bob");

// Semantically different envelopes are not identical
assert!(!env1.is_identical_to(&env3));

// Two envelopes with same content and structure are identical
assert!(env1.is_identical_to(&env2));

// Envelopes with same content but different structure (one elided) are not identical
let elided = env1.elide();
assert!(env1.is_equivalent_to(&elided));  // semantically the same
assert!(!env1.is_identical_to(&elided));  // but structurally different
Source§

impl Envelope

Source

pub fn case(&self) -> &EnvelopeCase

Returns a reference to the underlying envelope case.

The EnvelopeCase enum represents the specific structural variant of this envelope. This method provides access to that underlying variant for operations that need to differentiate between the different envelope types.

§Returns

A reference to the EnvelopeCase that defines this envelope’s structure.

Source§

impl Envelope

Support for basic envelope creation.

Source

pub fn new(subject: impl EnvelopeEncodable) -> Self

Creates an envelope with a subject, which can be any instance that implements EnvelopeEncodable.

Source

pub fn new_or_null(subject: Option<impl EnvelopeEncodable>) -> Self

Creates an envelope with a subject, which can be any instance that implements EnvelopeEncodable.

If subject is None, returns a null envelope.

Source

pub fn new_or_none(subject: Option<impl EnvelopeEncodable>) -> Option<Self>

Creates an envelope with a subject, which can be any instance that implements EnvelopeEncodable.

If subject is None, returns None.

Source

pub fn new_assertion( predicate: impl EnvelopeEncodable, object: impl EnvelopeEncodable, ) -> Self

Creates an assertion envelope with a predicate and object, each of which can be any instance that implements EnvelopeEncodable.

Source§

impl Envelope

Support for eliding elements from envelopes.

This includes eliding, encrypting and compressing (obscuring) elements.

Source

pub fn elide(&self) -> Self

Returns the elided variant of this envelope.

Elision replaces an envelope with just its digest, hiding its content while maintaining the integrity of the envelope’s digest tree. This is a fundamental privacy feature of Gordian Envelope that enables selective disclosure.

Returns the same envelope if it is already elided.

§Examples
let envelope = Envelope::new("Hello.");
let elided = envelope.elide();

// The elided envelope shows only "ELIDED" in formatting
assert_eq!(elided.format_flat(), "ELIDED");

// But it maintains the same digest as the original
assert!(envelope.is_equivalent_to(&elided));
Source

pub fn elide_removing_set_with_action( &self, target: &HashSet<Digest>, action: &ObscureAction, ) -> Self

Returns a version of this envelope with elements in the target set elided.

This function obscures elements in the envelope whose digests are in the provided target set, applying the specified action (elision, encryption, or compression) to those elements while leaving other elements intact.

§Parameters
  • target - The set of digests that identify elements to be obscured
  • action - The action to perform on the targeted elements (elide, encrypt, or compress)
§Examples
let envelope = Envelope::new("Alice")
    .add_assertion("knows", "Bob")
    .add_assertion("livesAt", "123 Main St.");

// Create a set of digests targeting the "livesAt" assertion
let mut target = HashSet::new();
let livesAt_assertion = envelope.assertion_with_predicate("livesAt").unwrap();
target.insert(livesAt_assertion.digest());

// Elide that specific assertion
let elided = envelope.elide_removing_set_with_action(&target, &ObscureAction::Elide);

// The result will have the "livesAt" assertion elided but "knows" still visible
Source

pub fn elide_removing_set(&self, target: &HashSet<Digest>) -> Self

Returns a version of this envelope with elements in the target set elided.

This is a convenience function that calls elide_set with is_revealing set to false, using the standard elision action. Use this when you want to simply elide elements rather than encrypt or compress them.

§Parameters
  • target - The set of digests that identify elements to be elided
§Examples
let envelope = Envelope::new("Alice")
    .add_assertion("knows", "Bob")
    .add_assertion("email", "alice@example.com");

// Create a set of digests targeting the email assertion
let mut target = HashSet::new();
let email_assertion = envelope.assertion_with_predicate("email").unwrap();
target.insert(email_assertion.digest());

// Elide the email assertion for privacy
let redacted = envelope.elide_removing_set(&target);
Source

pub fn elide_removing_array_with_action( &self, target: &[&dyn DigestProvider], action: &ObscureAction, ) -> Self

Returns a version of this envelope with elements in the target set elided.

  • Parameters:

    • target: An array of DigestProviders.
    • action: Perform the specified action (elision, encryption or compression).
  • Returns: The elided envelope.

Source

pub fn elide_removing_array(&self, target: &[&dyn DigestProvider]) -> Self

Returns a version of this envelope with elements in the target set elided.

  • Parameters:

    • target: An array of DigestProviders.
    • action: Perform the specified action (elision, encryption or compression).
  • Returns: The elided envelope.

Source

pub fn elide_removing_target_with_action( &self, target: &dyn DigestProvider, action: &ObscureAction, ) -> Self

Returns a version of this envelope with the target element elided.

  • Parameters:

    • target: A DigestProvider.
    • action: Perform the specified action (elision, encryption or compression).
  • Returns: The elided envelope.

Source

pub fn elide_removing_target(&self, target: &dyn DigestProvider) -> Self

Returns a version of this envelope with the target element elided.

  • Parameters:

    • target: A DigestProvider.
  • Returns: The elided envelope.

Source

pub fn elide_revealing_set_with_action( &self, target: &HashSet<Digest>, action: &ObscureAction, ) -> Self

Returns a version of this envelope with only elements in the target set revealed, and all other elements elided.

This function performs the opposite operation of elide_removing_set_with_action. Instead of specifying which elements to obscure, you specify which elements to reveal, and everything else will be obscured using the specified action.

This is particularly useful for selective disclosure where you want to reveal only specific portions of an envelope while keeping the rest private.

§Parameters
  • target - The set of digests that identify elements to be revealed
  • action - The action to perform on all other elements (elide, encrypt, or compress)
§Examples
let envelope = Envelope::new("Alice")
    .add_assertion("name", "Alice Smith")
    .add_assertion("age", 30)
    .add_assertion("ssn", "123-45-6789");

// Create a set of digests for elements we want to reveal
let mut reveal_set = HashSet::new();

// Add the subject and the name assertion to the set to reveal
reveal_set.insert(envelope.subject().digest());
reveal_set
    .insert(envelope.assertion_with_predicate("name").unwrap().digest());

// Create an envelope that only reveals name and hides age and SSN
let selective = envelope
    .elide_revealing_set_with_action(&reveal_set, &ObscureAction::Elide);
Source

pub fn elide_revealing_set(&self, target: &HashSet<Digest>) -> Self

Returns a version of this envelope with elements not in the target set elided.

  • Parameters:

    • target: The target set of digests.
  • Returns: The elided envelope.

Source

pub fn elide_revealing_array_with_action( &self, target: &[&dyn DigestProvider], action: &ObscureAction, ) -> Self

Returns a version of this envelope with elements not in the target set elided.

  • Parameters:

    • target: An array of DigestProviders.
    • action: Perform the specified action (elision, encryption or compression).
  • Returns: The elided envelope.

Source

pub fn elide_revealing_array(&self, target: &[&dyn DigestProvider]) -> Self

Returns a version of this envelope with elements not in the target set elided.

  • Parameters:

    • target: An array of DigestProviders.
  • Returns: The elided envelope.

Source

pub fn elide_revealing_target_with_action( &self, target: &dyn DigestProvider, action: &ObscureAction, ) -> Self

Returns a version of this envelope with all elements except the target element elided.

  • Parameters:

    • target: A DigestProvider.
    • action: Perform the specified action (elision, encryption or compression).
  • Returns: The elided envelope.

Source

pub fn elide_revealing_target(&self, target: &dyn DigestProvider) -> Self

Returns a version of this envelope with all elements except the target element elided.

  • Parameters:

    • target: A DigestProvider.
  • Returns: The elided envelope.

Source

pub fn elide_set_with_action( &self, target: &HashSet<Digest>, is_revealing: bool, action: &ObscureAction, ) -> Self

Returns an elided version of this envelope.

  • Parameters:

    • target: The target set of digests.
    • isRevealing: If true, the target set contains the digests of the elements to leave revealed. If it is false, the target set contains the digests of the elements to elide.
    • action: Perform the specified action (elision, encryption or compression).
  • Returns: The elided envelope.

Source

pub fn elide_set(&self, target: &HashSet<Digest>, is_revealing: bool) -> Self

Returns an elided version of this envelope.

  • Parameters:

    • target: The target set of digests.
    • isRevealing: If true, the target set contains the digests of the elements to leave revealed. If it is false, the target set contains the digests of the elements to elide.
  • Returns: The elided envelope.

Source

pub fn elide_array_with_action( &self, target: &[&dyn DigestProvider], is_revealing: bool, action: &ObscureAction, ) -> Self

Returns an elided version of this envelope.

  • Parameters:

    • target: An array of DigestProviders.
    • isRevealing: If true, the target set contains the digests of the elements to leave revealed. If it is false, the target set contains the digests of the elements to elide.
    • action: Perform the specified action (elision, encryption or compression).
  • Returns: The elided envelope.

Source

pub fn elide_array( &self, target: &[&dyn DigestProvider], is_revealing: bool, ) -> Self

Returns an elided version of this envelope.

  • Parameters:

    • target: An array of DigestProviders.
    • isRevealing: If true, the target set contains the digests of the elements to leave revealed. If it is false, the target set contains the digests of the elements to elide.
  • Returns: The elided envelope.

Source

pub fn elide_target_with_action( &self, target: &dyn DigestProvider, is_revealing: bool, action: &ObscureAction, ) -> Self

Returns an elided version of this envelope.

  • Parameters:

    • target: A DigestProvider.
    • isRevealing: If true, the target is the element to leave revealed, eliding all others. If it is false, the target is the element to elide, leaving all others revealed.
    • action: Perform the specified action (elision, encryption or compression).
  • Returns: The elided envelope.

Source

pub fn elide_target( &self, target: &dyn DigestProvider, is_revealing: bool, ) -> Self

Returns an elided version of this envelope.

  • Parameters:

    • target: A DigestProvider.
    • isRevealing: If true, the target is the element to leave revealed, eliding all others. If it is false, the target is the element to elide, leaving all others revealed.
  • Returns: The elided envelope.

Source

pub fn unelide(&self, envelope: impl Into<Envelope>) -> Result<Self>

Returns the unelided variant of this envelope by revealing the original content.

This function allows restoring an elided envelope to its original form, but only if the provided envelope’s digest matches the elided envelope’s digest. This ensures the integrity of the revealed content.

Returns the same envelope if it is already unelided.

§Errors

Returns EnvelopeError::InvalidDigest if the provided envelope’s digest doesn’t match the current envelope’s digest.

§Examples
let original = Envelope::new("Hello.");
let elided = original.elide();

// Later, we can unelide the envelope if we have the original
let revealed = elided.unelide(&original).unwrap();
assert_eq!(revealed.format(), "\"Hello.\"");

// Attempting to unelide with a different envelope will fail
let different = Envelope::new("Different");
assert!(elided.unelide(&different).is_err());
Source

pub fn nodes_matching( &self, target_digests: Option<&HashSet<Digest>>, obscure_types: &[ObscureType], ) -> HashSet<Digest>

Returns the set of digests of nodes matching the specified criteria.

This function walks the envelope hierarchy and returns digests of nodes that match both:

  • The optional target digest set (if provided; otherwise all nodes match)
  • Any of the specified obscuration types

If no obscuration types are provided, all nodes in the target set (or all nodes if no target set) are returned.

§Parameters
  • target_digests - Optional set of digests to filter by. If None, all nodes are considered for matching.
  • obscure_types - Slice of ObscureType values to match against. Only nodes obscured in one of these ways will be included.
§Returns

A HashSet of digests for nodes matching the specified criteria.

§Examples
let envelope = Envelope::new("Alice")
    .add_assertion("knows", "Bob")
    .add_assertion("age", 30);

// Elide one assertion
let knows_digest =
    envelope.assertion_with_predicate("knows").unwrap().digest();
let mut target = HashSet::new();
target.insert(knows_digest.clone());

let elided = envelope.elide_removing_set(&target);

// Find all elided nodes
let elided_digests = elided.nodes_matching(None, &[ObscureType::Elided]);
assert!(elided_digests.contains(&knows_digest));
Source

pub fn walk_unelide(&self, envelopes: &[Envelope]) -> Self

Returns a new envelope with elided nodes restored from the provided set.

This function walks the envelope hierarchy and attempts to restore any elided nodes by matching their digests against the provided set of envelopes. If a match is found, the elided node is replaced with the matching envelope.

If no matches are found, the original envelope is returned unchanged.

§Parameters
  • envelopes - A slice of envelopes that may match elided nodes in self
§Returns

A new envelope with elided nodes restored where possible.

§Examples
let alice = Envelope::new("Alice");
let bob = Envelope::new("Bob");
let envelope = Envelope::new("Alice").add_assertion("knows", "Bob");

// Elide both the subject and an assertion
let elided = envelope
    .elide_removing_target(&alice)
    .elide_removing_target(&bob);

// Restore the elided nodes
let restored = elided.walk_unelide(&[alice, bob]);

// The restored envelope should match the original
assert_eq!(restored.format(), envelope.format());
Source

pub fn walk_replace( &self, target: &HashSet<Digest>, replacement: &Envelope, ) -> Result<Self>

Returns a new envelope with nodes matching target digests replaced.

This function walks the envelope hierarchy and replaces any nodes whose digests match those in the provided target set with clones of the replacement envelope. Unlike walk_unelide, the replacement envelope does not need to have the same digest as the node being replaced.

This enables transforming specific elements in an envelope structure while preserving the overall hierarchy. The replacement is applied recursively throughout the tree.

§Parameters
  • target - Set of digests identifying nodes to replace
  • replacement - The envelope to clone for each matching node
§Returns

A new envelope with matching nodes replaced.

§Errors

Returns Error::InvalidFormat if attempting to replace an assertion with a non-assertion that is also not obscured (elided, encrypted, or compressed). Assertions in a node’s assertions array must be either assertions or obscured elements (which are presumed to be obscured assertions).

§Examples
let alice = Envelope::new("Alice");
let bob = Envelope::new("Bob");
let charlie = Envelope::new("Charlie");

let envelope = Envelope::new("Alice")
    .add_assertion("knows", "Bob")
    .add_assertion("likes", "Bob");

// Replace all instances of "Bob" with "Charlie"
let mut target = HashSet::new();
target.insert(bob.digest());

let modified = envelope.walk_replace(&target, &charlie).unwrap();

// Both assertions now reference Charlie instead of Bob
assert!(modified.format().contains("Charlie"));
assert!(!modified.format().contains("Bob"));
Source

pub fn walk_decrypt(&self, keys: &[SymmetricKey]) -> Self

Returns a new envelope with encrypted nodes decrypted using the provided keys.

This function walks the envelope hierarchy and attempts to decrypt any encrypted nodes using the provided set of symmetric keys. Each key is tried in sequence until one succeeds or all fail.

If no nodes can be decrypted, the original envelope is returned unchanged.

This function is only available when the encrypt feature is enabled.

§Parameters
  • keys - A slice of SymmetricKey values to use for decryption
§Returns

A new envelope with encrypted nodes decrypted where possible.

§Examples
let key1 = SymmetricKey::new();
let key2 = SymmetricKey::new();

let envelope = Envelope::new("Alice")
    .add_assertion("knows", "Bob")
    .add_assertion("age", 30);

// Encrypt different parts with different keys
let encrypted = envelope.elide_removing_set_with_action(
    &std::collections::HashSet::from([envelope
        .assertion_with_predicate("knows")
        .unwrap()
        .digest()]),
    &ObscureAction::Encrypt(key1.clone()),
);

// Decrypt with a set of keys
let decrypted = encrypted.walk_decrypt(&[key1, key2]);

// The decrypted envelope should match the original
assert!(decrypted.is_equivalent_to(&envelope));
Source

pub fn walk_decompress(&self, target_digests: Option<&HashSet<Digest>>) -> Self

Returns a new envelope with compressed nodes decompressed.

This function walks the envelope hierarchy and decompresses nodes that:

  • Are compressed, AND
  • Match the target digest set (if provided), OR all compressed nodes if no target set is provided

If no nodes can be decompressed, the original envelope is returned unchanged.

This function is only available when the compress feature is enabled.

§Parameters
  • target_digests - Optional set of digests to filter by. If None, all compressed nodes will be decompressed.
§Returns

A new envelope with compressed nodes decompressed where they match the criteria.

§Examples
let envelope = Envelope::new("Alice")
    .add_assertion("knows", "Bob")
    .add_assertion("bio", "A".repeat(1000));

// Compress one assertion
let bio_assertion = envelope.assertion_with_predicate("bio").unwrap();
let bio_digest = bio_assertion.digest();
let mut target = HashSet::new();
target.insert(bio_digest);

let compressed = envelope
    .elide_removing_set_with_action(&target, &ObscureAction::Compress);

// Decompress just the targeted node
let decompressed = compressed.walk_decompress(Some(&target));

// The decompressed envelope should match the original
assert!(decompressed.is_equivalent_to(&envelope));
Source§

impl Envelope

Static methods for creating envelopes from CBOR data.

Source

pub fn try_from_cbor(cbor: CBOR) -> Result<Self>

Creates an envelope from a CBOR value.

§Parameters
  • cbor - The CBOR value to convert into an envelope
§Returns

A new envelope created from the CBOR data.

§Errors

Returns an error if the CBOR does not represent a valid envelope structure.

Source

pub fn try_from_cbor_data(data: Vec<u8>) -> Result<Self>

Creates an envelope from raw CBOR binary data.

§Parameters
  • data - The raw CBOR binary data to convert into an envelope
§Returns

A new envelope created from the CBOR data.

§Errors

Returns an error if the data is not valid CBOR or does not represent a valid envelope structure.

Source§

impl Envelope

Source

pub fn subject(&self) -> Self

The envelope’s subject.

For an envelope with no assertions, returns the same envelope.

Source

pub fn assertions(&self) -> Vec<Self>

The envelope’s assertions.

Source

pub fn has_assertions(&self) -> bool

true if the envelope has at least one assertion, false otherwise.

Source

pub fn as_assertion(&self) -> Option<Self>

If the envelope’s subject is an assertion return it, else return None.

Source

pub fn try_assertion(&self) -> Result<Self>

If the envelope’s subject is an assertion return it, else return an error.

Source

pub fn as_predicate(&self) -> Option<Self>

The envelope’s predicate, or None if the envelope is not an assertion.

Source

pub fn try_predicate(&self) -> Result<Self>

The envelope’s predicate, or an error if the envelope is not an assertion.

Source

pub fn as_object(&self) -> Option<Self>

The envelope’s object, or None if the envelope is not an assertion.

Source

pub fn try_object(&self) -> Result<Self>

The envelope’s object, or an error if the envelope is not an assertion.

Source

pub fn as_leaf(&self) -> Option<CBOR>

The envelope’s leaf CBOR object, or None if the envelope is not a leaf.

Source

pub fn try_leaf(&self) -> Result<CBOR>

The envelope’s leaf CBOR object, or an error if the envelope is not a leaf.

Source

pub fn is_assertion(&self) -> bool

true if the envelope is case ::Assertion, false otherwise.

Source

pub fn is_encrypted(&self) -> bool

true if the envelope is case ::Encrypted, false otherwise.

Source

pub fn is_compressed(&self) -> bool

true if the envelope is case ::Compressed, false otherwise.

Source

pub fn is_elided(&self) -> bool

true if the envelope is case ::Elided, false otherwise.

Source

pub fn is_leaf(&self) -> bool

true if the envelope is case ::Leaf, false otherwise.

Source

pub fn is_node(&self) -> bool

true if the envelope is case ::Node, false otherwise.

Source

pub fn is_wrapped(&self) -> bool

true if the envelope is case ::Wrapped, false otherwise.

Source§

impl Envelope

Source

pub fn is_subject_assertion(&self) -> bool

true if the subject of the envelope is an assertion, false otherwise.

Source

pub fn is_subject_encrypted(&self) -> bool

true if the subject of the envelope has been encrypted, false otherwise.

Source

pub fn is_subject_compressed(&self) -> bool

true if the subject of the envelope has been compressed, false otherwise.

Source

pub fn is_subject_elided(&self) -> bool

true if the subject of the envelope has been elided, false otherwise.

Source

pub fn is_subject_obscured(&self) -> bool

true if the subject of the envelope has been encrypted, elided, or compressed, false otherwise.

Obscured assertion envelopes may exist in the list of an envelope’s assertions.

Source

pub fn is_internal(&self) -> bool

true if the envelope is internal, that is, it has child elements, or false if it is a leaf node.

Internal elements include .node, .wrapped, and .assertion.

Source

pub fn is_obscured(&self) -> bool

true if the envelope is encrypted, elided, or compressed; false otherwise.

Source

pub fn extract_subject<T>(&self) -> Result<T>
where T: Any + TryFrom<CBOR, Error = Error>,

Returns the envelope’s subject, decoded as the given CBOR type.

This method attempts to convert the envelope’s subject into the requested type T. The conversion will succeed if the underlying CBOR data can be properly decoded as the specified type.

§Type Parameters
  • T - The target type to convert the subject into. Must implement TryFrom<CBOR>.
§Returns
  • Result<T> - The decoded subject value or an error if conversion fails
§Errors
  • Returns Error::InvalidFormat if the encoded type doesn’t match the requested type.
§Examples
use bc_envelope::prelude::*;

// Extract a string
let envelope = Envelope::new("Hello");
let text: String = envelope.extract_subject().unwrap();
assert_eq!(text, "Hello");

// Extract a number
let envelope = Envelope::new(42);
let number: i32 = envelope.extract_subject().unwrap();
assert_eq!(number, 42);

// Extract fails with wrong type
let envelope = Envelope::new("Not a number");
let result = envelope.extract_subject::<i32>();
assert!(result.is_err());
Source

pub fn assertions_with_predicate( &self, predicate: impl EnvelopeEncodable, ) -> Vec<Self>

Returns all assertions with the given predicate. Match by comparing digests.

Source

pub fn assertion_with_predicate( &self, predicate: impl EnvelopeEncodable, ) -> Result<Self>

Returns the assertion with the given predicate.

Searches the envelope’s assertions for one with a predicate matching the provided value. The match is determined by comparing the digests of the predicates.

§Arguments
  • predicate - The predicate to search for, can be any type that implements EnvelopeEncodable
§Returns
  • Result<Self> - The matching assertion envelope if found
§Errors
  • Returns EnvelopeError::NonexistentPredicate if no assertion has the specified predicate
  • Returns EnvelopeError::AmbiguousPredicate if multiple assertions have the specified predicate
§Examples
use bc_envelope::prelude::*;

let envelope = Envelope::new("Person")
    .add_assertion("name", "Alice")
    .add_assertion("age", 30);

// Find assertion with predicate "name"
let name_assertion = envelope.assertion_with_predicate("name").unwrap();
let name = name_assertion
    .as_object()
    .unwrap()
    .extract_subject::<String>()
    .unwrap();
assert_eq!(name, "Alice");

// Trying to find a non-existent predicate produces an error
assert!(envelope.assertion_with_predicate("address").is_err());
Source

pub fn optional_assertion_with_predicate( &self, predicate: impl EnvelopeEncodable, ) -> Result<Option<Self>>

Returns the assertion with the given predicate, or None if there is no matching predicate.

Returns an error if there are multiple matching predicates.

Source

pub fn object_for_predicate( &self, predicate: impl EnvelopeEncodable, ) -> Result<Self>

Returns the object of the assertion with the given predicate.

This is a convenience method that finds an assertion with the specified predicate and returns its object. It’s a common operation when working with envelopes that have assertions containing data or metadata.

§Arguments
  • predicate - The predicate to search for, can be any type that implements EnvelopeEncodable
§Returns
  • Result<Self> - The object part of the matching assertion
§Errors
  • Returns EnvelopeError::NonexistentPredicate if no assertion has the specified predicate
  • Returns EnvelopeError::AmbiguousPredicate if multiple assertions have the specified predicate
§Examples
use bc_envelope::prelude::*;

let envelope = Envelope::new("Person")
    .add_assertion("name", "Alice")
    .add_assertion("age", 30);

// Get the object directly
let name = envelope.object_for_predicate("name").unwrap();
assert_eq!(name.extract_subject::<String>().unwrap(), "Alice");

let age = envelope.object_for_predicate("age").unwrap();
assert_eq!(age.extract_subject::<i32>().unwrap(), 30);
Source

pub fn try_as<T>(&self) -> Result<T>
where T: TryFrom<Envelope, Error = Error>,

Returns the envelope decoded as the given type.

This method attempts to convert the envelope into the requested type T. The conversion will succeed if the envelope can be properly decoded as the specified type.

Source

pub fn try_object_for_predicate<T>( &self, predicate: impl EnvelopeEncodable, ) -> Result<T>
where T: TryFrom<Envelope, Error = Error>,

Returns the object of the assertion with the given predicate, decoded as the given type.

This is a convenience method that finds an assertion with the specified predicate and returns its object, decoded as the specified type.

Source

pub fn optional_object_for_predicate( &self, predicate: impl EnvelopeEncodable, ) -> Result<Option<Self>>

Returns the object of the assertion with the given predicate, or None if there is no matching predicate.

Returns an error if there are multiple matching predicates.

Source

pub fn try_optional_object_for_predicate<T>( &self, predicate: impl EnvelopeEncodable, ) -> Result<Option<T>>
where T: TryFrom<Envelope, Error = Error>,

Returns the object of the assertion with the given predicate, or None if there is no matching predicate.

Source

pub fn extract_object<T: TryFrom<CBOR, Error = Error> + 'static>( &self, ) -> Result<T>

Returns the object of the assertion, decoded as the given CBOR type.

This method works with assertion envelopes (created with Envelope::new_assertion()) and extracts the object part of the assertion as the specified type.

§Type Parameters
  • T - The target type to convert the object into. Must implement TryFrom<CBOR>.
§Returns
  • Result<T> - The decoded object value
§Errors
  • Returns EnvelopeError::NotAssertion if the envelope is not an assertion
  • Returns Error::InvalidFormat if the encoded type doesn’t match the requested type
§Examples
use bc_envelope::prelude::*;

// Create an assertion envelope
let assertion = Envelope::new_assertion("age", 30);

// Extract the object value
let age: i32 = assertion.extract_object().unwrap();
assert_eq!(age, 30);

// Not an assertion, gives an error
let envelope = Envelope::new("Alice");
assert!(envelope.extract_object::<String>().is_err());
Source

pub fn extract_predicate<T: TryFrom<CBOR, Error = Error> + 'static>( &self, ) -> Result<T>

Returns the predicate of the assertion, decoded as the given CBOR type.

Returns an error if the envelope is not an assertion. Returns an error if the encoded type doesn’t match the given type.

Source

pub fn extract_object_for_predicate<T: TryFrom<CBOR, Error = Error> + 'static>( &self, predicate: impl EnvelopeEncodable, ) -> Result<T>

Returns the object of the assertion with the given predicate, decoded as the given CBOR type.

This is a high-level convenience method that combines finding an assertion by predicate and extracting its object as a specific type. This is particularly useful when working with envelopes containing typed data (strings, numbers, etc.) as assertion objects.

§Type Parameters
  • T - The target type to convert the object into. Must implement TryFrom<CBOR>.
§Arguments
  • predicate - The predicate to search for
§Returns
  • Result<T> - The decoded object value
§Errors
  • Returns EnvelopeError::NonexistentPredicate if no assertion has the specified predicate
  • Returns EnvelopeError::AmbiguousPredicate if multiple assertions have the specified predicate
  • Returns Error::InvalidFormat if the encoded type doesn’t match the requested type
§Examples
use bc_envelope::prelude::*;

let envelope = Envelope::new("Person")
    .add_assertion("name", "Alice")
    .add_assertion("age", 30);

// Extract typed values directly
let name: String = envelope.extract_object_for_predicate("name").unwrap();
let age: i32 = envelope.extract_object_for_predicate("age").unwrap();

assert_eq!(name, "Alice");
assert_eq!(age, 30);

// Type mismatch causes an error
let result = envelope.extract_object_for_predicate::<i32>("name");
assert!(result.is_err());
Source

pub fn extract_optional_object_for_predicate<T: TryFrom<CBOR, Error = Error> + 'static>( &self, predicate: impl EnvelopeEncodable, ) -> Result<Option<T>>

Returns the object of the assertion with the given predicate decoded as the given CBOR type, or None if there is no matching predicate.

Returns an error if there are multiple matching predicates.

Source

pub fn extract_object_for_predicate_with_default<T: TryFrom<CBOR, Error = Error> + 'static>( &self, predicate: impl EnvelopeEncodable, default: T, ) -> Result<T>

Returns the object of the assertion with the given predicate decoded as the given CBOR type, or a default value if there is no matching predicate.

Source

pub fn objects_for_predicate( &self, predicate: impl EnvelopeEncodable, ) -> Vec<Self>

Returns the objects of all assertions with the matching predicate.

Source

pub fn extract_objects_for_predicate<T: TryFrom<CBOR, Error = Error> + 'static>( &self, predicate: impl EnvelopeEncodable, ) -> Result<Vec<T>>

Returns the objects of all assertions with the matching predicate, decoded as the given CBOR type.

Returns an error if the encoded type doesn’t match the given type.

Source

pub fn try_objects_for_predicate<T: TryFrom<Envelope, Error = Error> + 'static>( &self, predicate: impl EnvelopeEncodable, ) -> Result<Vec<T>>

Returns the objects of all assertions with the matching predicate, decoded as the given type.

Returns an error if the encoded type doesn’t match the given type.

Source

pub fn elements_count(&self) -> usize

Returns the number of structural elements in the envelope, including itself.

Source§

impl Envelope

Source

pub fn set_position(&mut self, position: usize) -> Result<Self>

Sets the position (index) of the envelope by adding or replacing a known_values::POSITION assertion.

If there is more than one existing POSITION assertion, returns an InvalidFormat error. If a single POSITION assertion exists, it is removed before adding the new one. Returns the modified Envelope with the updated position.

§Arguments
  • position - The new position value to set.
§Errors

Returns an error if there is not exactly one POSITION assertion in the envelope.

Source

pub fn position(&self) -> Result<usize>

Retrieves the position value from the envelope’s known_values::POSITION assertion.

Searches for the POSITION assertion and extracts its value as a usize.

§Errors

Returns an error if the assertion is missing or if the value cannot be extracted as a usize.

Source

pub fn remove_position(&self) -> Result<Self>

Removes the known_values::POSITION assertion from the envelope.

§Errors

Returns an error if there is more than one POSITION assertion in the envelope.

If there is a single POSITION assertion, it is removed and the modified envelope is returned. If there are no POSITION assertions, the original envelope is returned.

Source§

impl Envelope

Functions for traversing and manipulating the envelope hierarchy.

Source

pub fn walk<State: Clone>( &self, hide_nodes: bool, state: State, visit: &Visitor<'_, State>, )

Walks the envelope structure, calling the visitor function for each element.

This function traverses the entire envelope hierarchy and calls the visitor function on each element. The traversal can be performed in two modes:

  • Structure-based traversal (hide_nodes = false): Visits every element including node containers
  • Tree-based traversal (hide_nodes = true): Skips node elements and focuses on semantic content

The visitor function can optionally return a context value that is passed to child elements, enabling state to be accumulated or passed down during traversal.

§Type Parameters
  • Parent - The type of context passed between parent and child elements
§Arguments
  • hide_nodes - If true, the visitor will not be called for node containers
  • visit - The visitor function called for each element
§Examples
use std::cell::RefCell;

use bc_envelope::prelude::*;

// Create an envelope with nested structure
let envelope = Envelope::new("Alice").add_assertion("knows", "Bob");

// Count the number of elements in the envelope
let count = RefCell::new(0);
let visitor = |_env: &Envelope,
               _level: usize,
               _edge: EdgeType,
               state: ()|
 -> ((), bool) {
    *count.borrow_mut() += 1;
    (state, false)
};

// Walk the entire envelope structure
envelope.walk(false, (), &visitor);
assert!(*count.borrow() > 0);
Source§

impl Envelope

Support for wrapping and unwrapping envelopes.

Source

pub fn wrap(&self) -> Self

Returns a new envelope which wraps the current envelope.

Wrapping an envelope allows you to treat an envelope (including its assertions) as a single unit, making it possible to add assertions about the envelope as a whole.

§Examples
// Create an envelope with an assertion
let envelope = Envelope::new("Hello.").add_assertion("language", "English");

// Wrap it to add an assertion about the envelope as a whole
let wrapped = envelope.wrap().add_assertion("authenticated", true);

assert_eq!(
    wrapped.format(),
    indoc! {r#"
{
    "Hello." [
        "language": "English"
    ]
} [
    "authenticated": true
]
"#}
    .trim()
);
Source

pub fn try_unwrap(&self) -> Result<Self>

Unwraps and returns the inner envelope.

This extracts the envelope contained within a wrapped envelope.

§Errors

Returns EnvelopeError::NotWrapped if this is not a wrapped envelope.

§Examples
// Create an envelope and wrap it
let envelope = Envelope::new("Hello.");
let wrapped = envelope.wrap();

// Unwrap to get the original envelope
let unwrapped = wrapped.try_unwrap().unwrap();
assert_eq!(unwrapped.format_flat(), r#""Hello.""#);
Source§

impl Envelope

Source

pub fn false() -> Self

Source

pub fn true() -> Self

Source

pub fn is_false(&self) -> bool

Source

pub fn is_true(&self) -> bool

Source

pub fn is_bool(&self) -> bool

Source§

impl Envelope

Source

pub fn is_number(&self) -> bool

true if the envelope is a leaf node that contains a number, false

Source

pub fn is_subject_number(&self) -> bool

true if the subject of the envelope is a number, false otherwise.

Source

pub fn is_nan(&self) -> bool

true if the envelope is a leaf node that contains the NaN value, false otherwise.

Source

pub fn is_subject_nan(&self) -> bool

true if the subject of the envelope is the NaN value, false otherwise.

Source§

impl Envelope

Source

pub fn null() -> Self

Source

pub fn is_null(&self) -> bool

Source§

impl Envelope

Source

pub fn try_byte_string(&self) -> Result<Vec<u8>>

The envelope’s leaf CBOR object as a CBOR byte string, or an error if the envelope is not a leaf, or the leaf is not a byte string.

Source

pub fn as_byte_string(&self) -> Option<Vec<u8>>

Source§

impl Envelope

Source

pub fn as_array(&self) -> Option<Vec<CBOR>>

Source

pub fn as_map(&self) -> Option<Map>

Source

pub fn as_text(&self) -> Option<String>

Source§

impl Envelope

Source

pub fn as_known_value(&self) -> Option<&KnownValue>

The envelope’s KnownValue, or None if the envelope is not case ::KnownValue.

Source

pub fn try_known_value(&self) -> Result<&KnownValue>

The envelope’s KnownValue, or an error if the envelope is not case ::KnownValue.

Source

pub fn is_known_value(&self) -> bool

true if the envelope is case ::KnownValue, false otherwise.

Source

pub fn unit() -> Self

Constructs a unit envelope.

Unit envelopes have the known value ''. They represent a position where no meaningful data can exist. In this sense they make a semantically stronger assertion than null, which represent a position where no meaningful data currently exists, but could exist in the future.

Source

pub fn is_subject_unit(&self) -> bool

true if the subject of the envelope is the unit value, false otherwise.

Source

pub fn check_subject_unit(&self) -> Result<&Self>

Checks that the subject of the envelope is the unit value.

Returns Ok(&self) if so, or an error otherwise.

Source§

impl Envelope

Support for the various text output formats for Envelope.

Source

pub fn format_opt(&self, opts: &EnvelopeFormatOpts<'_>) -> String

Returns the envelope notation for this envelope.

Source

pub fn format(&self) -> String

Returns the envelope notation for this envelope.

Uses the current format context.

Source

pub fn format_flat(&self) -> String

Returns the envelope notation for this envelope in flat format.

In flat format, the envelope is printed on a single line.

Source§

impl Envelope

Support for tree-formatting envelopes.

Source

pub fn tree_format(&self) -> String

Returns a tree-formatted string representation of the envelope with default options.

Source

pub fn tree_format_opt(&self, opts: &TreeFormatOpts<'_>) -> String

Returns a tree-formatted string representation of the envelope with the specified options.

§Options
  • hide_nodes - If true, hides NODE identifiers and only shows the semantic content. Default is false.
  • highlighting_target - Set of digests to highlight in the tree representation. Default is an empty set.
  • context - Formatting context. Default is TreeFormatContext::Global.
Source§

impl Envelope

Source

pub fn short_id(&self, opt: DigestDisplayFormat) -> String

Returns a text representation of the envelope’s digest.

Source§

impl Envelope

Support for tree-formatting envelopes.

Source

pub fn mermaid_format(&self) -> String

Source

pub fn mermaid_format_opt(&self, opts: &MermaidFormatOpts<'_>) -> String

Source§

impl Envelope

Source

pub fn summary(&self, max_length: usize, context: &FormatContext) -> String

Returns a short summary of the envelope’s content with a maximum length.

§Arguments
  • max_length - The maximum length of the summary
  • context - The formatting context
Source§

impl Envelope

Source

pub fn diagnostic_annotated(&self) -> String

Returns the CBOR diagnostic notation for this envelope, with annotations.

See RFC-8949 §8 for information on CBOR diagnostic notation.

Source

pub fn diagnostic(&self) -> String

Returns the CBOR diagnostic notation for this envelope.

Uses the current format context.

See RFC-8949 §8 for information on CBOR diagnostic notation.

Source§

impl Envelope

Source

pub fn hex_opt<'a>(&self, opts: HexFormatOpts<'a>) -> String

Returns the CBOR hex dump of this envelope.

See RFC-8949 for information on the CBOR binary format.

Source

pub fn hex(&self) -> String

Returns the CBOR hex dump of this envelope.

Uses the current format context.

See RFC-8949 for information on the CBOR binary format.

Source§

impl Envelope

Methods for creating attachment envelopes

Source

pub fn new_attachment( payload: impl EnvelopeEncodable, vendor: &str, conforms_to: Option<&str>, ) -> Self

Creates a new envelope with an attachment as its subject.

This creates an envelope whose subject is an attachment assertion, using the provided payload, vendor, and optional conformsTo URI.

§Parameters
  • payload - The content of the attachment
  • vendor - A string that uniquely identifies the vendor (typically a reverse domain name)
  • conforms_to - An optional URI that identifies the format of the attachment
§Returns

A new envelope with the attachment as its subject

§Examples
use bc_envelope::{base::envelope::EnvelopeCase, prelude::*};

// Create an attachment envelope
let envelope = Envelope::new_attachment(
    "Attachment data",
    "com.example",
    Some("https://example.com/format/v1"),
);

// The envelope is an assertion
assert!(matches!(envelope.case(), EnvelopeCase::Assertion(_)));
Source

pub fn add_attachment( &self, payload: impl EnvelopeEncodable, vendor: &str, conforms_to: Option<&str>, ) -> Self

Returns a new envelope with an added 'attachment': Envelope assertion.

This adds an attachment assertion to an existing envelope.

§Parameters
  • payload - The content of the attachment
  • vendor - A string that uniquely identifies the vendor (typically a reverse domain name)
  • conforms_to - An optional URI that identifies the format of the attachment
§Returns

A new envelope with the attachment assertion added

§Examples
use bc_envelope::prelude::*;

// Create a base envelope
let envelope = Envelope::new("User data").add_assertion("name", "Alice");

// Add an attachment
let with_attachment = envelope.add_attachment(
    "Vendor-specific metadata",
    "com.example",
    Some("https://example.com/metadata/v1"),
);

// The original envelope is unchanged
assert_eq!(envelope.assertions().len(), 1);

// The new envelope has an additional attachment assertion
assert_eq!(with_attachment.assertions().len(), 2);
assert!(
    with_attachment
        .assertions_with_predicate(known_values::ATTACHMENT)
        .len()
        > 0
);
Source§

impl Envelope

Methods for accessing attachments in envelopes

Source

pub fn attachment_payload(&self) -> Result<Self>

Returns the payload of an attachment envelope.

§Returns

The payload envelope

§Errors

Returns an error if the envelope is not a valid attachment envelope

Source

pub fn attachment_vendor(&self) -> Result<String>

Returns the vendor identifier of an attachment envelope.

§Returns

The vendor string

§Errors

Returns an error if the envelope is not a valid attachment envelope

Source

pub fn attachment_conforms_to(&self) -> Result<Option<String>>

Returns the optional conformsTo URI of an attachment envelope.

§Returns

The conformsTo string if present, or None

§Errors

Returns an error if the envelope is not a valid attachment envelope

Source

pub fn attachments_with_vendor_and_conforms_to( &self, vendor: Option<&str>, conforms_to: Option<&str>, ) -> Result<Vec<Self>>

Searches the envelope’s assertions for attachments that match the given vendor and conformsTo.

This method finds all attachment assertions in the envelope that match the specified criteria:

  • If vendor is None, matches any vendor
  • If conformsTo is None, matches any conformsTo value
  • If both are None, matches all attachments
§Parameters
  • vendor - Optional vendor identifier to match
  • conforms_to - Optional conformsTo URI to match
§Returns

A vector of matching attachment envelopes

§Errors

Returns an error if any of the envelope’s attachments are invalid

§Examples
use bc_envelope::prelude::*;

// Create an envelope with two attachments from the same vendor
let envelope = Envelope::new("Data")
    .add_attachment(
        "Attachment 1",
        "com.example",
        Some("https://example.com/format/v1"),
    )
    .add_attachment(
        "Attachment 2",
        "com.example",
        Some("https://example.com/format/v2"),
    );

// Find all attachments
let all_attachments = envelope.attachments().unwrap();
assert_eq!(all_attachments.len(), 2);

// Find attachments by vendor
let vendor_attachments = envelope
    .attachments_with_vendor_and_conforms_to(Some("com.example"), None)
    .unwrap();
assert_eq!(vendor_attachments.len(), 2);

// Find attachments by specific format
let v1_attachments = envelope
    .attachments_with_vendor_and_conforms_to(
        None,
        Some("https://example.com/format/v1"),
    )
    .unwrap();
assert_eq!(v1_attachments.len(), 1);
Source

pub fn attachments(&self) -> Result<Vec<Self>>

Returns all attachments in the envelope.

This is equivalent to calling attachments_with_vendor_and_conforms_to(None, None).

§Returns

A vector of all attachment envelopes

§Errors

Returns an error if any of the envelope’s attachments are invalid

Source

pub fn validate_attachment(&self) -> Result<()>

Validates that an envelope is a proper attachment envelope.

This ensures the envelope is an assertion envelope with the predicate attachment and the required structure for an attachment.

§Returns

Ok(()) if the envelope is a valid attachment envelope

§Errors

Returns EnvelopeError::InvalidAttachment if the envelope is not a valid attachment envelope

Source

pub fn attachment_with_vendor_and_conforms_to( &self, vendor: Option<&str>, conforms_to: Option<&str>, ) -> Result<Self>

Finds a single attachment matching the given vendor and conformsTo.

This works like attachments_with_vendor_and_conforms_to but returns a single attachment envelope rather than a vector. It requires that exactly one attachment matches the criteria.

§Parameters
  • vendor - Optional vendor identifier to match
  • conforms_to - Optional conformsTo URI to match
§Returns

The matching attachment envelope

§Errors
  • Returns EnvelopeError::NonexistentAttachment if no attachments match
  • Returns EnvelopeError::AmbiguousAttachment if more than one attachment matches
  • Returns an error if any of the envelope’s attachments are invalid
§Examples
use bc_envelope::prelude::*;

// Create an envelope with an attachment
let envelope = Envelope::new("Data").add_attachment(
    "Metadata",
    "com.example",
    Some("https://example.com/format/v1"),
);

// Find a specific attachment by vendor and format
let attachment = envelope
    .attachment_with_vendor_and_conforms_to(
        Some("com.example"),
        Some("https://example.com/format/v1"),
    )
    .unwrap();

// Access the attachment payload
let payload = attachment.attachment_payload().unwrap();
assert_eq!(payload.extract_subject::<String>().unwrap(), "Metadata");
Source§

impl Envelope

Support for compressing and decompressing envelopes.

Source

pub fn compress(&self) -> Result<Self>

Returns a compressed version of this envelope.

This method compresses the envelope using the DEFLATE algorithm, creating a more space-efficient representation while preserving the envelope’s digest and semantic content. The compressed envelope maintains the same digest as the original, ensuring compatibility with the envelope’s digest tree structure.

When an envelope is compressed, the entire envelope structure (including its subject and assertions) is compressed as a single unit. The compression preserves all the information but reduces the size of the serialized envelope.

§Returns

A Result containing the compressed envelope or an error.

§Errors
  • Returns EnvelopeError::AlreadyEncrypted if the envelope is already encrypted
  • Returns EnvelopeError::AlreadyElided if the envelope is already elided
  • May return various compression-related errors
§Examples
use bc_envelope::prelude::*;

// Create an envelope with some content
let text = "This is a fairly long text that will benefit from compression.
           The longer the text, the more effective compression becomes.
           DEFLATE works well on repetitive content like this.";
let envelope = Envelope::new(text);

// Compress the envelope
let compressed = envelope.compress().unwrap();

// Check that the compressed version has the same digest
assert_eq!(envelope.digest(), compressed.digest());

// Verify that the compressed version takes less space
assert!(compressed.to_cbor_data().len() < envelope.to_cbor_data().len());
Source

pub fn decompress(&self) -> Result<Self>

Returns the decompressed variant of this envelope.

This method reverses the compression process, restoring the envelope to its original decompressed form. The decompressed envelope will have the same digest as the compressed version.

§Returns

A Result containing the decompressed envelope or an error.

§Errors
  • Returns EnvelopeError::NotCompressed if the envelope is not compressed
  • Returns EnvelopeError::MissingDigest if the compressed envelope is missing its digest
  • Returns EnvelopeError::InvalidDigest if the decompressed data doesn’t match the expected digest
  • May return various decompression-related errors
§Examples
use bc_envelope::prelude::*;

// Create and compress an envelope
let original = Envelope::new("Hello, world!");
let compressed = original.compress().unwrap();

// Decompress it
let decompressed = compressed.decompress().unwrap();

// The decompressed envelope should match the original
assert_eq!(
    decompressed.extract_subject::<String>().unwrap(),
    "Hello, world!"
);
assert_eq!(decompressed.digest(), original.digest());

// Trying to decompress a non-compressed envelope fails
assert!(original.decompress().is_err());
Source

pub fn compress_subject(&self) -> Result<Self>

Returns this envelope with its subject compressed.

Unlike compress() which compresses the entire envelope, this method only compresses the subject of the envelope, leaving the assertions decompressed. This is useful when you want to compress a large subject while keeping the assertions readable and accessible.

§Returns

A Result containing a new envelope with a compressed subject, or an error.

§Errors

May return errors from the compression process.

§Examples
use bc_envelope::prelude::*;

// Create an envelope with a large subject and some assertions
let lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.";
let envelope = Envelope::new(lorem)
    .add_assertion("note", "This is a metadata note");

// Compress just the subject
let subject_compressed = envelope.compress_subject().unwrap();

// The envelope's digest is preserved
assert_eq!(envelope.digest(), subject_compressed.digest());

// The subject is now compressed
assert!(subject_compressed.subject().is_compressed());

// But the assertions are still directly accessible
let note = subject_compressed.object_for_predicate("note").unwrap();
assert_eq!(note.extract_subject::<String>().unwrap(), "This is a metadata note");
Source

pub fn decompress_subject(&self) -> Result<Self>

Returns this envelope with its subject decompressed.

This method reverses the effect of compress_subject(), decompressing the subject of the envelope while leaving the rest of the envelope unchanged.

§Returns

A Result containing a new envelope with an decompressed subject, or an error.

§Errors

May return errors from the decompression process.

§Examples
use bc_envelope::prelude::*;

// Create an envelope and compress its subject
let original =
    Envelope::new("Hello, world!").add_assertion("note", "Test note");
let compressed = original.compress_subject().unwrap();

// Verify the subject is compressed
assert!(compressed.subject().is_compressed());

// Decompress the subject
let decompressed = compressed.decompress_subject().unwrap();

// Verify the subject is now decompressed
assert!(!decompressed.subject().is_compressed());

// The content should match the original
assert_eq!(
    decompressed.extract_subject::<String>().unwrap(),
    "Hello, world!"
);
Source§

impl Envelope

Support for encrypting and decrypting envelopes using symmetric encryption.

This module extends Gordian Envelope with functions for symmetric encryption and decryption using the IETF-ChaCha20-Poly1305 construct. It enables privacy-enhancing operations by allowing envelope elements to be encrypted without changing the envelope’s digest, similar to elision.

The encryption process preserves the envelope’s digest tree structure, which means signatures, proofs, and other cryptographic artifacts remain valid even when parts of the envelope are encrypted.

§Examples

use bc_components::SymmetricKey;
use bc_envelope::prelude::*;

// Create an envelope
let envelope = Envelope::new("Hello world");

// Generate a symmetric key for encryption
let key = SymmetricKey::new();

// Encrypt the envelope's subject
let encrypted = envelope.encrypt_subject(&key).unwrap();

// The encrypted envelope has the same digest as the original
assert_eq!(envelope.digest(), encrypted.digest());

// The subject is now encrypted
assert!(encrypted.subject().is_encrypted());

// Decrypt the envelope
let decrypted = encrypted.decrypt_subject(&key).unwrap();

// The decrypted envelope is equivalent to the original
assert!(envelope.is_equivalent_to(&decrypted));

For encrypting the entire envelope including its assertions, you must first wrap the envelope:

use bc_components::SymmetricKey;
use bc_envelope::prelude::*;

// Create an envelope with assertions
let envelope = Envelope::new("Alice")
    .add_assertion("knows", "Bob")
    .add_assertion("knows", "Carol");

// Generate a symmetric key
let key = SymmetricKey::new();

// Encrypt the entire envelope (wrapper method does the wrapping for you)
let encrypted = envelope.encrypt(&key);

// Decrypt the entire envelope
let decrypted = encrypted.decrypt(&key).unwrap();

// The decrypted envelope is equivalent to the original
assert!(envelope.is_equivalent_to(&decrypted));
Source

pub fn encrypt_subject(&self, key: &SymmetricKey) -> Result<Self>

Returns a new envelope with its subject encrypted.

Encrypts only the subject of the envelope, leaving assertions unencrypted. To encrypt an entire envelope including its assertions, it must first be wrapped using the wrap() method, or you can use the encrypt() convenience method.

The encryption uses ChaCha20-Poly1305 and preserves the envelope’s digest, allowing for features like selective disclosure and signature verification to work even on encrypted envelopes.

§Parameters
  • key - The SymmetricKey to use for encryption
§Returns

A new envelope with its subject encrypted

§Errors

Returns an error if the envelope is already encrypted or elided

Source

pub fn decrypt_subject(&self, key: &SymmetricKey) -> Result<Self>

Returns a new envelope with its subject decrypted.

Decrypts the subject of an envelope that was previously encrypted using encrypt_subject(). The symmetric key used must be the same one used for encryption.

§Parameters
  • key - The SymmetricKey to use for decryption
§Returns

A new envelope with its subject decrypted

§Errors
  • Returns an error if the envelope’s subject is not encrypted
  • Returns an error if the key is incorrect
  • Returns an error if the digest of the decrypted envelope doesn’t match the expected digest
Source§

impl Envelope

Source

pub fn encrypt(&self, key: &SymmetricKey) -> Envelope

Convenience method to encrypt an entire envelope including its assertions.

This method wraps the envelope and then encrypts its subject, which has the effect of encrypting the entire original envelope including all its assertions.

§Parameters
  • key - The SymmetricKey to use for encryption
§Returns

A new envelope with the entire original envelope encrypted as its subject

§Examples
use bc_components::SymmetricKey;
use bc_envelope::prelude::*;

// Create an envelope with assertions
let envelope = Envelope::new("Alice").add_assertion("knows", "Bob");

// Generate a symmetric key
let key = SymmetricKey::new();

// Encrypt the entire envelope
let encrypted = envelope.encrypt(&key);
Source

pub fn decrypt(&self, key: &SymmetricKey) -> Result<Envelope>

Convenience method to decrypt an entire envelope that was encrypted using the encrypt() method.

This method decrypts the subject and then unwraps the resulting envelope, returning the original envelope with all its assertions.

§Parameters
  • key - The SymmetricKey to use for decryption
§Returns

The original decrypted envelope

§Errors
  • Returns an error if the envelope is not encrypted
  • Returns an error if the key is incorrect
  • Returns an error if the digest of the decrypted envelope doesn’t match the expected digest
  • Returns an error if the decrypted envelope cannot be unwrapped
§Examples
use bc_components::SymmetricKey;
use bc_envelope::prelude::*;

// Create an envelope with assertions
let envelope = Envelope::new("Alice").add_assertion("knows", "Bob");

// Generate a symmetric key
let key = SymmetricKey::new();

// Encrypt and then decrypt the entire envelope
let encrypted = envelope.encrypt(&key);
let decrypted = encrypted.decrypt(&key).unwrap();

// The decrypted envelope is equivalent to the original
assert!(envelope.is_equivalent_to(&decrypted));
Source§

impl Envelope

Source

pub fn unknown() -> Self

Creates an envelope containing the ‘Unknown’ known value.

This is used when representing an unknown error or value.

Source

pub fn ok() -> Self

Creates an envelope containing the ‘OK’ known value.

This is used when a response doesn’t need to return any specific value, just an acknowledgment that the request was successful.

Source§

impl Envelope

§Inclusion Proofs

Inclusion proofs allow a holder of an envelope to prove that specific elements exist within the envelope without revealing the entire contents. This is particularly useful for selective disclosure of information in privacy-preserving scenarios.

The inclusion proof mechanism leverages the Merkle-like digest tree structure of envelopes:

  • The holder creates a minimal structure containing only the digests necessary to validate the proof
  • A verifier with a trusted root digest can confirm that the specific elements exist in the original envelope
  • All other content can remain elided, preserving privacy

For enhanced privacy, elements can be salted to prevent correlation attacks.

§Examples
§Basic Inclusion Proof
use std::collections::HashSet;

use bc_envelope::prelude::*;

// Create an envelope with multiple assertions
let alice_friends = Envelope::new("Alice")
    .add_assertion("knows", "Bob")
    .add_assertion("knows", "Carol")
    .add_assertion("knows", "Dan");

// Create a representation of just the root digest
let alice_friends_root = alice_friends.elide_revealing_set(&HashSet::new());

// Create the target we want to prove exists
let knows_bob_assertion = Envelope::new_assertion("knows", "Bob");

// Generate a proof that Alice knows Bob
let alice_knows_bob_proof = alice_friends
    .proof_contains_target(&knows_bob_assertion)
    .unwrap();

// A third party can verify the proof against the trusted root
assert!(
    alice_friends_root.confirm_contains_target(
        &knows_bob_assertion,
        &alice_knows_bob_proof
    )
);
§Enhanced Privacy with Salting
use std::collections::HashSet;

use bc_envelope::prelude::*;

// Create an envelope with salted assertions for enhanced privacy
let alice_friends = Envelope::new("Alice")
    .add_assertion_salted("knows", "Bob", true)
    .add_assertion_salted("knows", "Carol", true)
    .add_assertion_salted("knows", "Dan", true);

// Create a representation of just the root digest
let alice_friends_root = alice_friends.elide_revealing_set(&HashSet::new());

// Create the target we want to prove exists
let knows_bob_assertion = Envelope::new_assertion("knows", "Bob");

// Generate a proof that Alice knows Bob
let alice_knows_bob_proof = alice_friends
    .proof_contains_target(&knows_bob_assertion)
    .unwrap();

// A third party can verify the proof against the trusted root
// Note: The salting prevents the third party from guessing other friends
// by simple correlation attacks
assert!(
    alice_friends_root.confirm_contains_target(
        &knows_bob_assertion,
        &alice_knows_bob_proof
    )
);
Source

pub fn proof_contains_set( &self, target: &HashSet<Digest, RandomState>, ) -> Option<Envelope>

Creates a proof that this envelope includes every element in the target set.

An inclusion proof is a specially constructed envelope that:

  • Has the same digest as the original envelope (or an elided version of it)
  • Contains the minimal structure needed to prove the existence of target elements
  • Keeps all other content elided to preserve privacy
§Parameters
  • target: The set of digests representing elements that the proof must include.
§Returns
  • Some(Envelope): A proof envelope if all targets can be proven to exist
  • None: If it cannot be proven that the envelope contains every element in the target set
§Example
use std::collections::HashSet;

use bc_envelope::prelude::*;

// Create a document with multiple assertions
let document = Envelope::new("Document")
    .add_assertion("title", "Important Report")
    .add_assertion("author", "Alice")
    .add_assertion("confidential", true);

// Create a set of elements we want to prove exist
let title_assertion = Envelope::new_assertion("title", "Important Report");
let author_assertion = Envelope::new_assertion("author", "Alice");

let mut target_set = HashSet::new();
target_set.insert(title_assertion.digest());
target_set.insert(author_assertion.digest());

// Generate a proof for multiple elements
let proof = document.proof_contains_set(&target_set).unwrap();

// The proof can be verified against the document's root digest
let document_root = document.elide_revealing_set(&HashSet::new());
assert!(document_root.confirm_contains_set(&target_set, &proof));
Source

pub fn proof_contains_target( &self, target: &dyn DigestProvider, ) -> Option<Envelope>

Creates a proof that this envelope includes the single target element.

This is a convenience method that wraps proof_contains_set() for the common case of proving the existence of just one element.

§Parameters
  • target: The element that the proof must demonstrate exists in this envelope.
§Returns
  • Some(Envelope): A proof envelope if the target can be proven to exist
  • None: If it cannot be proven that the envelope contains the target element
§Example
use std::collections::HashSet;

use bc_envelope::prelude::*;

// Create a credential with various attributes
let credential = Envelope::new("Credential")
    .add_assertion("firstName", "John")
    .add_assertion("lastName", "Smith")
    .add_assertion("birthDate", "1990-01-01")
    .add_assertion("address", "123 Main St")
    .add_assertion("documentNumber", "ABC123456");

// Create a trusted root digest
let credential_root = credential.elide_revealing_set(&HashSet::new());

// The holder wants to prove just their name without revealing other details
let first_name = Envelope::new_assertion("firstName", "John");

// Generate a proof for the first name
let proof = credential.proof_contains_target(&first_name).unwrap();

// A verifier can confirm the proof is valid
assert!(credential_root.confirm_contains_target(&first_name, &proof));
Source

pub fn confirm_contains_set( &self, target: &HashSet<Digest, RandomState>, proof: &Envelope, ) -> bool

Verifies whether this envelope contains all elements in the target set using the given inclusion proof.

This method is used by a verifier to check if a proof demonstrates the existence of all target elements within this envelope. The verification succeeds only if:

  1. The proof’s digest matches this envelope’s digest
  2. The proof contains all the target elements
§Parameters
  • target: The set of digests representing elements that need to be proven to exist.
  • proof: The inclusion proof envelope to verify.
§Returns
  • true: If all target elements are proven to exist in this envelope by the proof
  • false: Otherwise
§Example
use std::collections::HashSet;

use bc_envelope::prelude::*;

// A verifier has a trusted root digest of a document
let document = Envelope::new("Document")
    .add_assertion("title", "Report")
    .add_assertion("author", "Alice");
let document_root = document.elide_revealing_set(&HashSet::new());

// Create a set of elements we want to verify
let author_assertion = Envelope::new_assertion("author", "Alice");
let mut target_set = HashSet::new();
target_set.insert(author_assertion.digest());

// The holder provides a proof
let proof = document.proof_contains_set(&target_set).unwrap();

// The verifier confirms the proof is valid
assert!(document_root.confirm_contains_set(&target_set, &proof));
Source

pub fn confirm_contains_target( &self, target: &dyn DigestProvider, proof: &Envelope, ) -> bool

Verifies whether this envelope contains the single target element using the given inclusion proof.

This is a convenience method that wraps confirm_contains_set() for the common case of verifying just one element.

§Parameters
  • target: The element that needs to be proven to exist in this envelope.
  • proof: The inclusion proof envelope to verify.
§Returns
  • true: If the target element is proven to exist in this envelope by the proof
  • false: Otherwise
§Example
use std::collections::HashSet;

use bc_envelope::prelude::*;

// A verifier has a trusted root digest of a credential
let credential = Envelope::new("Credential")
    .add_assertion("isOver21", true)
    .add_assertion("licenseNumber", "DL12345678");
let credential_root = credential.elide_revealing_set(&HashSet::new());

// The element to be verified
let is_over_21 = Envelope::new_assertion("isOver21", true);

// The holder provides a proof
let proof = credential.proof_contains_target(&is_over_21).unwrap();

// The verifier confirms the proof shows the person is over 21
// without revealing their license number
assert!(credential_root.confirm_contains_target(&is_over_21, &proof));
Source§

impl Envelope

Support for public key encryption.

Source

pub fn add_recipient( &self, recipient: &dyn Encrypter, content_key: &SymmetricKey, ) -> Self

Returns a new envelope with an added hasRecipient: SealedMessage assertion.

This method adds a recipient to an already-encrypted envelope. It creates a hasRecipient assertion containing a SealedMessage that holds the content key encrypted to the recipient’s public key.

§Parameters
  • recipient - The public keys of the recipient that will be able to decrypt the envelope
  • content_key - The symmetric key that was used to encrypt the envelope’s subject
§Returns

A new envelope with the recipient assertion added

§Example
use bc_components::{PublicKeysProvider, SymmetricKey};
use bc_envelope::prelude::*;

let bob_keys = bc_components::PrivateKeyBase::new();

// Create and encrypt the envelope
let content_key = SymmetricKey::new();
let envelope = Envelope::new("Secret message")
    .encrypt_subject(&content_key)
    .unwrap()
    .add_recipient(&bob_keys.public_keys(), &content_key);

// Format of the envelope shows the hasRecipient assertion
assert!(envelope.format().contains("hasRecipient"));
Source

pub fn recipients(&self) -> Result<Vec<SealedMessage>>

Returns all SealedMessages from the envelope’s hasRecipient assertions.

This method extracts all the SealedMessage objects attached to the envelope as hasRecipient assertions. Each SealedMessage contains the content key encrypted to a particular recipient’s public key.

§Returns

A vector of SealedMessage objects, one for each recipient

§Errors

Returns an error if any hasRecipient assertion does not have a SealedMessage as its object, or if the object is obscured (elided or encrypted).

§Example
use bc_components::{PublicKeysProvider, SymmetricKey};
use bc_envelope::prelude::*;

let bob_keys = bc_components::PrivateKeyBase::new();
let carol_keys = bc_components::PrivateKeyBase::new();

// Create envelope with multiple recipients
let content_key = SymmetricKey::new();
let envelope = Envelope::new("Secret message")
    .encrypt_subject(&content_key)
    .unwrap()
    .add_recipient(&bob_keys.public_keys(), &content_key)
    .add_recipient(&carol_keys.public_keys(), &content_key);

// Get all recipient sealed messages
let sealed_messages = envelope.recipients().unwrap();
assert_eq!(sealed_messages.len(), 2);
Source

pub fn encrypt_subject_to_recipients( &self, recipients: &[&dyn Encrypter], ) -> Result<Self>

Encrypts the envelope’s subject and adds recipient assertions for multiple recipients.

This is a convenience method that handles the complete process of:

  1. Generating a random symmetric key (the content key)
  2. Encrypting the envelope’s subject with this key
  3. Encrypting the content key to each recipient’s public key
  4. Adding a hasRecipient assertion for each recipient
§Parameters
  • recipients - An array of public keys, one for each potential recipient
§Returns

A new envelope with encrypted subject and recipient assertions

§Errors

Returns an error if the envelope’s subject is already encrypted or cannot be encrypted for any other reason.

§Example
use bc_envelope::prelude::*;
use bc_components::PublicKeysProvider;

let bob_keys = bc_components::PrivateKeyBase::new();
let carol_keys = bc_components::PrivateKeyBase::new();

// Create and encrypt the envelope to both Bob and Carol
let envelope = Envelope::new("Shared secret");
let encrypted = envelope.encrypt_subject_to_recipients(
    &[&bob_keys.public_keys(), &carol_keys.public_keys()]
).unwrap();

// The envelope is now encrypted
assert_eq!(encrypted.format(), "ENCRYPTED [\n    'hasRecipient': SealedMessage\n    'hasRecipient': SealedMessage\n]");
Source

pub fn encrypt_subject_to_recipient( &self, recipient: &dyn Encrypter, ) -> Result<Self>

Encrypts the envelope’s subject and adds a recipient assertion for a single recipient.

This is a convenience method that handles the complete process of:

  1. Generating a random symmetric key (the content key)
  2. Encrypting the envelope’s subject with this key
  3. Encrypting the content key to the recipient’s public key
  4. Adding a hasRecipient assertion for the recipient
§Parameters
  • recipient - The public keys of the recipient who will be able to decrypt the envelope
§Returns

A new envelope with encrypted subject and recipient assertion

§Errors

Returns an error if the envelope’s subject is already encrypted or cannot be encrypted for any other reason.

§Example
use bc_components::PublicKeysProvider;
use bc_envelope::prelude::*;

let bob_keys = bc_components::PrivateKeyBase::new();

// Create and encrypt the envelope to Bob
let envelope = Envelope::new("Secret message");
let encrypted = envelope
    .encrypt_subject_to_recipient(&bob_keys.public_keys())
    .unwrap();

// The envelope is now encrypted with a recipient
assert!(encrypted.format().contains("hasRecipient"));
Source

pub fn decrypt_subject_to_recipient( &self, recipient: &dyn Decrypter, ) -> Result<Self>

Decrypts an envelope’s subject using the recipient’s private key.

This method:

  1. Finds and extracts all SealedMessage objects from hasRecipient assertions
  2. Tries to decrypt each one with the provided private key until successful
  3. Extracts the content key from the decrypted message
  4. Uses the content key to decrypt the envelope’s subject
§Parameters
  • recipient - The private key of the recipient trying to decrypt the envelope
§Returns

A new envelope with decrypted subject

§Errors

Returns an error if:

  • No hasRecipient assertions containing SealedMessage objects are found
  • None of the sealed messages can be decrypted with the provided private key
  • The envelope’s subject cannot be decrypted with the extracted content key
§Example
use bc_components::PublicKeysProvider;
use bc_envelope::prelude::*;

let bob_keys = bc_components::PrivateKeyBase::new();

// Create and encrypt the envelope to Bob
let envelope = Envelope::new("Secret message")
    .encrypt_subject_to_recipient(&bob_keys.public_keys())
    .unwrap();

// Bob decrypts it with his private key
let decrypted = envelope.decrypt_subject_to_recipient(&bob_keys).unwrap();

assert_eq!(
    decrypted.extract_subject::<String>().unwrap(),
    "Secret message"
);
Source§

impl Envelope

Convenience methods for recipient-based encryption and decryption.

These methods provide simplified versions of the recipient encryption and decryption operations with a more intuitive API for common use cases.

Source

pub fn encrypt_to_recipient(&self, recipient: &dyn Encrypter) -> Envelope

Wraps and encrypts an envelope to a single recipient.

This is a convenience method that:

  1. Wraps the envelope (preserving its assertions in the wrap)
  2. Encrypts the resulting envelope to the recipient

This method is simpler than calling wrap() and then encrypt_subject_to_recipient() separately, and it handles error unwrapping.

§Parameters
  • recipient - The public keys of the recipient who will be able to decrypt the envelope
§Returns

A new envelope that wraps and encrypts the original envelope to the recipient

§Example
use bc_components::PublicKeysProvider;
use bc_envelope::prelude::*;

let bob_keys = bc_components::PrivateKeyBase::new();

// Create an envelope with some assertions
let envelope = Envelope::new("Alice")
    .add_assertion("knows", "Bob")
    .add_assertion("age", 30);

// Wrap and encrypt it to Bob in one step
let encrypted = envelope.encrypt_to_recipient(&bob_keys.public_keys());

// The format shows it's encrypted but doesn't reveal the content
assert_eq!(
    encrypted.format(),
    "ENCRYPTED [\n    'hasRecipient': SealedMessage\n]"
);
Source

pub fn decrypt_to_recipient( &self, recipient: &dyn Decrypter, ) -> Result<Envelope>

Decrypts an envelope that was encrypted to a recipient and unwraps it.

This is a convenience method that:

  1. Decrypts the envelope using the recipient’s private key
  2. Unwraps the resulting envelope to reveal the original content

This method is simpler than calling decrypt_subject_to_recipient() and then try_unwrap() separately.

§Parameters
  • recipient - The private key of the recipient trying to decrypt the envelope
§Returns

The original, unwrapped envelope

§Errors

Returns an error if:

  • The envelope cannot be decrypted with the recipient’s private key
  • The decrypted envelope is not a wrapped envelope
§Example
use bc_components::PublicKeysProvider;
use bc_envelope::prelude::*;

let bob_keys = bc_components::PrivateKeyBase::new();

// Create an envelope with assertions and encrypt it to Bob
let original = Envelope::new("Alice")
    .add_assertion("knows", "Bob")
    .add_assertion("age", 30);

let encrypted = original.encrypt_to_recipient(&bob_keys.public_keys());

// Bob decrypts it with his private key and unwraps it
let decrypted = encrypted.decrypt_to_recipient(&bob_keys).unwrap();

// The decrypted envelope should match the original
assert!(decrypted.is_identical_to(&original));
Source§

impl Envelope

Support for signing envelopes and verifying signatures.

This implementation provides methods for digitally signing envelopes and verifying signatures. It supports both basic signatures and signatures with metadata, as well as multi-signature scenarios.

Source

pub fn add_signature(&self, private_key: &dyn Signer) -> Self

Creates a signature for the envelope’s subject and returns a new envelope with a 'signed': Signature assertion.

  • Parameters:

    • private_key: The signer’s SigningPrivateKey
  • Returns: The signed envelope.

Source

pub fn make_signed_assertion( &self, signature: &Signature, note: Option<&str>, ) -> Self

Convenience constructor for a 'signed': Signature assertion envelope.

  • Parameters:

    • signature: The Signature for the object.
    • note: An optional note to be added to the Signature.
  • Returns: The new assertion envelope.

Source

pub fn is_verified_signature( &self, signature: &Signature, public_key: &dyn Verifier, ) -> bool

Returns whether the given signature is valid.

  • Parameters:

    • signature: The Signature to be checked.
    • public_key: The potential signer’s Verifier.
  • Returns: true if the signature is valid for this envelope’s subject, false otherwise.

Source

pub fn verify_signature( &self, signature: &Signature, public_key: &dyn Verifier, ) -> Result<Self>

Checks whether the given signature is valid for the given public key.

Used for chaining a series of operations that include validating signatures.

  • Parameters:

    • signature: The Signature to be checked.
    • public_key: The potential signer’s Verifier.
  • Returns: This envelope.

  • Throws: Throws EnvelopeError.unverifiedSignature if the signature is not valid. valid.

Source

pub fn has_signature_from(&self, public_key: &dyn Verifier) -> Result<bool>

Returns whether the envelope’s subject has a valid signature from the given public key.

  • Parameters:

    • public_key: The potential signer’s Verifier.
  • Returns: true if any signature is valid for this envelope’s subject, false otherwise.

  • Throws: Throws an exception if any 'signed' assertion doesn’t contain a valid Signature as its object.

Source

pub fn has_signature_from_returning_metadata( &self, public_key: &dyn Verifier, ) -> Result<Option<Envelope>>

Returns whether the envelope’s subject has a valid signature from the given public key by returning the signature metadata.

  • Parameters:

  • public_key: The potential signer’s Verifier.

  • Returns: The metadata envelope if the signature is valid, None otherwise.

Source

pub fn verify_signature_from(&self, public_key: &dyn Verifier) -> Result<Self>

Returns whether the envelope’s subject has a valid signature from the given public key.

Used for chaining a series of operations that include validating signatures.

  • Parameters:

    • public_key: The potential signer’s Verifier.
  • Returns: This envelope.

  • Throws: Throws EnvelopeError.unverifiedSignature if the signature is not valid. valid.

Source

pub fn verify_signature_from_returning_metadata( &self, public_key: &dyn Verifier, ) -> Result<Envelope>

Source

pub fn has_signatures_from(&self, public_keys: &[&dyn Verifier]) -> Result<bool>

Checks whether the envelope’s subject has a set of signatures.

Source

pub fn has_signatures_from_threshold( &self, public_keys: &[&dyn Verifier], threshold: Option<usize>, ) -> Result<bool>

Returns whether the envelope’s subject has some threshold of signatures.

If threshold is nil, then all signers in public_keys must have signed. If threshold is 1, then at least one signer must have signed.

  • Parameters:

    • public_keys: An array of potential signers’ Verifiers.
    • threshold: Optional minimum number of signers.
  • Returns: true if the threshold of valid signatures is met, false otherwise.

  • Throws: Throws an exception if any 'signed' assertion doesn’t contain a valid Signature as its object.

Source

pub fn verify_signatures_from_threshold( &self, public_keys: &[&dyn Verifier], threshold: Option<usize>, ) -> Result<Self>

Checks whether the envelope’s subject has some threshold of signatures.

If threshold is nil, then all signers in public_keys must have signed. If threshold is 1, then at least one signer must have signed.

Used for chaining a series of operations that include validating signatures.

  • Parameters:

    • public_keys: An array of potential signers’ Verifiers.
    • threshold: Optional minimum number of signers.
  • Returns: This envelope.

  • Throws: Throws an exception if the threshold of valid signatures is not met.

Source

pub fn verify_signatures_from( &self, public_keys: &[&dyn Verifier], ) -> Result<Self>

Checks whether the envelope’s subject has a set of signatures.

Source§

impl Envelope

Convenience methods for signing and verifying envelopes.

These methods provide a simpler API for common signature operations, particularly for signing entire envelopes by automatically wrapping them.

Source

pub fn sign(&self, signer: &dyn Signer) -> Envelope

Signs the entire envelope (subject and assertions) by wrapping it first.

This is a convenience method that wraps the envelope before signing, ensuring that all assertions are included in the signature, not just the subject.

§Parameters
  • signer - The signer that will produce the signature.
§Returns

A new envelope with the wrapped envelope as subject and a signature assertion.

Source

pub fn sign_opt( &self, signer: &dyn Signer, options: Option<SigningOptions>, ) -> Envelope

Signs the entire envelope with options but no metadata.

This is a convenience method that wraps the envelope before signing with the specified options.

§Parameters
  • signer - The signer that will produce the signature.
  • options - Optional signing options to customize the signature generation.
§Returns

A new envelope with the wrapped envelope as subject and a signature assertion.

Source

pub fn verify(&self, verifier: &dyn Verifier) -> Result<Envelope>

Verifies that the envelope has a valid signature from the specified verifier.

This method assumes the envelope is wrapped (i.e., was signed using sign() rather than add_signature()), and unwraps it after verification.

§Parameters
  • verifier - The verifier to check the signature against.
§Returns

The unwrapped envelope if verification succeeds, otherwise an error.

§Errors

Returns an error if the signature verification fails or if the envelope cannot be unwrapped.

Source

pub fn verify_returning_metadata( &self, verifier: &dyn Verifier, ) -> Result<(Envelope, Envelope)>

Verifies the envelope’s signature and returns both the unwrapped envelope and signature metadata.

This method verifies that the envelope has a valid signature from the specified verifier, then unwraps it and returns both the envelope and any metadata associated with the signature.

§Parameters
  • verifier - The verifier to check the signature against.
§Returns

A tuple containing the unwrapped envelope and the signature metadata envelope if verification succeeds, otherwise an error.

§Errors

Returns an error if the signature verification fails or if the envelope cannot be unwrapped.

Source§

impl Envelope

Support for decorrelation of envelopes using salt.

Source

pub fn add_salt(&self) -> Self

Adds a proportionally-sized salt assertion to decorrelate the envelope.

This method adds random salt bytes as an assertion to the envelope. The size of the salt is proportional to the size of the envelope being salted:

  • For small envelopes: 8-16 bytes
  • For larger envelopes: 5-25% of the envelope’s size

Salt is added as an assertion with the predicate ‘salt’ (a known value) and an object containing random bytes. This changes the digest of the envelope while preserving its semantic content, making it impossible to correlate with other envelopes containing the same information.

§Returns

A new envelope with the salt assertion added.

§Examples
use bc_envelope::prelude::*;

// Create an envelope with personally identifiable information
let alice = Envelope::new("Alice")
    .add_assertion("email", "alice@example.com")
    .add_assertion("ssn", "123-45-6789");

// Create a second envelope with the same information
let alice2 = Envelope::new("Alice")
    .add_assertion("email", "alice@example.com")
    .add_assertion("ssn", "123-45-6789");

// The envelopes have the same digest because they contain the same information
assert_eq!(alice.digest(), alice2.digest());

// Add salt to both envelopes
let alice_salted = alice.add_salt();
let alice2_salted = alice2.add_salt();

// Now the envelopes have different digests, preventing correlation
assert_ne!(alice_salted.digest(), alice2_salted.digest());

// When elided, the salted envelopes still can't be correlated
assert_ne!(alice_salted.elide().digest(), alice2_salted.elide().digest());
Source

pub fn add_salt_instance(&self, salt: Salt) -> Self

Adds the given Salt as an assertion to the envelope.

This method attaches a pre-existing Salt object as an assertion to the envelope, using the known value ‘salt’ as the predicate. This is useful when you need to control the specific salt content being added.

§Parameters
  • salt - A Salt object containing random bytes
§Returns

A new envelope with the salt assertion added.

§Examples
use bc_components::Salt;
use bc_envelope::prelude::*;

// Create a salt with specific bytes
let salt = Salt::from_data(vec![1, 2, 3, 4, 5, 6, 7, 8]);

// Add this specific salt to an envelope
let envelope = Envelope::new("Hello");
let salted = envelope.add_salt_instance(salt);

// The envelope now contains the salt assertion
assert!(salted.format().contains("'salt': Salt"));
Source

pub fn add_salt_with_len(&self, count: usize) -> Result<Self>

Adds salt of a specific byte length to the envelope.

This method adds salt of a specified number of bytes to decorrelate the envelope. It requires that the byte count be at least 8 bytes (64 bits) to ensure sufficient entropy for effective decorrelation.

§Parameters
  • count - The exact number of salt bytes to add
§Returns

A Result containing the new envelope with salt added, or an error if the byte count is less than the minimum (8 bytes).

§Errors

Returns an error if the specified byte count is less than 8.

§Examples
use bc_envelope::prelude::*;

let envelope = Envelope::new("Hello");

// Add exactly 16 bytes of salt
let salted = envelope.add_salt_with_len(16).unwrap();

// Trying to add less than 8 bytes will result in an error
assert!(envelope.add_salt_with_len(7).is_err());
Source

pub fn add_salt_in_range(&self, range: RangeInclusive<usize>) -> Result<Self>

Adds salt with a byte length randomly chosen from the given range.

This method adds salt with a length randomly selected from the specified range to decorrelate the envelope. This approach provides additional decorrelation by varying the size of the salt itself.

§Parameters
  • range - The inclusive range of byte lengths to choose from
§Returns

A Result containing the new envelope with salt added, or an error if the minimum value of the range is less than 8 bytes.

§Errors

Returns an error if the minimum of the range is less than 8.

§Examples
use std::ops::RangeInclusive;

use bc_envelope::prelude::*;

let envelope = Envelope::new("Hello");

// Add salt with a length randomly chosen between 16 and 32 bytes
let salted = envelope.add_salt_in_range(16..=32).unwrap();

// Trying to use a range with minimum less than 8 will result in an error
assert!(envelope.add_salt_in_range(4..=16).is_err());
Source§

impl Envelope

Source

pub fn lock_subject( &self, method: KeyDerivationMethod, secret: impl AsRef<[u8]>, ) -> Result<Self>

Source

pub fn unlock_subject(&self, secret: impl AsRef<[u8]>) -> Result<Self>

Source

pub fn is_locked_with_password(&self) -> bool

Source

pub fn is_locked_with_ssh_agent(&self) -> bool

Source

pub fn add_secret( &self, method: KeyDerivationMethod, secret: impl AsRef<[u8]>, content_key: &SymmetricKey, ) -> Result<Self>

Source§

impl Envelope

Source

pub fn lock( &self, method: KeyDerivationMethod, secret: impl AsRef<[u8]>, ) -> Result<Self>

Source

pub fn unlock(&self, secret: impl AsRef<[u8]>) -> Result<Self>

Source§

impl Envelope

Support for splitting and combining envelopes using SSKR (Shamir’s Secret Sharing).

This module extends Gordian Envelope with functions to support Sharded Secret Key Reconstruction (SSKR), which is an implementation of Shamir’s Secret Sharing. SSKR allows splitting a secret (in this case, a symmetric encryption key) into multiple shares, with a threshold required for reconstruction.

SSKR provides social recovery for encrypted envelopes by allowing the owner to distribute shares to trusted individuals or storage locations, with a specified threshold required to reconstruct the original envelope.

§How SSKR Works with Envelopes

The overall process is as follows:

  1. A Gordian Envelope is encrypted with a symmetric key
  2. The symmetric key is split into multiple SSKR shares using a group threshold and member thresholds
  3. Each share is added as an assertion to a copy of the encrypted envelope
  4. These envelope copies are distributed to trusted individuals or storage locations
  5. Later, when enough shares are brought together, the original envelope can be reconstructed

Sharded Secret Key Reconstruction (SSKR) for Envelopes.

For a complete working example, see the sskr_split() and sskr_join() method documentation.

Source

pub fn sskr_split( &self, spec: &SSKRSpec, content_key: &SymmetricKey, ) -> Result<Vec<Vec<Envelope>>>

Splits the envelope into a set of SSKR shares.

This method splits the symmetric key used to encrypt the envelope into SSKR shares, and returns multiple copies of the original envelope, each with a different SSKR share added as an assertion. The envelope subject should already be encrypted with the provided content_key.

The returned structure is a nested array that preserves the group structure of the SSKR shares. Each outer array represents a group, and each inner array contains the shares for that group.

§Parameters
  • spec - The SSKR specification that defines the group structure and thresholds
  • content_key - The symmetric key that was used to encrypt the envelope
§Returns

A nested array of envelopes organized by groups, each envelope containing the original encrypted envelope with a unique SSKR share added as an assertion

§Errors

Returns an error if the SSKR shares cannot be generated

§Examples
use bc_envelope::prelude::*;
use bc_components::{SymmetricKey, SSKRGroupSpec, SSKRSpec};

// Create and encrypt an envelope
let envelope = Envelope::new("Secret data").encrypt(&SymmetricKey::new());

// Define a 2-of-3 SSKR split
let group_spec = SSKRGroupSpec::new(2, 3).unwrap();
let spec = SSKRSpec::new(1, vec![group_spec]).unwrap();

// Create a symmetric key for the encrypted content
let content_key = SymmetricKey::new();

// Split the envelope into shares
let shares = envelope.sskr_split(&spec, &content_key).unwrap();

// The outer array represents groups (in this case, a single group)
assert_eq!(shares.len(), 1);

// The inner array contains the shares for the group (3 shares in this example)
assert_eq!(shares[0].len(), 3);

// Each share is an envelope with an 'sskrShare' assertion
for share in &shares[0] {
    assert!(share.assertions_with_predicate(known_values::SSKR_SHARE).len() > 0);
}
Source

pub fn sskr_split_flattened( &self, spec: &SSKRSpec, content_key: &SymmetricKey, ) -> Result<Vec<Envelope>>

Splits the envelope into a flattened set of SSKR shares.

This method works like sskr_split() but returns a flat array of all shares rather than preserving the group structure. This is convenient when the group structure is not needed for distribution.

§Parameters
  • spec - The SSKR specification that defines the group structure and thresholds
  • content_key - The symmetric key that was used to encrypt the envelope
§Returns

A flat array of all envelopes containing SSKR shares

§Errors

Returns an error if the SSKR shares cannot be generated

§Examples
use bc_components::{SSKRGroupSpec, SSKRSpec, SymmetricKey};
use bc_envelope::prelude::*;

// Create and encrypt an envelope
let envelope = Envelope::new("Secret data").encrypt(&SymmetricKey::new());

// Define a 2-of-3 SSKR split in a single group
let group_spec = SSKRGroupSpec::new(2, 3).unwrap();
let spec = SSKRSpec::new(1, vec![group_spec]).unwrap();

// Create a symmetric key for the encrypted content
let content_key = SymmetricKey::new();

// Split the envelope into a flat array of shares
let shares = envelope.sskr_split_flattened(&spec, &content_key).unwrap();

// We get all 3 shares in a flat array
assert_eq!(shares.len(), 3);

// Each share is an envelope with an 'sskrShare' assertion
for share in &shares {
    assert!(
        share
            .assertions_with_predicate(known_values::SSKR_SHARE)
            .len()
            > 0
    );
}
Source

pub fn sskr_join(envelopes: &[&Envelope]) -> Result<Envelope>

Reconstructs the original envelope from a set of SSKR shares.

Given a set of envelopes with SSKR share assertions, this method attempts to combine the shares to reconstruct the original symmetric key. If successful, it uses the key to decrypt the envelope and return the original envelope subject.

The method will try all combinations of shares with matching identifiers to find a valid reconstruction.

§Parameters
  • envelopes - An array of envelope references containing SSKR shares
§Returns

The original envelope if reconstruction is successful

§Errors
  • Returns EnvelopeError::InvalidShares if not enough valid shares are provided
  • Returns various errors if decryption fails
§Examples
use bc_envelope::prelude::*;
use bc_components::{SymmetricKey, SSKRGroupSpec, SSKRSpec};

// Create the original envelope with an assertion
let original = Envelope::new("Secret message")
    .add_assertion("metadata", "This is a test");

// Create a content key
let content_key = SymmetricKey::new();

// Wrap the envelope (so the whole envelope including its assertions
// become the subject)
let wrapped_original = original
    .wrap();

// Encrypt the wrapped envelope
let encrypted = wrapped_original
    .encrypt_subject(&content_key).unwrap();

// Create a 2-of-3 SSKR split specification
let group = SSKRGroupSpec::new(2, 3).unwrap();
let spec = SSKRSpec::new(1, vec![group]).unwrap();

// Split the encrypted envelope into shares
let shares = encrypted.sskr_split(&spec, &content_key).unwrap();
assert_eq!(shares[0].len(), 3);

// The shares would normally be distributed to different people/places
// For recovery, we need at least the threshold number of shares (2 in this case)
let share1 = &shares[0][0];
let share2 = &shares[0][1];

// Combine the shares to recover the original decrypted envelope
let recovered_wrapped = Envelope::sskr_join(&[share1, share2]).unwrap();

// Unwrap the envelope to get the original envelope
let recovered = recovered_wrapped.try_unwrap().unwrap();

// Check that the recovered envelope matches the original
assert!(recovered.is_identical_to(&original));
Source§

impl Envelope

§Type System for Gordian Envelopes

This module provides functionality for adding, querying, and verifying types within envelopes. In Gordian Envelope, types are implemented using the special 'isA' Known Value predicate, which is semantically equivalent to the RDF rdf:type concept.

Type information enables:

  • Semantic classification of envelopes
  • Type verification before processing content
  • Conversion between domain objects and envelopes
  • Schema validation
§Type Representation

Types are represented as assertions with the 'isA' predicate (known value

  1. and an object that specifies the type. The type object is typically either:
  1. A Known Value from the registry (e.g., known_values::SEED_TYPE)
  2. A custom type represented as an envelope
§Usage Patterns

The type system is commonly used in two ways:

  1. Type Tagging: Adding type information to envelopes to indicate their semantic meaning

    use bc_envelope::prelude::*;
    
    // Create an envelope representing a person
    let person = Envelope::new("Alice")
        .add_type("Person")
        .add_assertion("age", 30);
  2. Type Checking: Verifying that an envelope has the expected type before processing

    use bc_envelope::prelude::*;
    
    fn process_person(envelope: &Envelope) -> EnvelopeResult<()> {
        // Verify this is a person before processing
        envelope.check_type("Person")?;
    
        // Now we can safely extract person-specific information
        let name: String = envelope.subject().try_into()?;
        let age = envelope.extract_object_for_predicate::<u8>("age")?;
    
        println!("{} is {} years old", name, age);
        Ok(())
    }
§Domain Object Conversion

The type system also enables conversion between domain objects and envelopes. The pattern typically involves:

  1. Implementing From<DomainObject> for Envelope to convert objects to envelopes
  2. Implementing TryFrom<Envelope> for DomainObject to convert envelopes back to objects
  3. Using check_type_value() or check_type() in the TryFrom implementation to verify the envelope has the correct type

See the test_seed.rs file in the tests directory for an example of this pattern.

Source

pub fn add_type(&self, object: impl EnvelopeEncodable) -> Self

Adds a type assertion to the envelope using the 'isA' predicate.

This method provides a convenient way to declare the type of an envelope using the standard 'isA' predicate (known value 1). The type can be any value that can be converted to an envelope, typically a string or a Known Value from the registry.

§Parameters
  • object: The type to assign to this envelope
§Returns

A new envelope with the type assertion added

§Examples

Using a string type:

use bc_envelope::prelude::*;

// Create a document and declare its type
let document = Envelope::new("Important Content").add_type("Document");

// Verify the type was added
assert!(document.has_type("Document"));

Using a predefined Known Value type:

use bc_envelope::prelude::*;

// Create a seed envelope with the standard SEED_TYPE
let seed_data = "seed data".to_string();
let seed = Envelope::new(seed_data).add_type(known_values::SEED_TYPE);

// Verify the type was added
assert!(seed.has_type_value(&known_values::SEED_TYPE));
Source

pub fn types(&self) -> Vec<Self>

Returns all type objects from the envelope’s 'isA' assertions.

This method retrieves all objects of assertions that use the 'isA' predicate. Each returned envelope represents a type that has been assigned to this envelope.

§Returns

A vector of envelopes, each representing a type assigned to this envelope

§Examples
use std::convert::TryInto;

use bc_envelope::prelude::*;

// Create an envelope with multiple types
let multi_typed = Envelope::new("Versatile Entity")
    .add_type("Person")
    .add_type("Employee")
    .add_type("Manager");

// Get all the type objects
let types = multi_typed.types();

// There should be 3 types
assert_eq!(types.len(), 3);

// For each type, we could verify its presence directly using digests
let person_type = Envelope::new("Person");
let employee_type = Envelope::new("Employee");
let manager_type = Envelope::new("Manager");

let has_person = types.iter().any(|e| e.digest() == person_type.digest());
let has_employee =
    types.iter().any(|e| e.digest() == employee_type.digest());
let has_manager = types.iter().any(|e| e.digest() == manager_type.digest());

assert!(has_person);
assert!(has_employee);
assert!(has_manager);
Source

pub fn get_type(&self) -> Result<Self>

Gets a single type object from the envelope’s 'isA' assertions.

This method is useful when an envelope is expected to have exactly one type. It returns an error if the envelope has zero or multiple types.

§Returns
  • Ok(Envelope): The single type object if exactly one exists
  • Err(EnvelopeError::AmbiguousType): If multiple types exist
§Examples

With a single type:

use bc_envelope::prelude::*;

// Create an envelope with a single type
let person = Envelope::new("Alice").add_type("Person");

// Get the type
let type_obj = person.get_type().unwrap();
let type_string: String = type_obj.try_into().unwrap();
assert_eq!(type_string, "Person");

With multiple types (results in error):

use bc_envelope::prelude::*;

// Create an envelope with multiple types
let multi_typed = Envelope::new("Alice")
    .add_type("Person")
    .add_type("Employee");

// Trying to get a single type will fail
let result = multi_typed.get_type();
assert!(result.is_err());
Source

pub fn has_type(&self, t: impl EnvelopeEncodable) -> bool

Checks if the envelope has a specific type, using an envelope as the type identifier.

This method compares the digest of each type object with the digest of the provided envelope to determine if the envelope has the specified type.

§Parameters
  • t: The type to check for, which will be converted to an envelope
§Returns

true if the envelope has the specified type, false otherwise

§Examples
use bc_envelope::prelude::*;

// Create a typed envelope
let document = Envelope::new("Contract")
    .add_type("LegalDocument")
    .add_assertion("status", "Draft");

// Check for various types
assert!(document.has_type("LegalDocument"));
assert!(!document.has_type("Spreadsheet"));

// Can also check with an envelope
let legal_doc_type = Envelope::new("LegalDocument");
assert!(document.has_type(legal_doc_type));
Source

pub fn has_type_value(&self, t: &KnownValue) -> bool

Checks if the envelope has a specific type, using a Known Value as the type identifier.

Similar to has_type, but specifically for checking against standard Known Value types from the registry.

§Parameters
  • t: The Known Value type to check for
§Returns

true if the envelope has the specified Known Value type, false otherwise

§Examples
use bc_envelope::prelude::*;

// Create a seed envelope
let seed_data = "seed data".to_string();
let seed = Envelope::new(seed_data).add_type(known_values::SEED_TYPE);

// Check the type using the Known Value
assert!(seed.has_type_value(&known_values::SEED_TYPE));
assert!(!seed.has_type_value(&known_values::PRIVATE_KEY_TYPE));
Source

pub fn check_type_value(&self, t: &KnownValue) -> Result<()>

Verifies that the envelope has a specific Known Value type.

This method is similar to has_type_value but returns a Result, making it suitable for use in validation chains with the ? operator.

§Parameters
  • t: The Known Value type to check for
§Returns
  • Ok(()): If the envelope has the specified type
  • Err(EnvelopeError::InvalidType): If the envelope does not have the specified type
§Examples
use bc_envelope::prelude::*;

// Function that processes a seed envelope
fn process_seed(envelope: &Envelope) -> EnvelopeResult<String> {
    // Verify this is a seed
    envelope.check_type_value(&known_values::SEED_TYPE)?;

    // Extract the seed data
    let seed_data: String = envelope.subject().try_into()?;
    Ok(seed_data)
}

// Create a seed envelope
let seed_data = "seed data".to_string();
let seed =
    Envelope::new(seed_data.clone()).add_type(known_values::SEED_TYPE);

// Process the seed
let result = process_seed(&seed);
assert!(result.is_ok());
assert_eq!(result.unwrap(), seed_data);

// Create a non-seed envelope
let not_a_seed = Envelope::new("Not a seed").add_type("SomethingElse");

// Processing should fail
let result = process_seed(&not_a_seed);
assert!(result.is_err());
Source

pub fn check_type(&self, t: impl EnvelopeEncodable) -> Result<()>

Verifies that the envelope has a specific type, using an envelope as the type identifier.

This method is similar to has_type but returns a Result, making it suitable for use in validation chains with the ? operator.

§Parameters
  • t: The type to check for, which will be converted to an envelope
§Returns
  • Ok(()): If the envelope has the specified type
  • Err(EnvelopeError::InvalidType): If the envelope does not have the specified type
§Examples
use bc_envelope::prelude::*;

// Function that processes a person
fn process_person(envelope: &Envelope) -> EnvelopeResult<String> {
    // Verify this is a person
    envelope.check_type("Person")?;

    // Extract the name
    let name: String = envelope.subject().try_into()?;
    Ok(name)
}

// Create a person envelope
let person = Envelope::new("Alice").add_type("Person");

// Process the person
let result = process_person(&person);
assert!(result.is_ok());
assert_eq!(result.unwrap(), "Alice");

// Create a non-person envelope
let document = Envelope::new("Contract").add_type("Document");

// Processing should fail
let result = process_person(&document);
assert!(result.is_err());
Source§

impl Envelope

Source

pub fn seal(&self, sender: &dyn Signer, recipient: &dyn Encrypter) -> Envelope

Seals an envelope by signing it with the sender’s key and then encrypting it to the recipient.

This is a convenience method that combines signing and encryption in one step.

§Arguments
  • sender - The private key used to sign the envelope
  • recipient - The public key used to encrypt the envelope
§Returns

A new envelope that has been signed and encrypted

§Example
use bc_components::{EncapsulationScheme, SignatureScheme};
use bc_envelope::prelude::*;

// Create an envelope
let envelope = Envelope::new("Confidential message");

// Generate keys for sender and recipient using specific schemes
let (sender_private, _) = SignatureScheme::Ed25519.keypair();
let (_, recipient_public) = EncapsulationScheme::X25519.keypair();

// Seal the envelope
let sealed_envelope = envelope.seal(&sender_private, &recipient_public);
Source

pub fn seal_opt( &self, sender: &dyn Signer, recipient: &dyn Encrypter, options: Option<SigningOptions>, ) -> Envelope

Seals an envelope by signing it with the sender’s key and then encrypting it to the recipient, with optional signing options.

This is a convenience method that combines signing and encryption in one step.

§Arguments
  • sender - The private key used to sign the envelope
  • recipient - The public key used to encrypt the envelope
  • options - Optional signing options to control how the signature is created
§Returns

A new envelope that has been signed and encrypted

§Example
use bc_components::{EncapsulationScheme, SignatureScheme, SigningOptions};
use bc_envelope::prelude::*;

// Create an envelope
let envelope = Envelope::new("Confidential message");

// Generate keys for sender and recipient using specific schemes
let (sender_private, _) = SignatureScheme::Ed25519.keypair();
let (_, recipient_public) = EncapsulationScheme::X25519.keypair();

// Create signing options for SSH
let options = SigningOptions::Ssh {
    namespace: "test".to_string(),
    hash_alg: ssh_key::HashAlg::Sha512,
};

// Seal the envelope with options
let sealed_envelope =
    envelope.seal_opt(&sender_private, &recipient_public, Some(options));
Source

pub fn unseal( &self, sender: &dyn Verifier, recipient: &dyn Decrypter, ) -> Result<Envelope>

Unseals an envelope by decrypting it with the recipient’s private key and then verifying the signature using the sender’s public key.

This is a convenience method that combines decryption and signature verification in one step.

§Arguments
  • sender - The public key used to verify the signature
  • recipient - The private key used to decrypt the envelope
§Returns

A Result containing the unsealed envelope if successful, or an error if decryption or signature verification fails

§Example
use bc_components::{EncapsulationScheme, SignatureScheme};
use bc_envelope::prelude::*;

// Create an envelope
let envelope = Envelope::new("Confidential message");

// Generate keys for sender and recipient using specific schemes
let (sender_private, sender_public) = SignatureScheme::Ed25519.keypair();
let (recipient_private, recipient_public) =
    EncapsulationScheme::X25519.keypair();

// Seal the envelope
let sealed_envelope = envelope.seal(&sender_private, &recipient_public);

// Unseal the envelope using the recipient's private key
let unsealed_envelope =
    sealed_envelope.unseal(&sender_public, &recipient_private)?;

// Verify we got back the original message
let message: String = unsealed_envelope.extract_subject()?;
assert_eq!(message, "Confidential message");

Trait Implementations§

Source§

impl AsRef<Envelope> for Envelope

Source§

fn as_ref(&self) -> &Envelope

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl CBORTagged for Envelope

Support for CBOR encoding and decoding of Envelope.

All envelopes are tagged with the envelope tag. Within that tag, each of the seven cases has a unique CBOR signature:

  • .node contains a CBOR array, the first element of which is the subject, followed by one or more assertions.
  • .leaf is tagged #6.24, which is the IANA tag for embedded CBOR.
  • .wrapped is tagged with the envelope tag.
  • .assertion is a single-element map {predicate: object}.
  • .knownValue is an unsigned 64-bit integer.
  • .encrypted is tagged with the crypto-msg tag.
  • .elided is a byte string of length 32.
Source§

fn cbor_tags() -> Vec<Tag>

Returns the CBOR tags associated with this type. Read more
Source§

impl CBORTaggedDecodable for Envelope

Source§

fn from_untagged_cbor(cbor: CBOR) -> Result<Self>

Creates an instance of this type by decoding it from untagged CBOR. Read more
Source§

fn from_tagged_cbor(cbor: CBOR) -> Result<Self, Error>
where Self: Sized,

Creates an instance of this type by decoding it from tagged CBOR. Read more
Source§

fn from_tagged_cbor_data(data: impl AsRef<[u8]>) -> Result<Self, Error>
where Self: Sized,

Creates an instance of this type by decoding it from binary encoded tagged CBOR. Read more
Source§

fn from_untagged_cbor_data(data: impl AsRef<[u8]>) -> Result<Self, Error>
where Self: Sized,

Creates an instance of this type by decoding it from binary encoded untagged CBOR. Read more
Source§

impl CBORTaggedEncodable for Envelope

Source§

fn untagged_cbor(&self) -> CBOR

Returns the untagged CBOR encoding of this instance. Read more
Source§

fn tagged_cbor(&self) -> CBOR

Returns the tagged CBOR encoding of this instance. Read more
Source§

fn tagged_cbor_data(&self) -> Vec<u8>

Returns the tagged value in CBOR binary representation. Read more
Source§

impl Clone for Envelope

Source§

fn clone(&self) -> Envelope

Returns a duplicate of the value. Read more
1.0.0§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Envelope

Source§

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

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

impl DigestProvider for Envelope

Support for calculating the digests associated with Envelope.

Envelopes implement the DigestProvider trait, which means they can provide cryptographic digests of their contents. This is a fundamental feature of Gordian Envelope that enables privacy-enhancing features like selective disclosure through elision while maintaining verifiable integrity.

Source§

fn digest(&self) -> Digest

Returns the envelope’s digest.

The digest of an envelope uniquely identifies its semantic content, regardless of whether parts of it are elided, encrypted, or compressed. This is a key property that enables privacy features while maintaining integrity.

Two envelopes with the same digest are considered semantically equivalent - they represent the same information, even if parts of one envelope are elided or obscured.

§Returns

A borrowed reference to the digest if it’s already computed and stored in the envelope, or a newly computed digest if needed.

§Examples
let envelope = Envelope::new("Hello.");
let elided = envelope.elide();

// Even though the content is elided, the digests match
assert_eq!(envelope.digest(), elided.digest());
Source§

impl Display for Envelope

Implements string display for Envelope.

Source§

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

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

impl From<&Envelope> for Envelope

Conversion from &Envelope to Envelope.

This creates a clone of the envelope. Since envelopes use reference counting, this is a relatively inexpensive operation.

Source§

fn from(envelope: &Envelope) -> Self

Converts to this type from the input type.
Source§

impl From<ARID> for Envelope

Source§

fn from(value: ARID) -> Self

Converts this value into an envelope.

Source§

impl From<ByteString> for Envelope

Source§

fn from(value: ByteString) -> Self

Converts this value into an envelope.

Source§

impl From<Date> for Envelope

Source§

fn from(value: Date) -> Self

Converts this value into an envelope.

Source§

impl From<Digest> for Envelope

Source§

fn from(value: Digest) -> Self

Converts this value into an envelope.

Source§

impl From<EncryptedKey> for Envelope

Source§

fn from(value: EncryptedKey) -> Self

Converts this value into an envelope.

Source§

impl From<Envelope> for CBOR

Source§

fn from(value: Envelope) -> Self

Converts to this type from the input type.
Source§

impl From<EnvelopeCase> for Envelope

Conversion from EnvelopeCase to Envelope.

This allows creating an envelope directly from an envelope case variant.

Source§

fn from(case: EnvelopeCase) -> Self

Converts to this type from the input type.
Source§

impl<T> From<Event<T>> for Envelope

Converts an Event<T> to an Envelope.

The envelope’s subject is the event’s ID tagged with TAG_EVENT, and assertions include the event’s content, note (if not empty), and date (if present).

Source§

fn from(event: Event<T>) -> Self

Converts to this type from the input type.
Source§

impl From<Expression> for Envelope

Allows converting an Expression to an Envelope.

This simply returns the envelope that represents the expression.

Source§

fn from(expression: Expression) -> Self

Converts to this type from the input type.
Source§

impl From<JSON> for Envelope

Source§

fn from(value: JSON) -> Self

Converts this value into an envelope.

Source§

impl From<PrivateKeyBase> for Envelope

Source§

fn from(value: PrivateKeyBase) -> Self

Converts this value into an envelope.

Source§

impl From<PrivateKeys> for Envelope

Source§

fn from(value: PrivateKeys) -> Self

Converts this value into an envelope.

Source§

impl From<PublicKeys> for Envelope

Source§

fn from(value: PublicKeys) -> Self

Converts this value into an envelope.

Source§

impl From<Reference> for Envelope

Source§

fn from(value: Reference) -> Self

Converts this value into an envelope.

Source§

impl From<Request> for Envelope

Converts a Request to an Envelope.

The envelope’s subject is the request’s ID tagged with TAG_REQUEST, and assertions include the request’s body, note (if not empty), and date (if present).

Source§

fn from(request: Request) -> Self

Converts to this type from the input type.
Source§

impl From<Response> for Envelope

Converts a Response to an Envelope.

Successful responses have the request ID as the subject and a ‘result’ assertion. Failure responses have the request ID (or ‘Unknown’ if not known) as the subject and an ‘error’ assertion.

Source§

fn from(value: Response) -> Self

Converts to this type from the input type.
Source§

impl From<SSKRShare> for Envelope

Source§

fn from(value: SSKRShare) -> Self

Converts this value into an envelope.

Source§

impl From<Salt> for Envelope

Source§

fn from(value: Salt) -> Self

Converts this value into an envelope.

Source§

impl From<SealedMessage> for Envelope

Source§

fn from(value: SealedMessage) -> Self

Converts this value into an envelope.

Source§

impl From<Signature> for Envelope

Source§

fn from(value: Signature) -> Self

Converts this value into an envelope.

Source§

impl From<URI> for Envelope

Source§

fn from(value: URI) -> Self

Converts this value into an envelope.

Source§

impl From<UUID> for Envelope

Source§

fn from(value: UUID) -> Self

Converts this value into an envelope.

Source§

impl From<XID> for Envelope

Source§

fn from(value: XID) -> Self

Converts this value into an envelope.

Source§

impl From<bool> for Envelope

Source§

fn from(value: bool) -> Self

Converts this value into an envelope.

Source§

impl From<f32> for Envelope

Source§

fn from(value: f32) -> Self

Converts this value into an envelope.

Source§

impl From<f64> for Envelope

Source§

fn from(value: f64) -> Self

Converts this value into an envelope.

Source§

impl From<i16> for Envelope

Source§

fn from(value: i16) -> Self

Converts this value into an envelope.

Source§

impl From<i32> for Envelope

Source§

fn from(value: i32) -> Self

Converts this value into an envelope.

Source§

impl From<i64> for Envelope

Source§

fn from(value: i64) -> Self

Converts this value into an envelope.

Source§

impl From<i8> for Envelope

Source§

fn from(value: i8) -> Self

Converts this value into an envelope.

Source§

impl From<u16> for Envelope

Source§

fn from(value: u16) -> Self

Converts this value into an envelope.

Source§

impl From<u32> for Envelope

Source§

fn from(value: u32) -> Self

Converts this value into an envelope.

Source§

impl From<u64> for Envelope

Source§

fn from(value: u64) -> Self

Converts this value into an envelope.

Source§

impl From<u8> for Envelope

Source§

fn from(value: u8) -> Self

Converts this value into an envelope.

Source§

impl From<usize> for Envelope

Source§

fn from(value: usize) -> Self

Converts this value into an envelope.

Source§

impl PartialEq for Envelope

Implementation of PartialEq for Envelope to allow for structural comparison.

This implements the == operator for envelopes using the is_identical_to() method, which checks for both semantic equivalence and structural identity. Following the corrected behavior of that method:

  1. Envelopes with different content (not semantically equivalent) are not equal (!=)
  2. Envelopes with the same content but different structure are not equal (!=)
  3. Only envelopes with both the same content and structure are equal (==)

Note that we deliberately do not also implement Eq as this comparison for structural identity is potentially expensive (O(m + n) in the worst case), and data structures like HashMap expect Eq to be a fast operation.

§Usage with Hash Maps and Sets

If you want to use envelopes as keys in hash-based collections like HashMap or HashSet, you should pre-compute the envelope’s structural_digest() and use that as the key instead, as this will be more efficient.

§Examples

let env1 = Envelope::new("Alice");
let env2 = Envelope::new("Alice");
let env3 = Envelope::new("Bob");

// Same content and structure are equal
assert!(env1 == env2);

// Different content means not equal
assert!(env1 != env3);

// Same content but different structure (one elided) are not equal
assert!(env1 != env1.elide());
Source§

fn eq(&self, other: &Self) -> bool

Compares two envelopes for structural identity.

This is equivalent to calling self.is_identical_to(other).

1.0.0§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl TryFrom<CBOR> for Envelope

Source§

type Error = Error

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

fn try_from(value: CBOR) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Compressed> for Envelope

Available on crate feature compress only.

TryFrom implementation to convert compressed data into an envelope.

This conversion is only available when the compress feature is enabled.

Source§

fn try_from(compressed: Compressed) -> Result<Self>

Attempts to create an envelope with compressed data as its subject.

This uses the specialized envelope constructor for compressed content.

Source§

type Error = Error

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

impl TryFrom<EncryptedMessage> for Envelope

Available on crate feature encrypt only.

TryFrom implementation to convert an encrypted message into an envelope.

This conversion is only available when the encrypt feature is enabled.

Source§

fn try_from(value: EncryptedMessage) -> Result<Self>

Attempts to create an envelope with an encrypted message as its subject.

This uses the specialized envelope constructor for encrypted content.

Source§

type Error = Error

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

impl TryFrom<Envelope> for ARID

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for ByteString

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for Date

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for Digest

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl<T> TryFrom<Envelope> for Event<T>

Converts an Envelope to an Event<T>.

This constructor extracts the event ID, content, note, and date from an envelope. The content is converted to the generic type T.

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for Expression

Allows converting an Envelope to an Expression.

This extracts the function from the envelope’s subject and creates an Expression with that function and the envelope.

§Errors

Returns an error if the envelope’s subject cannot be extracted as a Function.

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for Function

Implements conversion from Envelope to Function.

This attempts to extract a Function from an Envelope leaf.

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for PrivateKeyBase

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for PrivateKeys

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for PublicKeys

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for Reference

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for Request

Converts an envelope to a Request.

This simplified constructor doesn’t validate the request’s function.

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for Response

Converts an Envelope to a Response.

The envelope must have a TAG_RESPONSE-tagged subject and either a ‘result’ or ‘error’ assertion (but not both).

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for SSKRShare

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for Salt

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for SealedMessage

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for Signature

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for String

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for URI

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for UUID

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for XID

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for bool

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for f32

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for f64

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for i16

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for i32

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for i64

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for i8

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for u16

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for u32

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for u64

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for u8

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl TryFrom<Envelope> for usize

Source§

type Error = Error

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

fn try_from(envelope: Envelope) -> Result<Self>

Performs the conversion.
Source§

impl Eq for Envelope

Auto Trait Implementations§

Blanket Implementations§

§

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

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

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

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

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

§

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

Mutably borrows from an owned value. Read more
Source§

impl<T> CBORDecodable for T
where T: TryFrom<CBOR, Error = Error>,

Source§

fn try_from_cbor(cbor: &CBOR) -> Result<Self, Error>

Source§

impl<T> CBOREncodable for T
where T: Into<CBOR> + Clone,

Source§

fn to_cbor(&self) -> CBOR

Converts this value to a CBOR object. Read more
Source§

fn to_cbor_data(&self) -> Vec<u8>

Converts this value directly to binary CBOR data. Read more
§

impl<T> CloneToUninit for T
where T: Clone,

§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> EnvelopeEncodable for T
where T: Into<Envelope> + Clone,

Source§

fn into_envelope(self) -> Envelope

Converts the value into an envelope by using its Into<Envelope> implementation.

Source§

fn to_envelope(&self) -> Envelope
where Self: Clone,

Converts a reference to this value into a Gordian Envelope. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

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

§

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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T> ToString for T
where T: Display + ?Sized,

§

fn to_string(&self) -> String

Converts the given value to a String. Read more
§

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

§

type Error = Infallible

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

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

Performs the conversion.
§

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.
§

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

Performs the conversion.
Source§

impl<T> URDecodable for T

Source§

fn from_ur(ur: impl AsRef<UR>) -> Result<Self, Error>
where Self: Sized,

Source§

fn from_ur_string(ur_string: impl Into<String>) -> Result<Self, Error>
where Self: Sized,

Source§

impl<T> UREncodable for T

Source§

fn ur(&self) -> UR

Returns the UR representation of the object.
Source§

fn ur_string(&self) -> String

Returns the UR string representation of the object.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> CBORCodable for T

Source§

impl<T> CBORTaggedCodable for T

Source§

impl<T> URCodable for T