pub mod builder;
pub mod headers;
pub mod parse;
pub mod seal;
pub mod verify;
use crate::{
ArcOutput, AuthenticationResults, DkimResult,
common::{
crypto::{Algorithm, Sha256, SigningKey},
headers::Header,
verify::VerifySignature,
},
dkim::{Canonicalization, NeedDomain},
};
#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct ArcSealer<T: SigningKey<Hasher = Sha256>, State = NeedDomain> {
_state: std::marker::PhantomData<State>,
pub(crate) key: T,
pub(crate) signature: Signature,
pub(crate) seal: Seal,
}
#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct Signature {
pub i: u32,
pub a: Algorithm,
pub d: String,
pub s: String,
pub b: Vec<u8>,
pub bh: Vec<u8>,
pub h: Vec<String>,
pub z: Vec<String>,
pub l: u64,
pub x: u64,
pub t: u64,
pub ch: Canonicalization,
pub cb: Canonicalization,
}
#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct Seal {
pub i: u32,
pub a: Algorithm,
pub b: Vec<u8>,
pub d: String,
pub s: String,
pub t: u64,
pub cv: ChainValidation,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Results {
pub i: u32,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ArcSet<'x> {
pub signature: Signature,
pub seal: Seal,
pub results: &'x AuthenticationResults<'x>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Set<'x> {
pub signature: Header<'x, &'x Signature>,
pub seal: Header<'x, &'x Seal>,
pub results: Header<'x, &'x Results>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub enum ChainValidation {
#[default]
None,
Fail,
Pass,
}
impl VerifySignature for Signature {
fn signature(&self) -> &[u8] {
&self.b
}
fn algorithm(&self) -> Algorithm {
self.a
}
fn selector(&self) -> &str {
&self.s
}
fn domain(&self) -> &str {
&self.d
}
}
impl VerifySignature for Seal {
fn signature(&self) -> &[u8] {
&self.b
}
fn algorithm(&self) -> Algorithm {
self.a
}
fn selector(&self) -> &str {
&self.s
}
fn domain(&self) -> &str {
&self.d
}
}
impl<'x> ArcOutput<'x> {
pub fn with_result(mut self, result: DkimResult) -> Self {
self.result = result;
self
}
pub fn with_set(mut self, set: Set<'x>) -> Self {
self.set.push(set);
self
}
pub fn can_be_sealed(&self) -> bool {
self.set.is_empty() || self.set.last().unwrap().seal.header.cv != ChainValidation::Fail
}
}
impl Default for ArcOutput<'_> {
fn default() -> Self {
Self {
result: DkimResult::None,
set: Vec::new(),
}
}
}