Skip to main content

email_auth/dkim/
types.rs

1/// DKIM signing/verification algorithm.
2#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3pub enum Algorithm {
4    /// RSA with SHA-1 (verify only, MUST NOT sign)
5    RsaSha1,
6    /// RSA with SHA-256 (preferred)
7    RsaSha256,
8    /// Ed25519 with SHA-256 (RFC 8463)
9    Ed25519Sha256,
10}
11
12impl Algorithm {
13    /// Parse algorithm string (case-insensitive).
14    pub fn parse(s: &str) -> Option<Self> {
15        match s.to_ascii_lowercase().as_str() {
16            "rsa-sha1" => Some(Algorithm::RsaSha1),
17            "rsa-sha256" => Some(Algorithm::RsaSha256),
18            "ed25519-sha256" => Some(Algorithm::Ed25519Sha256),
19            _ => None,
20        }
21    }
22
23    /// Returns the hash algorithm used by this signing algorithm.
24    pub fn hash_algorithm(&self) -> HashAlgorithm {
25        match self {
26            Algorithm::RsaSha1 => HashAlgorithm::Sha1,
27            Algorithm::RsaSha256 | Algorithm::Ed25519Sha256 => HashAlgorithm::Sha256,
28        }
29    }
30}
31
32/// Canonicalization method for headers or body.
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub enum CanonicalizationMethod {
35    Simple,
36    Relaxed,
37}
38
39impl CanonicalizationMethod {
40    pub fn parse(s: &str) -> Option<Self> {
41        match s.to_ascii_lowercase().as_str() {
42            "simple" => Some(CanonicalizationMethod::Simple),
43            "relaxed" => Some(CanonicalizationMethod::Relaxed),
44            _ => None,
45        }
46    }
47}
48
49/// Parsed DKIM-Signature header.
50#[derive(Debug, Clone, PartialEq, Eq)]
51pub struct DkimSignature {
52    pub version: u8,
53    pub algorithm: Algorithm,
54    pub signature: Vec<u8>,
55    pub body_hash: Vec<u8>,
56    pub header_canonicalization: CanonicalizationMethod,
57    pub body_canonicalization: CanonicalizationMethod,
58    pub domain: String,
59    pub signed_headers: Vec<String>,
60    pub auid: String,
61    pub body_length: Option<u64>,
62    pub selector: String,
63    pub timestamp: Option<u64>,
64    pub expiration: Option<u64>,
65    pub copied_headers: Option<Vec<String>>,
66    pub raw_header: String,
67}
68
69/// Key type for DKIM public key records.
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub enum KeyType {
72    Rsa,
73    Ed25519,
74}
75
76impl KeyType {
77    pub fn parse(s: &str) -> Option<Self> {
78        match s.to_ascii_lowercase().as_str() {
79            "rsa" => Some(KeyType::Rsa),
80            "ed25519" => Some(KeyType::Ed25519),
81            _ => None,
82        }
83    }
84}
85
86/// Hash algorithm constraint from key h= tag.
87#[derive(Debug, Clone, Copy, PartialEq, Eq)]
88pub enum HashAlgorithm {
89    Sha1,
90    Sha256,
91}
92
93impl HashAlgorithm {
94    pub fn parse(s: &str) -> Option<Self> {
95        match s.to_ascii_lowercase().as_str() {
96            "sha1" => Some(HashAlgorithm::Sha1),
97            "sha256" => Some(HashAlgorithm::Sha256),
98            _ => None,
99        }
100    }
101}
102
103/// Key flags from t= tag in DNS key record.
104#[derive(Debug, Clone, Copy, PartialEq, Eq)]
105pub enum KeyFlag {
106    /// t=y: testing mode
107    Testing,
108    /// t=s: strict mode (i= must exactly equal d=)
109    Strict,
110}
111
112/// DKIM verification result.
113#[derive(Debug, Clone, PartialEq, Eq)]
114pub enum DkimResult {
115    /// Signature verified successfully.
116    Pass {
117        domain: String,
118        selector: String,
119        testing: bool,
120    },
121    /// Cryptographic verification failed.
122    Fail {
123        kind: FailureKind,
124        detail: String,
125    },
126    /// Permanent structural/configuration error.
127    PermFail {
128        kind: PermFailKind,
129        detail: String,
130    },
131    /// Transient error (DNS timeout).
132    TempFail {
133        reason: String,
134    },
135    /// No DKIM-Signature header present.
136    None,
137}
138
139/// Cryptographic failure kinds.
140#[derive(Debug, Clone, Copy, PartialEq, Eq)]
141pub enum FailureKind {
142    BodyHashMismatch,
143    SignatureVerificationFailed,
144}
145
146/// Permanent failure kinds.
147#[derive(Debug, Clone, Copy, PartialEq, Eq)]
148pub enum PermFailKind {
149    MalformedSignature,
150    KeyRevoked,
151    KeyNotFound,
152    ExpiredSignature,
153    AlgorithmMismatch,
154    HashNotPermitted,
155    ServiceTypeMismatch,
156    StrictModeViolation,
157    DomainMismatch,
158}