Skip to main content

mini_mail_auth/dkim/
sign.rs

1use super::{canonicalize::CanonicalHeaders, DkimSigner, Done, Signature};
2use crate::{
3    common::{
4        crypto::SigningKey,
5        headers::{HeaderIterator, HeaderStream, Writable, Writer},
6    },
7    Error,
8};
9use base64::{engine::general_purpose::STANDARD as BASE64_STANDARD, Engine as _};
10use std::time::SystemTime;
11
12impl<T: SigningKey> DkimSigner<T, Done> {
13    pub fn sign(&self, message: &[u8]) -> crate::Result<Signature> {
14        self.sign_stream(
15            HeaderIterator::new(message),
16            SystemTime::now()
17                .duration_since(SystemTime::UNIX_EPOCH)
18                .map(|d| d.as_secs())
19                .unwrap_or(0),
20        )
21    }
22
23    fn sign_stream<'x>(
24        &self,
25        message: impl HeaderStream<'x>,
26        now: u64,
27    ) -> crate::Result<Signature> {
28        let (body_len, canonical_headers, signed_headers, canonical_body) =
29            self.template.canonicalize(message);
30
31        if signed_headers.is_empty() {
32            return Err(Error::NoHeadersFound);
33        }
34
35        let mut signature = self.template.clone();
36        let body_hash = self.key.hash(canonical_body);
37        signature.bh = BASE64_STANDARD.encode(body_hash.as_ref()).into_bytes();
38        signature.t = now;
39        signature.h = signed_headers;
40        if signature.l > 0 {
41            signature.l = body_len as u64;
42        }
43
44        let b = self.key.sign(SignableMessage {
45            headers: canonical_headers,
46            signature: &signature,
47        })?;
48
49        signature.b = BASE64_STANDARD.encode(&b).into_bytes();
50
51        Ok(signature)
52    }
53}
54
55pub(super) struct SignableMessage<'a> {
56    headers: CanonicalHeaders<'a>,
57    signature: &'a Signature,
58}
59
60impl Writable for SignableMessage<'_> {
61    fn write(self, writer: &mut impl Writer) {
62        self.headers.write(writer);
63        self.signature.write(writer, false);
64    }
65}