Commit
Author: Dirkjan Ochtman [dirkjan@ochtman.nl]
Hash: 56ae25fa5dfa63a6e7c36b79473e974c79a60ae9
Timestamp: Wed, 14 Dec 2022 12:50:37 +0000 (1 year ago)

+55 -19 +/-3 browse
Add local trait to abstract over hashing
1diff --git a/src/arc/seal.rs b/src/arc/seal.rs
2index 88561f3..6835c16 100644
3--- a/src/arc/seal.rs
4+++ b/src/arc/seal.rs
5 @@ -8,13 +8,16 @@
6 * except according to those terms.
7 */
8
9- use std::{io::Write, time::SystemTime};
10+ use std::time::SystemTime;
11
12 use mail_builder::encoders::base64::base64_encode;
13- use sha2::{Digest, Sha256};
14+ use sha2::Sha256;
15
16 use crate::{
17- common::{crypto::SigningKey, headers::Writer},
18+ common::{
19+ crypto::{HashContext, SigningKey},
20+ headers::Writer,
21+ },
22 dkim::{Canonicalization, Done},
23 ArcOutput, AuthenticatedMessage, AuthenticationResults, DkimResult, Error,
24 };
25 @@ -72,7 +75,7 @@ impl<T: SigningKey<Hasher = Sha256>> ArcSealer<T, Done> {
26 .duration_since(SystemTime::UNIX_EPOCH)
27 .map(|d| d.as_secs())
28 .unwrap_or(0);
29- set.signature.bh = base64_encode(&body_hasher.finalize())?;
30+ set.signature.bh = base64_encode(body_hasher.finish().as_ref())?;
31 set.signature.t = now;
32 set.signature.x = if set.signature.x > 0 {
33 now + set.signature.x
34 @@ -88,11 +91,11 @@ impl<T: SigningKey<Hasher = Sha256>> ArcSealer<T, Done> {
35 set.signature.write(&mut header_hasher, false);
36
37 // Sign
38- let b = self.key.sign(&header_hasher.finalize())?;
39+ let b = self.key.sign(header_hasher.finish())?;
40 set.signature.b = base64_encode(&b)?;
41
42 // Hash ARC chain
43- let mut header_hasher = Sha256::new();
44+ let mut header_hasher = self.key.hasher();
45 if !arc_output.set.is_empty() {
46 Canonicalization::Relaxed.canonicalize_headers(
47 &mut arc_output.set.iter().flat_map(|set| {
48 @@ -109,11 +112,11 @@ impl<T: SigningKey<Hasher = Sha256>> ArcSealer<T, Done> {
49 // Hash ARC headers for the current instance
50 set.results.write(&mut header_hasher, set.seal.i, false);
51 set.signature.write(&mut header_hasher, false);
52- header_hasher.write_all(b"\r\n")?;
53+ header_hasher.write(b"\r\n");
54 set.seal.write(&mut header_hasher, false);
55
56 // Seal
57- let b = self.key.sign(&header_hasher.finalize())?;
58+ let b = self.key.sign(header_hasher.finish())?;
59 set.seal.b = base64_encode(&b)?;
60
61 Ok(set)
62 diff --git a/src/common/crypto.rs b/src/common/crypto.rs
63index 5e206d2..a897c9b 100644
64--- a/src/common/crypto.rs
65+++ b/src/common/crypto.rs
66 @@ -14,9 +14,9 @@ use crate::{dkim::Canonicalization, Error, Result};
67 use super::headers::Writer;
68
69 pub trait SigningKey {
70- type Hasher: Digest + Writer;
71+ type Hasher: HashContext;
72
73- fn sign(&self, data: &Output<Self::Hasher>) -> Result<Vec<u8>>;
74+ fn sign(&self, data: HashOutput) -> Result<Vec<u8>>;
75
76 fn hasher(&self) -> Self::Hasher {
77 Self::Hasher::new()
78 @@ -58,9 +58,12 @@ impl<T: Digest + AssociatedOid + io::Write> RsaKey<T> {
79 impl SigningKey for RsaKey<Sha1> {
80 type Hasher = Sha1;
81
82- fn sign(&self, data: &Output<Self::Hasher>) -> Result<Vec<u8>> {
83+ fn sign(&self, data: HashOutput) -> Result<Vec<u8>> {
84 self.inner
85- .sign(PaddingScheme::new_pkcs1v15_sign::<Self::Hasher>(), data)
86+ .sign(
87+ PaddingScheme::new_pkcs1v15_sign::<Self::Hasher>(),
88+ data.as_ref(),
89+ )
90 .map_err(|err| Error::CryptoError(err.to_string()))
91 }
92
93 @@ -72,9 +75,12 @@ impl SigningKey for RsaKey<Sha1> {
94 impl SigningKey for RsaKey<Sha256> {
95 type Hasher = Sha256;
96
97- fn sign(&self, data: &Output<Self::Hasher>) -> Result<Vec<u8>> {
98+ fn sign(&self, data: HashOutput) -> Result<Vec<u8>> {
99 self.inner
100- .sign(PaddingScheme::new_pkcs1v15_sign::<Self::Hasher>(), data)
101+ .sign(
102+ PaddingScheme::new_pkcs1v15_sign::<Self::Hasher>(),
103+ data.as_ref(),
104+ )
105 .map_err(|err| Error::CryptoError(err.to_string()))
106 }
107
108 @@ -104,7 +110,7 @@ impl Ed25519Key {
109 impl SigningKey for Ed25519Key {
110 type Hasher = Sha256;
111
112- fn sign(&self, data: &Output<Self::Hasher>) -> Result<Vec<u8>> {
113+ fn sign(&self, data: HashOutput) -> Result<Vec<u8>> {
114 Ok(self.inner.sign(data.as_ref()).to_bytes().to_vec())
115 }
116
117 @@ -227,6 +233,31 @@ impl Writer for Sha256 {
118 }
119 }
120
121+ pub trait HashContext: Writer + Sized {
122+ fn new() -> Self;
123+ fn finish(self) -> HashOutput;
124+ }
125+
126+ impl HashContext for Sha1 {
127+ fn new() -> Self {
128+ <Self as Digest>::new()
129+ }
130+
131+ fn finish(self) -> HashOutput {
132+ HashOutput::Sha1(self.finalize())
133+ }
134+ }
135+
136+ impl HashContext for Sha256 {
137+ fn new() -> Self {
138+ <Self as Digest>::new()
139+ }
140+
141+ fn finish(self) -> HashOutput {
142+ HashOutput::Sha256(self.finalize())
143+ }
144+ }
145+
146 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
147 #[repr(u64)]
148 pub enum HashAlgorithm {
149 diff --git a/src/dkim/sign.rs b/src/dkim/sign.rs
150index d264b1a..9203449 100644
151--- a/src/dkim/sign.rs
152+++ b/src/dkim/sign.rs
153 @@ -11,10 +11,12 @@
154 use std::time::SystemTime;
155
156 use mail_builder::encoders::base64::base64_encode;
157- use sha1::Digest;
158
159 use super::{DkimSigner, Done, Signature};
160- use crate::{common::crypto::SigningKey, Error};
161+ use crate::{
162+ common::crypto::{HashContext, SigningKey},
163+ Error,
164+ };
165
166 impl<T: SigningKey> DkimSigner<T, Done> {
167 /// Signs a message.
168 @@ -44,7 +46,7 @@ impl<T: SigningKey> DkimSigner<T, Done> {
169
170 // Create Signature
171 let mut signature = self.template.clone();
172- signature.bh = base64_encode(&body_hasher.finalize())?;
173+ signature.bh = base64_encode(&body_hasher.finish().as_ref())?;
174 signature.t = now;
175 signature.x = if signature.x > 0 {
176 now + signature.x
177 @@ -60,7 +62,7 @@ impl<T: SigningKey> DkimSigner<T, Done> {
178 signature.write(&mut header_hasher, false);
179
180 // Sign
181- let b = self.key.sign(&header_hasher.finalize())?;
182+ let b = self.key.sign(header_hasher.finish())?;
183
184 // Encode
185 signature.b = base64_encode(&b)?;