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 (
RcorArcwhen themultithreadedfeature is enabled) and structure sharing to enable efficient O(1) cloning of anEnvelopeor recursively, anyEnvelopes it contains. Cloning anEnvelopesimply 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.
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.
Sourcepub fn add_assertion(
&self,
predicate: impl EnvelopeEncodable,
object: impl EnvelopeEncodable,
) -> Self
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 AliceSourcepub fn add_assertion_envelope(
&self,
assertion_envelope: impl EnvelopeEncodable,
) -> Result<Self>
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();Sourcepub fn add_assertion_envelopes(&self, assertions: &[Self]) -> Result<Self>
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();Sourcepub fn add_optional_assertion_envelope(
&self,
assertion: Option<Self>,
) -> Result<Self>
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();Sourcepub fn add_optional_assertion(
&self,
predicate: impl EnvelopeEncodable,
object: Option<impl EnvelopeEncodable>,
) -> Self
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 assertionobject- 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));Sourcepub fn add_nonempty_string_assertion(
&self,
predicate: impl EnvelopeEncodable,
str: impl AsRef<str>,
) -> Self
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 assertionstr- 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);Sourcepub fn add_assertions(&self, envelopes: &[Self]) -> Self
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.
impl Envelope
Support for adding conditional assertions.
These methods add assertions only when certain conditions are met.
Sourcepub fn add_assertion_if(
&self,
condition: bool,
predicate: impl EnvelopeEncodable,
object: impl EnvelopeEncodable,
) -> Self
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 assertionpredicate- The predicate for the assertionobject- 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);Sourcepub fn add_assertion_envelope_if(
&self,
condition: bool,
assertion_envelope: Self,
) -> Result<Self>
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 envelopeassertion_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.
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.
Sourcepub fn add_assertion_salted<P, O>(
&self,
predicate: P,
object: O,
salted: bool,
) -> Selfwhere
P: EnvelopeEncodable,
O: EnvelopeEncodable,
pub fn add_assertion_salted<P, O>(
&self,
predicate: P,
object: O,
salted: bool,
) -> Selfwhere
P: EnvelopeEncodable,
O: EnvelopeEncodable,
Returns the result of adding the given assertion to the envelope, optionally salting it.
Sourcepub fn add_assertion_envelope_salted(
&self,
assertion_envelope: Self,
salted: bool,
) -> Result<Self>
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.
Sourcepub fn add_optional_assertion_envelope_salted(
&self,
assertion: Option<Self>,
salted: bool,
) -> Result<Self>
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.
pub fn add_assertions_salted(&self, assertions: &[Self], salted: bool) -> Self
Source§impl Envelope
Support for removing or replacing assertions.
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.
Sourcepub fn remove_assertion(&self, target: Self) -> Self
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);Sourcepub fn replace_assertion(
&self,
assertion: Self,
new_assertion: Self,
) -> Result<Self>
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 replacenew_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();Sourcepub fn replace_subject(&self, subject: Self) -> Self
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.
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.
Sourcepub fn digests(&self, level_limit: usize) -> HashSet<Digest>
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::MAXmeans 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 objectsSourcepub fn deep_digests(&self) -> HashSet<Digest>
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);Sourcepub fn shallow_digests(&self) -> HashSet<Digest>
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());Sourcepub fn structural_digest(&self) -> Digest
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()oris_equivalent_to()) - Two envelopes contain the same information in their unobscured form, complexity O(1) -
Structural identity (using
structural_digest()oris_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());Sourcepub fn is_equivalent_to(&self, other: &Self) -> bool
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));Sourcepub fn is_identical_to(&self, other: &Self) -> bool
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:
-
If the envelopes are not semantically equivalent (different digests), returns
false- different content means they cannot be identical -
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 differentSource§impl Envelope
impl Envelope
Sourcepub fn case(&self) -> &EnvelopeCase
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.
impl Envelope
Support for basic envelope creation.
Sourcepub fn new(subject: impl EnvelopeEncodable) -> Self
pub fn new(subject: impl EnvelopeEncodable) -> Self
Creates an envelope with a subject, which
can be any instance that implements EnvelopeEncodable.
Sourcepub fn new_or_null(subject: Option<impl EnvelopeEncodable>) -> Self
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.
Sourcepub fn new_or_none(subject: Option<impl EnvelopeEncodable>) -> Option<Self>
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.
Sourcepub fn new_assertion(
predicate: impl EnvelopeEncodable,
object: impl EnvelopeEncodable,
) -> Self
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.
impl Envelope
Support for eliding elements from envelopes.
This includes eliding, encrypting and compressing (obscuring) elements.
Sourcepub fn elide(&self) -> Self
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));Sourcepub fn elide_removing_set_with_action(
&self,
target: &HashSet<Digest>,
action: &ObscureAction,
) -> Self
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 obscuredaction- 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 visibleSourcepub fn elide_removing_set(&self, target: &HashSet<Digest>) -> Self
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);Sourcepub fn elide_removing_array_with_action(
&self,
target: &[&dyn DigestProvider],
action: &ObscureAction,
) -> Self
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).
- target: An array of
-
Returns: The elided envelope.
Sourcepub fn elide_removing_array(&self, target: &[&dyn DigestProvider]) -> Self
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).
- target: An array of
-
Returns: The elided envelope.
Sourcepub fn elide_removing_target_with_action(
&self,
target: &dyn DigestProvider,
action: &ObscureAction,
) -> Self
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).
- target: A
-
Returns: The elided envelope.
Sourcepub fn elide_removing_target(&self, target: &dyn DigestProvider) -> Self
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.
- target: A
-
Returns: The elided envelope.
Sourcepub fn elide_revealing_set_with_action(
&self,
target: &HashSet<Digest>,
action: &ObscureAction,
) -> Self
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 revealedaction- 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);Sourcepub fn elide_revealing_set(&self, target: &HashSet<Digest>) -> Self
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.
Sourcepub fn elide_revealing_array_with_action(
&self,
target: &[&dyn DigestProvider],
action: &ObscureAction,
) -> Self
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).
- target: An array of
-
Returns: The elided envelope.
Sourcepub fn elide_revealing_array(&self, target: &[&dyn DigestProvider]) -> Self
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.
- target: An array of
-
Returns: The elided envelope.
Sourcepub fn elide_revealing_target_with_action(
&self,
target: &dyn DigestProvider,
action: &ObscureAction,
) -> Self
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).
- target: A
-
Returns: The elided envelope.
Sourcepub fn elide_revealing_target(&self, target: &dyn DigestProvider) -> Self
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.
- target: A
-
Returns: The elided envelope.
Sourcepub fn elide_set_with_action(
&self,
target: &HashSet<Digest>,
is_revealing: bool,
action: &ObscureAction,
) -> Self
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 isfalse, the target set contains the digests of the elements to elide. - action: Perform the specified action (elision, encryption or compression).
-
Returns: The elided envelope.
Sourcepub fn elide_set(&self, target: &HashSet<Digest>, is_revealing: bool) -> Self
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 isfalse, the target set contains the digests of the elements to elide.
-
Returns: The elided envelope.
Sourcepub fn elide_array_with_action(
&self,
target: &[&dyn DigestProvider],
is_revealing: bool,
action: &ObscureAction,
) -> Self
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 isfalse, the target set contains the digests of the elements to elide. - action: Perform the specified action (elision, encryption or compression).
- target: An array of
-
Returns: The elided envelope.
Sourcepub fn elide_array(
&self,
target: &[&dyn DigestProvider],
is_revealing: bool,
) -> Self
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 isfalse, the target set contains the digests of the elements to elide.
- target: An array of
-
Returns: The elided envelope.
Sourcepub fn elide_target_with_action(
&self,
target: &dyn DigestProvider,
is_revealing: bool,
action: &ObscureAction,
) -> Self
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 isfalse, the target is the element to elide, leaving all others revealed. - action: Perform the specified action (elision, encryption or compression).
- target: A
-
Returns: The elided envelope.
Sourcepub fn elide_target(
&self,
target: &dyn DigestProvider,
is_revealing: bool,
) -> Self
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 isfalse, the target is the element to elide, leaving all others revealed.
- target: A
-
Returns: The elided envelope.
Sourcepub fn unelide(&self, envelope: impl Into<Envelope>) -> Result<Self>
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());Sourcepub fn nodes_matching(
&self,
target_digests: Option<&HashSet<Digest>>,
obscure_types: &[ObscureType],
) -> HashSet<Digest>
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. IfNone, all nodes are considered for matching.obscure_types- Slice ofObscureTypevalues 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));Sourcepub fn walk_unelide(&self, envelopes: &[Envelope]) -> Self
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 inself
§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());Sourcepub fn walk_replace(
&self,
target: &HashSet<Digest>,
replacement: &Envelope,
) -> Result<Self>
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 replacereplacement- 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"));Sourcepub fn walk_decrypt(&self, keys: &[SymmetricKey]) -> Self
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 ofSymmetricKeyvalues 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));Sourcepub fn walk_decompress(&self, target_digests: Option<&HashSet<Digest>>) -> Self
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. IfNone, 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.
impl Envelope
Static methods for creating envelopes from CBOR data.
Sourcepub fn try_from_cbor(cbor: CBOR) -> Result<Self>
pub fn try_from_cbor(cbor: CBOR) -> Result<Self>
Sourcepub fn try_from_cbor_data(data: Vec<u8>) -> Result<Self>
pub fn try_from_cbor_data(data: Vec<u8>) -> Result<Self>
Source§impl Envelope
impl Envelope
Sourcepub fn subject(&self) -> Self
pub fn subject(&self) -> Self
The envelope’s subject.
For an envelope with no assertions, returns the same envelope.
Sourcepub fn assertions(&self) -> Vec<Self>
pub fn assertions(&self) -> Vec<Self>
The envelope’s assertions.
Sourcepub fn has_assertions(&self) -> bool
pub fn has_assertions(&self) -> bool
true if the envelope has at least one assertion, false otherwise.
Sourcepub fn as_assertion(&self) -> Option<Self>
pub fn as_assertion(&self) -> Option<Self>
If the envelope’s subject is an assertion return it, else return None.
Sourcepub fn try_assertion(&self) -> Result<Self>
pub fn try_assertion(&self) -> Result<Self>
If the envelope’s subject is an assertion return it, else return an error.
Sourcepub fn as_predicate(&self) -> Option<Self>
pub fn as_predicate(&self) -> Option<Self>
The envelope’s predicate, or None if the envelope is not an assertion.
Sourcepub fn try_predicate(&self) -> Result<Self>
pub fn try_predicate(&self) -> Result<Self>
The envelope’s predicate, or an error if the envelope is not an assertion.
Sourcepub fn as_object(&self) -> Option<Self>
pub fn as_object(&self) -> Option<Self>
The envelope’s object, or None if the envelope is not an assertion.
Sourcepub fn try_object(&self) -> Result<Self>
pub fn try_object(&self) -> Result<Self>
The envelope’s object, or an error if the envelope is not an assertion.
Sourcepub fn as_leaf(&self) -> Option<CBOR>
pub fn as_leaf(&self) -> Option<CBOR>
The envelope’s leaf CBOR object, or None if the envelope is not a
leaf.
Sourcepub fn try_leaf(&self) -> Result<CBOR>
pub fn try_leaf(&self) -> Result<CBOR>
The envelope’s leaf CBOR object, or an error if the envelope is not a leaf.
Sourcepub fn is_assertion(&self) -> bool
pub fn is_assertion(&self) -> bool
true if the envelope is case ::Assertion, false otherwise.
Sourcepub fn is_encrypted(&self) -> bool
pub fn is_encrypted(&self) -> bool
true if the envelope is case ::Encrypted, false otherwise.
Sourcepub fn is_compressed(&self) -> bool
pub fn is_compressed(&self) -> bool
true if the envelope is case ::Compressed, false otherwise.
Sourcepub fn is_wrapped(&self) -> bool
pub fn is_wrapped(&self) -> bool
true if the envelope is case ::Wrapped, false otherwise.
Source§impl Envelope
impl Envelope
Sourcepub fn is_subject_assertion(&self) -> bool
pub fn is_subject_assertion(&self) -> bool
true if the subject of the envelope is an assertion, false
otherwise.
Sourcepub fn is_subject_encrypted(&self) -> bool
pub fn is_subject_encrypted(&self) -> bool
true if the subject of the envelope has been encrypted, false
otherwise.
Sourcepub fn is_subject_compressed(&self) -> bool
pub fn is_subject_compressed(&self) -> bool
true if the subject of the envelope has been compressed, false
otherwise.
Sourcepub fn is_subject_elided(&self) -> bool
pub fn is_subject_elided(&self) -> bool
true if the subject of the envelope has been elided, false
otherwise.
Sourcepub fn is_subject_obscured(&self) -> bool
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.
Sourcepub fn is_internal(&self) -> bool
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.
Sourcepub fn is_obscured(&self) -> bool
pub fn is_obscured(&self) -> bool
true if the envelope is encrypted, elided, or compressed; false
otherwise.
Sourcepub fn extract_subject<T>(&self) -> Result<T>
pub fn extract_subject<T>(&self) -> Result<T>
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 implementTryFrom<CBOR>.
§Returns
Result<T>- The decoded subject value or an error if conversion fails
§Errors
- Returns
Error::InvalidFormatif 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());Sourcepub fn assertions_with_predicate(
&self,
predicate: impl EnvelopeEncodable,
) -> Vec<Self>
pub fn assertions_with_predicate( &self, predicate: impl EnvelopeEncodable, ) -> Vec<Self>
Returns all assertions with the given predicate. Match by comparing digests.
Sourcepub fn assertion_with_predicate(
&self,
predicate: impl EnvelopeEncodable,
) -> Result<Self>
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 implementsEnvelopeEncodable
§Returns
Result<Self>- The matching assertion envelope if found
§Errors
- Returns
EnvelopeError::NonexistentPredicateif no assertion has the specified predicate - Returns
EnvelopeError::AmbiguousPredicateif 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());Sourcepub fn optional_assertion_with_predicate(
&self,
predicate: impl EnvelopeEncodable,
) -> Result<Option<Self>>
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.
Sourcepub fn object_for_predicate(
&self,
predicate: impl EnvelopeEncodable,
) -> Result<Self>
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 implementsEnvelopeEncodable
§Returns
Result<Self>- The object part of the matching assertion
§Errors
- Returns
EnvelopeError::NonexistentPredicateif no assertion has the specified predicate - Returns
EnvelopeError::AmbiguousPredicateif 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);Sourcepub fn try_as<T>(&self) -> Result<T>
pub fn try_as<T>(&self) -> Result<T>
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.
Sourcepub fn try_object_for_predicate<T>(
&self,
predicate: impl EnvelopeEncodable,
) -> Result<T>
pub fn try_object_for_predicate<T>( &self, predicate: impl EnvelopeEncodable, ) -> Result<T>
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.
Sourcepub fn optional_object_for_predicate(
&self,
predicate: impl EnvelopeEncodable,
) -> Result<Option<Self>>
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.
Sourcepub fn try_optional_object_for_predicate<T>(
&self,
predicate: impl EnvelopeEncodable,
) -> Result<Option<T>>
pub fn try_optional_object_for_predicate<T>( &self, predicate: impl EnvelopeEncodable, ) -> Result<Option<T>>
Returns the object of the assertion with the given predicate, or None
if there is no matching predicate.
Sourcepub fn extract_object<T: TryFrom<CBOR, Error = Error> + 'static>(
&self,
) -> Result<T>
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 implementTryFrom<CBOR>.
§Returns
Result<T>- The decoded object value
§Errors
- Returns
EnvelopeError::NotAssertionif the envelope is not an assertion - Returns
Error::InvalidFormatif 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());Sourcepub fn extract_predicate<T: TryFrom<CBOR, Error = Error> + 'static>(
&self,
) -> Result<T>
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.
Sourcepub fn extract_object_for_predicate<T: TryFrom<CBOR, Error = Error> + 'static>(
&self,
predicate: impl EnvelopeEncodable,
) -> Result<T>
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 implementTryFrom<CBOR>.
§Arguments
predicate- The predicate to search for
§Returns
Result<T>- The decoded object value
§Errors
- Returns
EnvelopeError::NonexistentPredicateif no assertion has the specified predicate - Returns
EnvelopeError::AmbiguousPredicateif multiple assertions have the specified predicate - Returns
Error::InvalidFormatif 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());Sourcepub fn extract_optional_object_for_predicate<T: TryFrom<CBOR, Error = Error> + 'static>(
&self,
predicate: impl EnvelopeEncodable,
) -> Result<Option<T>>
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.
Sourcepub fn extract_object_for_predicate_with_default<T: TryFrom<CBOR, Error = Error> + 'static>(
&self,
predicate: impl EnvelopeEncodable,
default: T,
) -> Result<T>
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.
Sourcepub fn objects_for_predicate(
&self,
predicate: impl EnvelopeEncodable,
) -> Vec<Self>
pub fn objects_for_predicate( &self, predicate: impl EnvelopeEncodable, ) -> Vec<Self>
Returns the objects of all assertions with the matching predicate.
Sourcepub fn extract_objects_for_predicate<T: TryFrom<CBOR, Error = Error> + 'static>(
&self,
predicate: impl EnvelopeEncodable,
) -> Result<Vec<T>>
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.
Sourcepub fn try_objects_for_predicate<T: TryFrom<Envelope, Error = Error> + 'static>(
&self,
predicate: impl EnvelopeEncodable,
) -> Result<Vec<T>>
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.
Sourcepub fn elements_count(&self) -> usize
pub fn elements_count(&self) -> usize
Returns the number of structural elements in the envelope, including itself.
Source§impl Envelope
impl Envelope
Sourcepub fn set_position(&mut self, position: usize) -> Result<Self>
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.
Sourcepub fn position(&self) -> Result<usize>
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.
Sourcepub fn remove_position(&self) -> Result<Self>
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.
impl Envelope
Functions for traversing and manipulating the envelope hierarchy.
Sourcepub fn walk<State: Clone>(
&self,
hide_nodes: bool,
state: State,
visit: &Visitor<'_, State>,
)
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 containersvisit- 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.
impl Envelope
Support for wrapping and unwrapping envelopes.
Sourcepub fn wrap(&self) -> Self
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()
);Sourcepub fn try_unwrap(&self) -> Result<Self>
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
impl Envelope
Sourcepub fn is_number(&self) -> bool
pub fn is_number(&self) -> bool
true if the envelope is a leaf node that contains a number, false
Sourcepub fn is_subject_number(&self) -> bool
pub fn is_subject_number(&self) -> bool
true if the subject of the envelope is a number, false
otherwise.
Sourcepub fn is_nan(&self) -> bool
pub fn is_nan(&self) -> bool
true if the envelope is a leaf node that contains the NaN value,
false otherwise.
Sourcepub fn is_subject_nan(&self) -> bool
pub fn is_subject_nan(&self) -> bool
true if the subject of the envelope is the NaN value, false
otherwise.
Source§impl Envelope
impl Envelope
Sourcepub fn try_byte_string(&self) -> Result<Vec<u8>>
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.
pub fn as_byte_string(&self) -> Option<Vec<u8>>
Source§impl Envelope
impl Envelope
Sourcepub fn as_known_value(&self) -> Option<&KnownValue>
pub fn as_known_value(&self) -> Option<&KnownValue>
The envelope’s KnownValue, or None if the envelope is not case
::KnownValue.
Sourcepub fn try_known_value(&self) -> Result<&KnownValue>
pub fn try_known_value(&self) -> Result<&KnownValue>
The envelope’s KnownValue, or an error if the envelope is not case
::KnownValue.
Sourcepub fn is_known_value(&self) -> bool
pub fn is_known_value(&self) -> bool
true if the envelope is case ::KnownValue, false otherwise.
Sourcepub fn unit() -> Self
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.
Sourcepub fn is_subject_unit(&self) -> bool
pub fn is_subject_unit(&self) -> bool
true if the subject of the envelope is the unit value, false
otherwise.
Sourcepub fn check_subject_unit(&self) -> Result<&Self>
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.
impl Envelope
Support for the various text output formats for Envelope.
Sourcepub fn format_opt(&self, opts: &EnvelopeFormatOpts<'_>) -> String
pub fn format_opt(&self, opts: &EnvelopeFormatOpts<'_>) -> String
Returns the envelope notation for this envelope.
Sourcepub fn format(&self) -> String
pub fn format(&self) -> String
Returns the envelope notation for this envelope.
Uses the current format context.
Sourcepub fn format_flat(&self) -> String
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.
impl Envelope
Support for tree-formatting envelopes.
Sourcepub fn tree_format(&self) -> String
pub fn tree_format(&self) -> String
Returns a tree-formatted string representation of the envelope with default options.
Sourcepub fn tree_format_opt(&self, opts: &TreeFormatOpts<'_>) -> String
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 isfalse.highlighting_target- Set of digests to highlight in the tree representation. Default is an empty set.context- Formatting context. Default isTreeFormatContext::Global.
Source§impl Envelope
impl Envelope
Sourcepub fn short_id(&self, opt: DigestDisplayFormat) -> String
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.
impl Envelope
Support for tree-formatting envelopes.
pub fn mermaid_format(&self) -> String
pub fn mermaid_format_opt(&self, opts: &MermaidFormatOpts<'_>) -> String
Source§impl Envelope
impl Envelope
Sourcepub fn diagnostic_annotated(&self) -> String
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.
Sourcepub fn diagnostic(&self) -> String
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
impl Envelope
Source§impl Envelope
Methods for creating attachment envelopes
impl Envelope
Methods for creating attachment envelopes
Sourcepub fn new_attachment(
payload: impl EnvelopeEncodable,
vendor: &str,
conforms_to: Option<&str>,
) -> Self
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 attachmentvendor- 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(_)));Sourcepub fn add_attachment(
&self,
payload: impl EnvelopeEncodable,
vendor: &str,
conforms_to: Option<&str>,
) -> Self
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 attachmentvendor- 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
impl Envelope
Methods for accessing attachments in envelopes
Sourcepub fn attachment_payload(&self) -> Result<Self>
pub fn attachment_payload(&self) -> Result<Self>
Sourcepub fn attachment_vendor(&self) -> Result<String>
pub fn attachment_vendor(&self) -> Result<String>
Sourcepub fn attachment_conforms_to(&self) -> Result<Option<String>>
pub fn attachment_conforms_to(&self) -> Result<Option<String>>
Sourcepub fn attachments_with_vendor_and_conforms_to(
&self,
vendor: Option<&str>,
conforms_to: Option<&str>,
) -> Result<Vec<Self>>
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
vendorisNone, matches any vendor - If
conformsToisNone, matches any conformsTo value - If both are
None, matches all attachments
§Parameters
vendor- Optional vendor identifier to matchconforms_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);Sourcepub fn attachments(&self) -> Result<Vec<Self>>
pub fn attachments(&self) -> Result<Vec<Self>>
Sourcepub fn validate_attachment(&self) -> Result<()>
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
Sourcepub fn attachment_with_vendor_and_conforms_to(
&self,
vendor: Option<&str>,
conforms_to: Option<&str>,
) -> Result<Self>
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 matchconforms_to- Optional conformsTo URI to match
§Returns
The matching attachment envelope
§Errors
- Returns
EnvelopeError::NonexistentAttachmentif no attachments match - Returns
EnvelopeError::AmbiguousAttachmentif 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.
impl Envelope
Support for compressing and decompressing envelopes.
Sourcepub fn compress(&self) -> Result<Self>
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::AlreadyEncryptedif the envelope is already encrypted - Returns
EnvelopeError::AlreadyElidedif 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());Sourcepub fn decompress(&self) -> Result<Self>
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::NotCompressedif the envelope is not compressed - Returns
EnvelopeError::MissingDigestif the compressed envelope is missing its digest - Returns
EnvelopeError::InvalidDigestif 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());Sourcepub fn compress_subject(&self) -> Result<Self>
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");Sourcepub fn decompress_subject(&self) -> Result<Self>
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.
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));Sourcepub fn encrypt_subject(&self, key: &SymmetricKey) -> Result<Self>
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- TheSymmetricKeyto use for encryption
§Returns
A new envelope with its subject encrypted
§Errors
Returns an error if the envelope is already encrypted or elided
Sourcepub fn decrypt_subject(&self, key: &SymmetricKey) -> Result<Self>
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- TheSymmetricKeyto 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
impl Envelope
Sourcepub fn encrypt(&self, key: &SymmetricKey) -> Envelope
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- TheSymmetricKeyto 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);Sourcepub fn decrypt(&self, key: &SymmetricKey) -> Result<Envelope>
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- TheSymmetricKeyto 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
impl Envelope
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.
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
)
);Sourcepub fn proof_contains_set(
&self,
target: &HashSet<Digest, RandomState>,
) -> Option<Envelope>
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 existNone: 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));Sourcepub fn proof_contains_target(
&self,
target: &dyn DigestProvider,
) -> Option<Envelope>
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 existNone: 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));Sourcepub fn confirm_contains_set(
&self,
target: &HashSet<Digest, RandomState>,
proof: &Envelope,
) -> bool
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:
- The proof’s digest matches this envelope’s digest
- 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 prooffalse: 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));Sourcepub fn confirm_contains_target(
&self,
target: &dyn DigestProvider,
proof: &Envelope,
) -> bool
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 prooffalse: 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.
impl Envelope
Support for public key encryption.
Sourcepub fn add_recipient(
&self,
recipient: &dyn Encrypter,
content_key: &SymmetricKey,
) -> Self
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 envelopecontent_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"));Sourcepub fn recipients(&self) -> Result<Vec<SealedMessage>>
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);Sourcepub fn encrypt_subject_to_recipients(
&self,
recipients: &[&dyn Encrypter],
) -> Result<Self>
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:
- Generating a random symmetric key (the content key)
- Encrypting the envelope’s subject with this key
- Encrypting the content key to each recipient’s public key
- Adding a
hasRecipientassertion 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]");Sourcepub fn encrypt_subject_to_recipient(
&self,
recipient: &dyn Encrypter,
) -> Result<Self>
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:
- Generating a random symmetric key (the content key)
- Encrypting the envelope’s subject with this key
- Encrypting the content key to the recipient’s public key
- Adding a
hasRecipientassertion 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"));Sourcepub fn decrypt_subject_to_recipient(
&self,
recipient: &dyn Decrypter,
) -> Result<Self>
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:
- Finds and extracts all
SealedMessageobjects fromhasRecipientassertions - Tries to decrypt each one with the provided private key until successful
- Extracts the content key from the decrypted message
- 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
hasRecipientassertions containingSealedMessageobjects 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.
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.
Sourcepub fn encrypt_to_recipient(&self, recipient: &dyn Encrypter) -> Envelope
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:
- Wraps the envelope (preserving its assertions in the wrap)
- 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]"
);Sourcepub fn decrypt_to_recipient(
&self,
recipient: &dyn Decrypter,
) -> Result<Envelope>
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:
- Decrypts the envelope using the recipient’s private key
- 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.
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.
Sourcepub fn add_signature(&self, private_key: &dyn Signer) -> Self
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
- private_key: The signer’s
-
Returns: The signed envelope.
Sourcepub fn make_signed_assertion(
&self,
signature: &Signature,
note: Option<&str>,
) -> Self
pub fn make_signed_assertion( &self, signature: &Signature, note: Option<&str>, ) -> Self
Convenience constructor for a 'signed': Signature assertion envelope.
-
Parameters:
- signature: The
Signaturefor the object. - note: An optional note to be added to the
Signature.
- signature: The
-
Returns: The new assertion envelope.
Sourcepub fn is_verified_signature(
&self,
signature: &Signature,
public_key: &dyn Verifier,
) -> bool
pub fn is_verified_signature( &self, signature: &Signature, public_key: &dyn Verifier, ) -> bool
Returns whether the given signature is valid.
-
Parameters:
- signature: The
Signatureto be checked. - public_key: The potential signer’s
Verifier.
- signature: The
-
Returns:
trueif the signature is valid for this envelope’s subject,falseotherwise.
Sourcepub fn verify_signature(
&self,
signature: &Signature,
public_key: &dyn Verifier,
) -> Result<Self>
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
Signatureto be checked. - public_key: The potential signer’s
Verifier.
- signature: The
-
Returns: This envelope.
-
Throws: Throws
EnvelopeError.unverifiedSignatureif the signature is not valid. valid.
Sourcepub fn has_signature_from(&self, public_key: &dyn Verifier) -> Result<bool>
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.
- public_key: The potential signer’s
-
Returns:
trueif any signature is valid for this envelope’s subject,falseotherwise. -
Throws: Throws an exception if any
'signed'assertion doesn’t contain a validSignatureas its object.
Sourcepub fn has_signature_from_returning_metadata(
&self,
public_key: &dyn Verifier,
) -> Result<Option<Envelope>>
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,
Noneotherwise.
Sourcepub fn verify_signature_from(&self, public_key: &dyn Verifier) -> Result<Self>
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.
- public_key: The potential signer’s
-
Returns: This envelope.
-
Throws: Throws
EnvelopeError.unverifiedSignatureif the signature is not valid. valid.
pub fn verify_signature_from_returning_metadata( &self, public_key: &dyn Verifier, ) -> Result<Envelope>
Sourcepub fn has_signatures_from(&self, public_keys: &[&dyn Verifier]) -> Result<bool>
pub fn has_signatures_from(&self, public_keys: &[&dyn Verifier]) -> Result<bool>
Checks whether the envelope’s subject has a set of signatures.
Sourcepub fn has_signatures_from_threshold(
&self,
public_keys: &[&dyn Verifier],
threshold: Option<usize>,
) -> Result<bool>
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.
- public_keys: An array of potential signers’
-
Returns:
trueif the threshold of valid signatures is met,falseotherwise. -
Throws: Throws an exception if any
'signed'assertion doesn’t contain a validSignatureas its object.
Sourcepub fn verify_signatures_from_threshold(
&self,
public_keys: &[&dyn Verifier],
threshold: Option<usize>,
) -> Result<Self>
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.
- public_keys: An array of potential signers’
-
Returns: This envelope.
-
Throws: Throws an exception if the threshold of valid signatures is not met.
Sourcepub fn verify_signatures_from(
&self,
public_keys: &[&dyn Verifier],
) -> Result<Self>
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.
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.
Sourcepub fn sign(&self, signer: &dyn Signer) -> Envelope
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.
Sourcepub fn sign_opt(
&self,
signer: &dyn Signer,
options: Option<SigningOptions>,
) -> Envelope
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.
Sourcepub fn verify(&self, verifier: &dyn Verifier) -> Result<Envelope>
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.
Sourcepub fn verify_returning_metadata(
&self,
verifier: &dyn Verifier,
) -> Result<(Envelope, Envelope)>
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.
impl Envelope
Support for decorrelation of envelopes using salt.
Sourcepub fn add_salt(&self) -> Self
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());Sourcepub fn add_salt_instance(&self, salt: Salt) -> Self
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"));Sourcepub fn add_salt_with_len(&self, count: usize) -> Result<Self>
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());Sourcepub fn add_salt_in_range(&self, range: RangeInclusive<usize>) -> Result<Self>
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
impl Envelope
pub fn lock_subject( &self, method: KeyDerivationMethod, secret: impl AsRef<[u8]>, ) -> Result<Self>
pub fn unlock_subject(&self, secret: impl AsRef<[u8]>) -> Result<Self>
pub fn is_locked_with_password(&self) -> bool
pub fn is_locked_with_ssh_agent(&self) -> bool
pub fn add_secret( &self, method: KeyDerivationMethod, secret: impl AsRef<[u8]>, content_key: &SymmetricKey, ) -> Result<Self>
Source§impl Envelope
Support for splitting and combining envelopes using SSKR (Shamir’s Secret
Sharing).
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:
- A Gordian Envelope is encrypted with a symmetric key
- The symmetric key is split into multiple SSKR shares using a group threshold and member thresholds
- Each share is added as an assertion to a copy of the encrypted envelope
- These envelope copies are distributed to trusted individuals or storage locations
- 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.
Sourcepub fn sskr_split(
&self,
spec: &SSKRSpec,
content_key: &SymmetricKey,
) -> Result<Vec<Vec<Envelope>>>
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 thresholdscontent_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);
}Sourcepub fn sskr_split_flattened(
&self,
spec: &SSKRSpec,
content_key: &SymmetricKey,
) -> Result<Vec<Envelope>>
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 thresholdscontent_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
);
}Sourcepub fn sskr_join(envelopes: &[&Envelope]) -> Result<Envelope>
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::InvalidSharesif 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.
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
- and an object that specifies the type. The type object is typically either:
- A Known Value from the registry (e.g.,
known_values::SEED_TYPE) - A custom type represented as an envelope
§Usage Patterns
The type system is commonly used in two ways:
-
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); -
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:
- Implementing
From<DomainObject> for Envelopeto convert objects to envelopes - Implementing
TryFrom<Envelope> for DomainObjectto convert envelopes back to objects - Using
check_type_value()orcheck_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.
Sourcepub fn add_type(&self, object: impl EnvelopeEncodable) -> Self
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));Sourcepub fn types(&self) -> Vec<Self>
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);Sourcepub fn get_type(&self) -> Result<Self>
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 existsErr(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());Sourcepub fn has_type(&self, t: impl EnvelopeEncodable) -> bool
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));Sourcepub fn has_type_value(&self, t: &KnownValue) -> bool
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));Sourcepub fn check_type_value(&self, t: &KnownValue) -> Result<()>
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 typeErr(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(¬_a_seed);
assert!(result.is_err());Sourcepub fn check_type(&self, t: impl EnvelopeEncodable) -> Result<()>
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 typeErr(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
impl Envelope
Sourcepub fn seal(&self, sender: &dyn Signer, recipient: &dyn Encrypter) -> Envelope
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 enveloperecipient- 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);Sourcepub fn seal_opt(
&self,
sender: &dyn Signer,
recipient: &dyn Encrypter,
options: Option<SigningOptions>,
) -> Envelope
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 enveloperecipient- The public key used to encrypt the envelopeoptions- 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));Sourcepub fn unseal(
&self,
sender: &dyn Verifier,
recipient: &dyn Decrypter,
) -> Result<Envelope>
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 signaturerecipient- 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 CBORTagged for Envelope
Support for CBOR encoding and decoding of Envelope.
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:
.nodecontains a CBOR array, the first element of which is the subject, followed by one or more assertions..leafis tagged #6.24, which is the IANA tag for embedded CBOR..wrappedis tagged with theenvelopetag..assertionis a single-element map{predicate: object}..knownValueis an unsigned 64-bit integer..encryptedis tagged with thecrypto-msgtag..elidedis a byte string of length 32.
Source§impl CBORTaggedDecodable for Envelope
impl CBORTaggedDecodable for Envelope
Source§fn from_untagged_cbor(cbor: CBOR) -> Result<Self>
fn from_untagged_cbor(cbor: CBOR) -> Result<Self>
Source§fn from_tagged_cbor(cbor: CBOR) -> Result<Self, Error>where
Self: Sized,
fn from_tagged_cbor(cbor: CBOR) -> Result<Self, Error>where
Self: Sized,
Source§impl CBORTaggedEncodable for Envelope
impl CBORTaggedEncodable for Envelope
Source§fn untagged_cbor(&self) -> CBOR
fn untagged_cbor(&self) -> CBOR
Source§fn tagged_cbor(&self) -> CBOR
fn tagged_cbor(&self) -> CBOR
Source§impl DigestProvider for Envelope
Support for calculating the digests associated with Envelope.
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
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 From<&Envelope> for Envelope
Conversion from &Envelope to Envelope.
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§impl From<ByteString> for Envelope
impl From<ByteString> for Envelope
Source§fn from(value: ByteString) -> Self
fn from(value: ByteString) -> Self
Converts this value into an envelope.
Source§impl From<EncryptedKey> for Envelope
impl From<EncryptedKey> for Envelope
Source§fn from(value: EncryptedKey) -> Self
fn from(value: EncryptedKey) -> Self
Converts this value into an envelope.
Source§impl From<EnvelopeCase> for Envelope
Conversion from EnvelopeCase to Envelope.
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
fn from(case: EnvelopeCase) -> Self
Source§impl<T> From<Event<T>> for Envelope
Converts an Event<T> to an Envelope.
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§impl From<Expression> for Envelope
Allows converting an Expression to an Envelope.
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
fn from(expression: Expression) -> Self
Source§impl From<PrivateKeyBase> for Envelope
impl From<PrivateKeyBase> for Envelope
Source§fn from(value: PrivateKeyBase) -> Self
fn from(value: PrivateKeyBase) -> Self
Converts this value into an envelope.
Source§impl From<PrivateKeys> for Envelope
impl From<PrivateKeys> for Envelope
Source§fn from(value: PrivateKeys) -> Self
fn from(value: PrivateKeys) -> Self
Converts this value into an envelope.
Source§impl From<PublicKeys> for Envelope
impl From<PublicKeys> for Envelope
Source§fn from(value: PublicKeys) -> Self
fn from(value: PublicKeys) -> Self
Converts this value into an envelope.
Source§impl From<Request> for Envelope
Converts a Request to an Envelope.
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§impl From<Response> for Envelope
Converts a Response to an Envelope.
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§impl From<SealedMessage> for Envelope
impl From<SealedMessage> for Envelope
Source§fn from(value: SealedMessage) -> Self
fn from(value: SealedMessage) -> Self
Converts this value into an envelope.
Source§impl PartialEq for Envelope
Implementation of PartialEq for Envelope to allow for structural
comparison.
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:
- Envelopes with different content (not semantically equivalent) are not equal (!=)
- Envelopes with the same content but different structure are not equal (!=)
- 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§impl TryFrom<Compressed> for Envelope
Available on crate feature compress only.TryFrom implementation to convert compressed data into an envelope.
impl TryFrom<Compressed> for Envelope
compress only.TryFrom implementation to convert compressed data into an envelope.
This conversion is only available when the compress feature is enabled.
Source§impl TryFrom<EncryptedMessage> for Envelope
Available on crate feature encrypt only.TryFrom implementation to convert an encrypted message into an envelope.
impl TryFrom<EncryptedMessage> for Envelope
encrypt only.TryFrom implementation to convert an encrypted message into an envelope.
This conversion is only available when the encrypt feature is enabled.
Source§impl TryFrom<Envelope> for ByteString
impl TryFrom<Envelope> for ByteString
Source§impl<T> TryFrom<Envelope> for Event<T>
Converts an Envelope to an Event<T>.
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§impl TryFrom<Envelope> for Expression
Allows converting an Envelope to an Expression.
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§impl TryFrom<Envelope> for Function
Implements conversion from Envelope to Function.
impl TryFrom<Envelope> for Function
Implements conversion from Envelope to Function.
This attempts to extract a Function from an Envelope leaf.
Source§impl TryFrom<Envelope> for PrivateKeyBase
impl TryFrom<Envelope> for PrivateKeyBase
Source§impl TryFrom<Envelope> for PrivateKeys
impl TryFrom<Envelope> for PrivateKeys
Source§impl TryFrom<Envelope> for PublicKeys
impl TryFrom<Envelope> for PublicKeys
Source§impl TryFrom<Envelope> for Request
Converts an envelope to a Request.
impl TryFrom<Envelope> for Request
Converts an envelope to a Request.
This simplified constructor doesn’t validate the request’s function.
Source§impl TryFrom<Envelope> for Response
Converts an Envelope to a Response.
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§impl TryFrom<Envelope> for SealedMessage
impl TryFrom<Envelope> for SealedMessage
impl Eq for Envelope
Auto Trait Implementations§
impl Freeze for Envelope
impl RefUnwindSafe for Envelope
impl !Send for Envelope
impl !Sync for Envelope
impl Unpin for Envelope
impl UnwindSafe for Envelope
Blanket Implementations§
§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CBORDecodable for T
impl<T> CBORDecodable for T
Source§impl<T> CBOREncodable for T
impl<T> CBOREncodable for T
§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§unsafe fn clone_to_uninit(&self, dest: *mut u8)
unsafe fn clone_to_uninit(&self, dest: *mut u8)
clone_to_uninit)Source§impl<T> EnvelopeEncodable for T
impl<T> EnvelopeEncodable for T
Source§fn into_envelope(self) -> Envelope
fn into_envelope(self) -> Envelope
Converts the value into an envelope by using its Into<Envelope>
implementation.
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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