use alloc::vec::Vec;
use core::marker::PhantomData;
use future_form::FutureForm;
use crate::{
codec::{Decode, Encode},
signature::{AsyncSigner, SignaturePrimitive, Signer},
verified::Verified,
};
pub struct Signed<T, S: SignaturePrimitive, C> {
issuer: S::VerifyingKey,
signature: S::Signature,
encoded_payload: Vec<u8>,
_marker: PhantomData<fn() -> (T, C)>,
}
impl<T, S: SignaturePrimitive, C> Clone for Signed<T, S, C>
where
S::VerifyingKey: Clone,
S::Signature: Clone,
{
fn clone(&self) -> Self {
Self {
issuer: self.issuer.clone(),
signature: self.signature.clone(),
encoded_payload: self.encoded_payload.clone(),
_marker: PhantomData,
}
}
}
impl<T, S: SignaturePrimitive, C> PartialEq for Signed<T, S, C>
where
S::VerifyingKey: PartialEq,
S::Signature: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.issuer == other.issuer
&& self.signature == other.signature
&& self.encoded_payload == other.encoded_payload
}
}
impl<T, S: SignaturePrimitive, C> Eq for Signed<T, S, C>
where
S::VerifyingKey: Eq,
S::Signature: Eq,
{
}
impl<T, S: SignaturePrimitive, C> core::hash::Hash for Signed<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.issuer.hash(state);
self.signature.hash(state);
self.encoded_payload.hash(state);
}
}
impl<T, S: SignaturePrimitive, C> core::fmt::Debug for Signed<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("Signed")
.field("issuer", &self.issuer)
.field("signature", &self.signature)
.field("encoded_payload", &self.encoded_payload)
.finish()
}
}
impl<T, S: SignaturePrimitive, C> Signed<T, S, C> {
#[must_use]
pub(crate) fn new(
issuer: S::VerifyingKey,
signature: S::Signature,
encoded_payload: Vec<u8>,
) -> Self {
Self {
issuer,
signature,
encoded_payload,
_marker: PhantomData,
}
}
#[must_use]
#[allow(clippy::expect_used)] pub fn seal<K: Signer<S>>(signer: &K, payload: &T) -> Self
where
C: Encode<T>,
{
let encoded = C::encode(payload).expect("encoding failed");
let signature = signer.sign(&encoded);
Self::new(signer.verifying_key(), signature, encoded)
}
#[allow(clippy::expect_used)] pub async fn seal_async<F: FutureForm, K: AsyncSigner<S, F>>(signer: &K, payload: &T) -> Self
where
C: Encode<T>,
{
let encoded = C::encode(payload).expect("encoding failed");
let signature = signer.sign(&encoded).await;
Self::new(signer.verifying_key(), signature, encoded)
}
#[allow(clippy::expect_used)] pub fn seal_verified<K: Signer<S>>(signer: &K, payload: T) -> Verified<T, S, C>
where
C: Encode<T>,
{
let encoded = C::encode(&payload).expect("encoding failed");
let signature = signer.sign(&encoded);
let envelope = Self::new(signer.verifying_key(), signature, encoded);
Verified::new(envelope, payload)
}
#[allow(clippy::expect_used)] pub async fn seal_verified_async<F: FutureForm, K: AsyncSigner<S, F>>(
signer: &K,
payload: T,
) -> Verified<T, S, C>
where
C: Encode<T>,
{
let encoded = C::encode(&payload).expect("encoding failed");
let signature = signer.sign(&encoded).await;
let envelope = Self::new(signer.verifying_key(), signature, encoded);
Verified::new(envelope, payload)
}
pub fn try_verify(&self) -> Result<Verified<T, S, C>, VerificationError>
where
C: Decode<T>,
S::VerifyingKey: Clone,
S::Signature: Clone,
{
S::verify(&self.issuer, &self.encoded_payload, &self.signature)
.map_err(|_| VerificationError::InvalidSignature)?;
let payload =
C::decode(&self.encoded_payload).map_err(|_| VerificationError::DecodeError)?;
Ok(Verified::new(self.clone(), payload))
}
pub fn into_verified(self) -> Result<Verified<T, S, C>, VerificationError>
where
C: Decode<T>,
{
S::verify(&self.issuer, &self.encoded_payload, &self.signature)
.map_err(|_| VerificationError::InvalidSignature)?;
let payload =
C::decode(&self.encoded_payload).map_err(|_| VerificationError::DecodeError)?;
Ok(Verified::new(self, payload))
}
#[must_use]
pub const fn issuer(&self) -> &S::VerifyingKey {
&self.issuer
}
#[must_use]
pub const fn signature(&self) -> &S::Signature {
&self.signature
}
#[must_use]
pub fn encoded_payload(&self) -> &[u8] {
&self.encoded_payload
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum VerificationError {
InvalidSignature,
DecodeError,
}
impl core::fmt::Display for VerificationError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::InvalidSignature => write!(f, "invalid signature"),
Self::DecodeError => write!(f, "payload decode error"),
}
}
}
pub trait SignedUnchecked<T, S: SignaturePrimitive, C> {
fn from_unchecked_parts(
issuer: S::VerifyingKey,
signature: S::Signature,
encoded_payload: Vec<u8>,
) -> Self;
}
impl<T, S: SignaturePrimitive, C> SignedUnchecked<T, S, C> for Signed<T, S, C> {
fn from_unchecked_parts(
issuer: S::VerifyingKey,
signature: S::Signature,
encoded_payload: Vec<u8>,
) -> Self {
Self::new(issuer, signature, encoded_payload)
}
}
#[cfg(feature = "serde")]
impl<T, S: SignaturePrimitive, C> serde::Serialize for Signed<T, S, C>
where
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("Signed", 3)?;
state.serialize_field("issuer", &self.issuer)?;
state.serialize_field("signature", &self.signature)?;
state.serialize_field("encoded_payload", &self.encoded_payload)?;
state.end()
}
}
#[cfg(feature = "serde")]
impl<'de, T, S: SignaturePrimitive, C> serde::Deserialize<'de> for Signed<T, S, C>
where
S::VerifyingKey: serde::Deserialize<'de>,
S::Signature: serde::Deserialize<'de>,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
use serde::de::{MapAccess, Visitor};
struct SignedVisitor<T, S: SignaturePrimitive, C>(PhantomData<(T, S, C)>);
impl<'de, T, S: SignaturePrimitive, C> Visitor<'de> for SignedVisitor<T, S, C>
where
S::VerifyingKey: serde::Deserialize<'de>,
S::Signature: serde::Deserialize<'de>,
{
type Value = Signed<T, S, C>;
fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter.write_str("struct Signed")
}
fn visit_map<V: MapAccess<'de>>(self, mut map: V) -> Result<Signed<T, S, C>, V::Error> {
let mut issuer = None;
let mut signature = None;
let mut encoded_payload = None;
while let Some(key) = map.next_key::<&str>()? {
match key {
"issuer" => issuer = Some(map.next_value()?),
"signature" => signature = Some(map.next_value()?),
"encoded_payload" => encoded_payload = Some(map.next_value()?),
_ => {
let _: serde::de::IgnoredAny = map.next_value()?;
}
}
}
let issuer = issuer.ok_or_else(|| serde::de::Error::missing_field("issuer"))?;
let signature =
signature.ok_or_else(|| serde::de::Error::missing_field("signature"))?;
let encoded_payload = encoded_payload
.ok_or_else(|| serde::de::Error::missing_field("encoded_payload"))?;
Ok(Signed::new(issuer, signature, encoded_payload))
}
}
const FIELDS: &[&str] = &["issuer", "signature", "encoded_payload"];
deserializer.deserialize_struct("Signed", FIELDS, SignedVisitor(PhantomData))
}
}
#[cfg(feature = "arbitrary")]
impl<'a, T, S: SignaturePrimitive, C> arbitrary::Arbitrary<'a> for Signed<T, S, C>
where
S::VerifyingKey: arbitrary::Arbitrary<'a>,
S::Signature: arbitrary::Arbitrary<'a>,
{
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let issuer = S::VerifyingKey::arbitrary(u)?;
let signature = S::Signature::arbitrary(u)?;
let encoded_payload = Vec::arbitrary(u)?;
Ok(Self::new(issuer, signature, encoded_payload))
}
}
#[cfg(feature = "bolero")]
impl<T: 'static, S: SignaturePrimitive + 'static, C: 'static> bolero_generator::TypeGenerator
for Signed<T, S, C>
where
S::VerifyingKey: bolero_generator::TypeGenerator,
S::Signature: bolero_generator::TypeGenerator,
{
fn generate<D: bolero_generator::Driver>(driver: &mut D) -> Option<Self> {
let issuer = S::VerifyingKey::generate(driver)?;
let signature = S::Signature::generate(driver)?;
let encoded_payload = Vec::generate(driver)?;
Some(Self::new(issuer, signature, encoded_payload))
}
}
#[cfg(feature = "proptest")]
impl<T: 'static, S: SignaturePrimitive + 'static, C: 'static> proptest::arbitrary::Arbitrary
for Signed<T, S, C>
where
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::<S::VerifyingKey>(),
any::<S::Signature>(),
proptest::collection::vec(any::<u8>(), 0..256),
)
.prop_map(|(issuer, signature, encoded_payload)| {
Self::new(issuer, signature, encoded_payload)
})
.boxed()
}
}
#[cfg(feature = "rkyv")]
pub mod archive {
use super::{SignaturePrimitive, Signed};
use alloc::vec::Vec;
use rkyv::{Archive, Archived, Deserialize, Serialize, rancor::Fallible};
impl<T, S: SignaturePrimitive, C> Archive for Signed<T, S, C>
where
S::VerifyingKey: Archive,
S::Signature: Archive,
{
type Archived = ArchivedSigned<S::VerifyingKey, S::Signature>;
type Resolver = SignedResolver<S::VerifyingKey, S::Signature>;
fn resolve(&self, resolver: Self::Resolver, out: rkyv::Place<Self::Archived>) {
let helper = SignedHelper {
issuer: self.issuer.clone(),
signature: self.signature.clone(),
encoded_payload: self.encoded_payload.clone(),
};
helper.resolve(resolver, out);
}
}
impl<T, S: SignaturePrimitive, C, Ser> Serialize<Ser> for Signed<T, S, C>
where
S::VerifyingKey: Serialize<Ser>,
S::Signature: Serialize<Ser>,
Ser: Fallible + rkyv::ser::Allocator + rkyv::ser::Writer + ?Sized,
{
fn serialize(&self, serializer: &mut Ser) -> Result<Self::Resolver, Ser::Error> {
let helper = SignedHelper {
issuer: self.issuer.clone(),
signature: self.signature.clone(),
encoded_payload: self.encoded_payload.clone(),
};
helper.serialize(serializer)
}
}
impl<T, S: SignaturePrimitive, C, D> Deserialize<Signed<T, S, C>, D>
for ArchivedSigned<S::VerifyingKey, S::Signature>
where
S::VerifyingKey: Archive,
S::Signature: Archive,
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<Signed<T, S, C>, D::Error> {
let helper: SignedHelper<S::VerifyingKey, S::Signature> =
<ArchivedSigned<S::VerifyingKey, S::Signature> as Deserialize<
SignedHelper<S::VerifyingKey, S::Signature>,
D,
>>::deserialize(self, deserializer)?;
Ok(Signed::new(
helper.issuer,
helper.signature,
helper.encoded_payload,
))
}
}
#[derive(Debug, Archive, Serialize, Deserialize)]
pub struct SignedHelper<VerifyingKey, Signature> {
issuer: VerifyingKey,
signature: Signature,
encoded_payload: Vec<u8>,
}
pub type ArchivedSigned<VerifyingKey, Signature> =
ArchivedSignedHelper<VerifyingKey, Signature>;
pub type SignedResolver<VerifyingKey, Signature> =
SignedHelperResolver<VerifyingKey, Signature>;
}