Something went wrong. Try again.
Typelevel cryptographic algo tracking crates.io/crates/evidence
typelevel cryptography util
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420//! Verified payloads — witnesses of successful signature verification.//!//! [`Verified<T, S, C>`] is a witness type that proves a signature has been//! successfully verified. It is the _only_ way to access the payload of a//! [`Signed<T, S, C>`](crate::signed::Signed).//!//! # Construction//!//! `Verified` can only be constructed via [`Signed::try_verify`](crate::signed::Signed::try_verify).//! This ensures that you cannot accidentally use unverified data.//!//! For testing or trusted contexts, the [`VerifiedUnchecked`] extension trait//! provides an escape hatch, but it must be explicitly imported.//!//! # Example//!//! ```//! # #[cfg(feature = "ed25519")]//! # {//! use evidence::{codec::Identity, signature::{ed25519::Ed25519, Signer}, signed::Signed, verified::Verified};//!//! let signing_key = ed25519_dalek::SigningKey::from_bytes(&[1u8; 32]);//! let data = b"hello world";//!//! let signed: Signed<[u8; 11], Ed25519, Identity> = Signed::seal(&signing_key, data);//! let verified: Verified<[u8; 11], Ed25519, Identity> = signed.try_verify().unwrap();//!//! // Now we have proven access to the payload//! assert_eq!(verified.payload(), data);//! assert_eq!(verified.issuer(), &signing_key.verifying_key());//!//! // The original Signed envelope is retained//! assert_eq!(verified.signed(), &signed);//! # }//! ```
use crate::{signature::SignaturePrimitive, signed::Signed};
/// A verified payload — proof that signature verification succeeded.////// This type is only constructible via:/// - [`Signed::try_verify`](crate::signed::Signed::try_verify) — verify an existing `Signed` (cloning)/// - [`Signed::into_verified`](crate::signed::Signed::into_verified) — verify an existing `Signed` (consuming)/// - [`Signed::seal_verified`](crate::signed::Signed::seal_verified) — sign and return `Verified` directly/// - [`Signed::seal_verified_async`](crate::signed::Signed::seal_verified_async) — async variant////// This ensures that you cannot accidentally use unverified data.////// The original [`Signed`] envelope is retained, so you can recover the/// encoded payload bytes, signature, and issuer key without re-signing.////// # Security Note////// `Verified<T>` should generally _not_ be serialized and sent over the wire./// Always transmit [`Signed<T>`](crate::signed::Signed) and have the recipient/// verify it themselves.pub struct Verified<T, S: SignaturePrimitive, C> { signed: Signed<T, S, C>, payload: T,}
impl<T: Clone, S: SignaturePrimitive, C> Clone for Verified<T, S, C>where S::VerifyingKey: Clone, S::Signature: Clone,{ fn clone(&self) -> Self { Self { signed: self.signed.clone(), payload: self.payload.clone(), } }}
impl<T: PartialEq, S: SignaturePrimitive, C> PartialEq for Verified<T, S, C>where S::VerifyingKey: PartialEq, S::Signature: PartialEq,{ fn eq(&self, other: &Self) -> bool { self.signed == other.signed && self.payload == other.payload }}
impl<T: Eq, S: SignaturePrimitive, C> Eq for Verified<T, S, C>where S::VerifyingKey: Eq, S::Signature: Eq,{}
impl<T: core::hash::Hash, S: SignaturePrimitive, C> core::hash::Hash for Verified<T, S, C>where S::VerifyingKey: core::hash::Hash, S::Signature: core::hash::Hash,{ fn hash<H: core::hash::Hasher>(&self, state: &mut H) { self.signed.hash(state); self.payload.hash(state); }}
impl<T: core::fmt::Debug, S: SignaturePrimitive, C> core::fmt::Debug for Verified<T, S, C>where S::VerifyingKey: core::fmt::Debug, S::Signature: core::fmt::Debug,{ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("Verified") .field("signed", &self.signed) .field("payload", &self.payload) .finish() }}
impl<T, S: SignaturePrimitive, C> Verified<T, S, C> { /// Create a verified payload from its signed envelope and decoded payload. /// /// This is `pub(crate)` — only constructible via `Signed::try_verify`, /// `Signed::into_verified`, `Signed::seal_verified`, and /// `Signed::seal_verified_async`. #[must_use] pub(crate) const fn new(signed: Signed<T, S, C>, payload: T) -> Self { Self { signed, payload } }
/// Get the issuer's verifying key. /// /// This is the key that was used to verify the signature. #[must_use] pub const fn issuer(&self) -> &S::VerifyingKey { self.signed.issuer() }
/// Get a reference to the verified payload. #[must_use] pub const fn payload(&self) -> &T { &self.payload }
/// Get a reference to the original signed envelope. /// /// This provides access to the encoded payload bytes, signature, /// and issuer key without needing to re-sign. #[must_use] pub const fn signed(&self) -> &Signed<T, S, C> { &self.signed }
/// Consume the witness and return the payload. #[must_use] pub fn into_payload(self) -> T { self.payload }
/// Consume the witness and return the original signed envelope. #[must_use] pub fn into_signed(self) -> Signed<T, S, C> { self.signed }
/// Consume the witness and return the signed envelope and payload. #[must_use] pub fn into_parts(self) -> (Signed<T, S, C>, T) { (self.signed, self.payload) }}
/// Extension trait for constructing [`Verified`] without verification.////// This trait is _intentionally_ not in the prelude. Importing it is an explicit/// acknowledgment that you are bypassing the verification guarantee.////// # When to use////// - Testing with known-good data/// - Trusted internal contexts where verification happened elsewhere/// - Reconstructing from a trusted database////// # Example////// ```/// # #[cfg(feature = "ed25519")]/// # {/// use evidence::{codec::Identity, signature::ed25519::Ed25519, signed::{Signed, SignedUnchecked}, verified::{Verified, VerifiedUnchecked}};////// let key = ed25519_dalek::VerifyingKey::from_bytes(&[0u8; 32]).unwrap();/// let signature = ed25519_dalek::Signature::from_bytes(&[0u8; 64]);/// let payload = vec![1, 2, 3, 4];////// let signed: Signed<Vec<u8>, Ed25519, Identity> =/// Signed::from_unchecked_parts(key, signature, payload.clone());////// let verified: Verified<Vec<u8>, Ed25519, Identity> =/// Verified::from_unchecked_parts(signed, payload);/// # }/// ```pub trait VerifiedUnchecked<T, S: SignaturePrimitive, C> { /// Create a verified payload from a signed envelope and decoded payload. /// /// # Safety (logical) /// /// This bypasses the verification guarantee. The caller must ensure /// the payload was actually verified (e.g., in a trusted context). fn from_unchecked_parts(signed: Signed<T, S, C>, payload: T) -> Self;}
impl<T, S: SignaturePrimitive, C> VerifiedUnchecked<T, S, C> for Verified<T, S, C> { fn from_unchecked_parts(signed: Signed<T, S, C>, payload: T) -> Self { Self::new(signed, payload) }}
#[cfg(feature = "serde")]impl<T, S: SignaturePrimitive, C> serde::Serialize for Verified<T, S, C>where T: serde::Serialize, S::VerifyingKey: serde::Serialize, S::Signature: serde::Serialize,{ fn serialize<Ser: serde::Serializer>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> { use serde::ser::SerializeStruct; let mut state = serializer.serialize_struct("Verified", 2)?; state.serialize_field("signed", &self.signed)?; state.serialize_field("payload", &self.payload)?; state.end() }}
#[cfg(feature = "serde")]impl<'de, T, S: SignaturePrimitive, C> serde::Deserialize<'de> for Verified<T, S, C>where T: serde::Deserialize<'de>, S::VerifyingKey: serde::Deserialize<'de>, S::Signature: serde::Deserialize<'de>,{ fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { use core::marker::PhantomData; use serde::de::{MapAccess, Visitor};
struct VerifiedVisitor<T, S: SignaturePrimitive, C>(PhantomData<(T, S, C)>);
impl<'de, T, S: SignaturePrimitive, C> Visitor<'de> for VerifiedVisitor<T, S, C> where T: serde::Deserialize<'de>, S::VerifyingKey: serde::Deserialize<'de>, S::Signature: serde::Deserialize<'de>, { type Value = Verified<T, S, C>;
fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { formatter.write_str("struct Verified") }
fn visit_map<V: MapAccess<'de>>( self, mut map: V, ) -> Result<Verified<T, S, C>, V::Error> { let mut signed = None; let mut payload = None;
while let Some(key) = map.next_key::<&str>()? { match key { "signed" => signed = Some(map.next_value()?), "payload" => payload = Some(map.next_value()?), _ => { let _: serde::de::IgnoredAny = map.next_value()?; } } }
let signed = signed.ok_or_else(|| serde::de::Error::missing_field("signed"))?; let payload = payload.ok_or_else(|| serde::de::Error::missing_field("payload"))?;
Ok(Verified::new(signed, payload)) } }
const FIELDS: &[&str] = &["signed", "payload"]; deserializer.deserialize_struct("Verified", FIELDS, VerifiedVisitor(PhantomData)) }}
#[cfg(feature = "arbitrary")]impl<'a, T, S: SignaturePrimitive, C> arbitrary::Arbitrary<'a> for Verified<T, S, C>where T: arbitrary::Arbitrary<'a>, S::VerifyingKey: arbitrary::Arbitrary<'a>, S::Signature: arbitrary::Arbitrary<'a>,{ fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> { let signed = Signed::arbitrary(u)?; let payload = T::arbitrary(u)?; Ok(Self::new(signed, payload)) }}
#[cfg(feature = "bolero")]impl<T: 'static, S: SignaturePrimitive + 'static, C: 'static> bolero_generator::TypeGenerator for Verified<T, S, C>where T: bolero_generator::TypeGenerator, S::VerifyingKey: bolero_generator::TypeGenerator, S::Signature: bolero_generator::TypeGenerator,{ fn generate<D: bolero_generator::Driver>(driver: &mut D) -> Option<Self> { let signed = Signed::generate(driver)?; let payload = T::generate(driver)?; Some(Self::new(signed, payload)) }}
#[cfg(feature = "proptest")]impl<T: 'static, S: SignaturePrimitive + 'static, C: 'static> proptest::arbitrary::Arbitrary for Verified<T, S, C>where T: proptest::arbitrary::Arbitrary + 'static, S::VerifyingKey: proptest::arbitrary::Arbitrary + 'static, S::Signature: proptest::arbitrary::Arbitrary + 'static,{ type Parameters = (); type Strategy = proptest::strategy::BoxedStrategy<Self>;
fn arbitrary_with((): Self::Parameters) -> Self::Strategy { use proptest::prelude::*; (any::<Signed<T, S, C>>(), any::<T>()) .prop_map(|(signed, payload)| Self::new(signed, payload)) .boxed() }}
#[cfg(feature = "rkyv")]/// Zero-copy [`rkyv`] serialization support for [`Verified`].pub mod archive { use super::{SignaturePrimitive, Signed, Verified}; use alloc::vec::Vec; use rkyv::{Archive, Archived, Deserialize, Serialize, rancor::Fallible};
impl<T, S: SignaturePrimitive, C> Archive for Verified<T, S, C> where T: Archive + Clone, S::VerifyingKey: Archive + Clone, S::Signature: Archive + Clone, { type Archived = ArchivedVerified<T, S::VerifyingKey, S::Signature>; type Resolver = VerifiedResolver<T, S::VerifyingKey, S::Signature>;
fn resolve(&self, resolver: Self::Resolver, out: rkyv::Place<Self::Archived>) { let helper = VerifiedHelper { issuer: self.signed.issuer().clone(), signature: self.signed.signature().clone(), encoded_payload: self.signed.encoded_payload().to_vec(), payload: self.payload.clone(), }; helper.resolve(resolver, out); } }
impl<T, S: SignaturePrimitive, C, Ser> Serialize<Ser> for Verified<T, S, C> where T: Serialize<Ser> + Clone, S::VerifyingKey: Serialize<Ser> + Clone, S::Signature: Serialize<Ser> + Clone, Ser: Fallible + rkyv::ser::Allocator + rkyv::ser::Writer + ?Sized, { fn serialize(&self, serializer: &mut Ser) -> Result<Self::Resolver, Ser::Error> { let helper = VerifiedHelper { issuer: self.signed.issuer().clone(), signature: self.signed.signature().clone(), encoded_payload: self.signed.encoded_payload().to_vec(), payload: self.payload.clone(), }; helper.serialize(serializer) } }
impl<T, S: SignaturePrimitive, C, D> Deserialize<Verified<T, S, C>, D> for ArchivedVerified<T, S::VerifyingKey, S::Signature> where T: Archive, S::VerifyingKey: Archive, S::Signature: Archive, Archived<T>: Deserialize<T, D>, Archived<S::VerifyingKey>: Deserialize<S::VerifyingKey, D>, Archived<S::Signature>: Deserialize<S::Signature, D>, D: Fallible + ?Sized, D::Error: rkyv::rancor::Source, { fn deserialize(&self, deserializer: &mut D) -> Result<Verified<T, S, C>, D::Error> { let helper: VerifiedHelper<T, S::VerifyingKey, S::Signature> = <ArchivedVerified<T, S::VerifyingKey, S::Signature> as Deserialize< VerifiedHelper<T, S::VerifyingKey, S::Signature>, D, >>::deserialize(self, deserializer)?; let signed = Signed::new(helper.issuer, helper.signature, helper.encoded_payload); Ok(Verified::new(signed, helper.payload)) } }
/// Helper struct for rkyv serialization. /// /// The phantom type parameters from [`Verified`] are erased in the archived /// form since they only matter at compile time. #[derive(Debug, Archive, Serialize, Deserialize)] pub struct VerifiedHelper<Payload, VerifyingKey, Signature> { issuer: VerifyingKey, signature: Signature, encoded_payload: Vec<u8>, payload: Payload, }
/// Type alias for the archived form of [`Verified`]. pub type ArchivedVerified<Payload, VerifyingKey, Signature> = ArchivedVerifiedHelper<Payload, VerifyingKey, Signature>;
/// Type alias for the resolver of [`Verified`]. pub type VerifiedResolver<Payload, VerifyingKey, Signature> = VerifiedHelperResolver<Payload, VerifyingKey, Signature>;}