Commit
+172 -137 +/-6 browse
1 | diff --git a/examples/arc_seal.rs b/examples/arc_seal.rs |
2 | index 7c519a0..460b898 100644 |
3 | --- a/examples/arc_seal.rs |
4 | +++ b/examples/arc_seal.rs |
5 | @@ -10,9 +10,10 @@ |
6 | |
7 | use mail_auth::{ |
8 | arc::ArcSet, |
9 | - common::{crypto::PrivateKey, headers::HeaderWriter}, |
10 | + common::{crypto::RsaKey, headers::HeaderWriter}, |
11 | AuthenticatedMessage, AuthenticationResults, Resolver, |
12 | }; |
13 | + use sha2::Sha256; |
14 | |
15 | const TEST_MESSAGE: &str = include_str!("../resources/arc/001.txt"); |
16 | |
17 | @@ -52,7 +53,7 @@ async fn main() { |
18 | // Seal message |
19 | if arc_result.can_be_sealed() { |
20 | // Seal the e-mail message using RSA-SHA256 |
21 | - let pk_rsa = PrivateKey::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
22 | + let pk_rsa = RsaKey::<Sha256>::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
23 | let arc_set = ArcSet::new(&auth_results) |
24 | .domain("example.org") |
25 | .selector("default") |
26 | diff --git a/examples/dkim_sign.rs b/examples/dkim_sign.rs |
27 | index 1ae0e28..9bf3bfe 100644 |
28 | --- a/examples/dkim_sign.rs |
29 | +++ b/examples/dkim_sign.rs |
30 | @@ -9,10 +9,11 @@ |
31 | */ |
32 | |
33 | use mail_auth::{ |
34 | - common::{crypto::PrivateKey, headers::HeaderWriter}, |
35 | + common::{crypto::Ed25519Key, crypto::RsaKey, headers::HeaderWriter}, |
36 | dkim::Signature, |
37 | }; |
38 | use mail_parser::decoders::base64::base64_decode; |
39 | + use sha2::Sha256; |
40 | |
41 | const RSA_PRIVATE_KEY: &str = r#"-----BEGIN RSA PRIVATE KEY----- |
42 | MIICXwIBAAKBgQDwIRP/UC3SBsEmGqZ9ZJW3/DkMoGeLnQg1fWn7/zYtIxN2SnFC |
43 | @@ -42,7 +43,7 @@ I'm going to need those TPS reports ASAP. So, if you could do that, that'd be gr |
44 | |
45 | fn main() { |
46 | // Sign an e-mail message using RSA-SHA256 |
47 | - let pk_rsa = PrivateKey::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
48 | + let pk_rsa = RsaKey::<Sha256>::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
49 | let signature_rsa = Signature::new() |
50 | .headers(["From", "To", "Subject"]) |
51 | .domain("example.com") |
52 | @@ -51,7 +52,7 @@ fn main() { |
53 | .unwrap(); |
54 | |
55 | // Sign an e-mail message using ED25519-SHA256 |
56 | - let pk_ed = PrivateKey::from_ed25519( |
57 | + let pk_ed = Ed25519Key::from_bytes( |
58 | &base64_decode(ED25519_PUBLIC_KEY.as_bytes()).unwrap(), |
59 | &base64_decode(ED25519_PRIVATE_KEY.as_bytes()).unwrap(), |
60 | ) |
61 | diff --git a/src/arc/seal.rs b/src/arc/seal.rs |
62 | index 7e9af0a..cada5a8 100644 |
63 | --- a/src/arc/seal.rs |
64 | +++ b/src/arc/seal.rs |
65 | @@ -10,15 +10,12 @@ |
66 | |
67 | use std::{borrow::Cow, io::Write, time::SystemTime}; |
68 | |
69 | - use ed25519_dalek::Signer; |
70 | use mail_builder::encoders::base64::base64_encode; |
71 | - use rsa::PaddingScheme; |
72 | - use sha1::Digest; |
73 | - use sha2::Sha256; |
74 | + use sha2::{Digest, Sha256}; |
75 | |
76 | use crate::{ |
77 | - common::crypto::Algorithm, dkim::Canonicalization, ArcOutput, AuthenticatedMessage, |
78 | - AuthenticationResults, DkimResult, Error, PrivateKey, |
79 | + common::crypto::SigningKey, dkim::Canonicalization, ArcOutput, AuthenticatedMessage, |
80 | + AuthenticationResults, DkimResult, Error, |
81 | }; |
82 | |
83 | use super::{ArcSet, ChainValidation, Seal, Signature}; |
84 | @@ -36,20 +33,15 @@ impl<'x> ArcSet<'x> { |
85 | mut self, |
86 | message: &'x AuthenticatedMessage<'x>, |
87 | arc_output: &ArcOutput, |
88 | - with_key: &PrivateKey, |
89 | + with_key: &impl SigningKey<Hasher = Sha256>, |
90 | ) -> crate::Result<Self> { |
91 | if !arc_output.can_be_sealed() { |
92 | return Err(Error::ARCInvalidCV); |
93 | } |
94 | |
95 | // Set a= |
96 | - if let PrivateKey::Ed25519(_) = with_key { |
97 | - self.signature.a = Algorithm::Ed25519Sha256; |
98 | - self.seal.a = Algorithm::Ed25519Sha256; |
99 | - } else { |
100 | - self.signature.a = Algorithm::RsaSha256; |
101 | - self.seal.a = Algorithm::RsaSha256; |
102 | - } |
103 | + self.signature.a = with_key.algorithm(); |
104 | + self.seal.a = with_key.algorithm(); |
105 | |
106 | // Set i= and cv= |
107 | if arc_output.set.is_empty() { |
108 | @@ -67,8 +59,8 @@ impl<'x> ArcSet<'x> { |
109 | } |
110 | |
111 | // Create hashes |
112 | - let mut body_hasher = Sha256::new(); |
113 | - let mut header_hasher = Sha256::new(); |
114 | + let mut body_hasher = with_key.hasher(); |
115 | + let mut header_hasher = with_key.hasher(); |
116 | |
117 | // Canonicalize headers and body |
118 | let (body_len, signed_headers) = |
119 | @@ -100,17 +92,7 @@ impl<'x> ArcSet<'x> { |
120 | self.signature.write(&mut header_hasher, false)?; |
121 | |
122 | // Sign |
123 | - let b = match with_key { |
124 | - PrivateKey::Rsa(private_key) => private_key |
125 | - .sign( |
126 | - PaddingScheme::new_pkcs1v15_sign::<Sha256>(), |
127 | - &header_hasher.finalize(), |
128 | - ) |
129 | - .map_err(|err| Error::CryptoError(err.to_string()))?, |
130 | - PrivateKey::Ed25519(key_pair) => { |
131 | - key_pair.sign(&header_hasher.finalize()).to_bytes().to_vec() |
132 | - } |
133 | - }; |
134 | + let b = with_key.sign(&header_hasher.finalize())?; |
135 | self.signature.b = base64_encode(&b)?; |
136 | |
137 | // Hash ARC chain |
138 | @@ -135,17 +117,7 @@ impl<'x> ArcSet<'x> { |
139 | self.seal.write(&mut header_hasher, false)?; |
140 | |
141 | // Seal |
142 | - let b = match with_key { |
143 | - PrivateKey::Rsa(private_key) => private_key |
144 | - .sign( |
145 | - PaddingScheme::new_pkcs1v15_sign::<Sha256>(), |
146 | - &header_hasher.finalize(), |
147 | - ) |
148 | - .map_err(|err| Error::CryptoError(err.to_string()))?, |
149 | - PrivateKey::Ed25519(key_pair) => { |
150 | - key_pair.sign(&header_hasher.finalize()).to_bytes().to_vec() |
151 | - } |
152 | - }; |
153 | + let b = with_key.sign(&header_hasher.finalize())?; |
154 | self.seal.b = base64_encode(&b)?; |
155 | |
156 | Ok(self) |
157 | @@ -242,12 +214,17 @@ mod test { |
158 | use std::time::{Duration, Instant}; |
159 | |
160 | use mail_parser::decoders::base64::base64_decode; |
161 | + use sha2::Sha256; |
162 | |
163 | use crate::{ |
164 | arc::ArcSet, |
165 | - common::{headers::HeaderWriter, parse::TxtRecordParser}, |
166 | + common::{ |
167 | + crypto::{Ed25519Key, RsaKey, SigningKey}, |
168 | + headers::HeaderWriter, |
169 | + parse::TxtRecordParser, |
170 | + }, |
171 | dkim::{DomainKey, Signature}, |
172 | - AuthenticatedMessage, AuthenticationResults, DkimResult, PrivateKey, Resolver, |
173 | + AuthenticatedMessage, AuthenticationResults, DkimResult, Resolver, |
174 | }; |
175 | |
176 | const RSA_PRIVATE_KEY: &str = r#"-----BEGIN RSA PRIVATE KEY----- |
177 | @@ -303,8 +280,8 @@ GMot/L2x0IYyMLAz6oLWh2hm7zwtb0CgOrPo1ke44hFYnfc= |
178 | ); |
179 | |
180 | // Create private keys |
181 | - let pk_rsa = PrivateKey::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
182 | - let pk_ed = PrivateKey::from_ed25519( |
183 | + let pk_rsa = RsaKey::<Sha256>::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
184 | + let pk_ed = Ed25519Key::from_bytes( |
185 | &base64_decode(ED25519_PUBLIC_KEY.rsplit_once("p=").unwrap().1.as_bytes()).unwrap(), |
186 | &base64_decode(ED25519_PRIVATE_KEY.as_bytes()).unwrap(), |
187 | ) |
188 | @@ -336,7 +313,7 @@ GMot/L2x0IYyMLAz6oLWh2hm7zwtb0CgOrPo1ke44hFYnfc= |
189 | raw_message: &str, |
190 | d: &str, |
191 | s: &str, |
192 | - pk: &PrivateKey, |
193 | + pk: &impl SigningKey<Hasher = Sha256>, |
194 | ) -> String { |
195 | let message = AuthenticatedMessage::parse(raw_message.as_bytes()).unwrap(); |
196 | let dkim_result = resolver.verify_dkim(&message).await; |
197 | diff --git a/src/common/crypto.rs b/src/common/crypto.rs |
198 | index 8edf434..2d4a4d1 100644 |
199 | --- a/src/common/crypto.rs |
200 | +++ b/src/common/crypto.rs |
201 | @@ -1,38 +1,113 @@ |
202 | - use rsa::{RsaPrivateKey, pkcs1::DecodeRsaPrivateKey}; |
203 | + use std::{io, marker::PhantomData}; |
204 | |
205 | - use crate::Error; |
206 | + use ed25519_dalek::Signer; |
207 | + use rsa::{ |
208 | + pkcs1::DecodeRsaPrivateKey, |
209 | + pkcs8::{AssociatedOid, ObjectIdentifier}, |
210 | + PaddingScheme, RsaPrivateKey, |
211 | + }; |
212 | + use sha1::{digest::Output, Sha1}; |
213 | + use sha2::{digest::Digest, Sha256}; |
214 | + |
215 | + use crate::{Error, Result}; |
216 | + |
217 | + pub trait SigningKey { |
218 | + type Hasher: Digest + AssociatedOid + io::Write; |
219 | + |
220 | + fn sign(&self, data: &Output<Self::Hasher>) -> Result<Vec<u8>>; |
221 | + |
222 | + fn hasher(&self) -> Self::Hasher { |
223 | + Self::Hasher::new() |
224 | + } |
225 | + |
226 | + fn algorithm(&self) -> Algorithm; |
227 | + } |
228 | |
229 | #[derive(Debug)] |
230 | - pub enum PrivateKey { |
231 | - Rsa(RsaPrivateKey), |
232 | - Ed25519(ed25519_dalek::Keypair), |
233 | + pub struct RsaKey<T> { |
234 | + inner: RsaPrivateKey, |
235 | + padding: PhantomData<T>, |
236 | } |
237 | |
238 | - impl PrivateKey { |
239 | + impl<T: Digest + AssociatedOid + io::Write> RsaKey<T> { |
240 | /// Creates a new RSA private key from a PKCS1 PEM string. |
241 | - pub fn from_rsa_pkcs1_pem(private_key_pem: &str) -> crate::Result<Self> { |
242 | - Ok(PrivateKey::Rsa( |
243 | - RsaPrivateKey::from_pkcs1_pem(private_key_pem) |
244 | - .map_err(|err| Error::CryptoError(err.to_string()))?, |
245 | - )) |
246 | + pub fn from_rsa_pkcs1_pem(private_key_pem: &str) -> Result<Self> { |
247 | + let inner = RsaPrivateKey::from_pkcs1_pem(private_key_pem) |
248 | + .map_err(|err| Error::CryptoError(err.to_string()))?; |
249 | + |
250 | + Ok(RsaKey { |
251 | + inner, |
252 | + padding: PhantomData, |
253 | + }) |
254 | } |
255 | |
256 | /// Creates a new RSA private key from a PKCS1 binary slice. |
257 | - pub fn from_rsa_pkcs1_der(private_key_bytes: &[u8]) -> crate::Result<Self> { |
258 | - Ok(PrivateKey::Rsa( |
259 | - RsaPrivateKey::from_pkcs1_der(private_key_bytes) |
260 | - .map_err(|err| Error::CryptoError(err.to_string()))?, |
261 | - )) |
262 | + pub fn from_rsa_pkcs1_der(private_key_bytes: &[u8]) -> Result<Self> { |
263 | + let inner = RsaPrivateKey::from_pkcs1_der(private_key_bytes) |
264 | + .map_err(|err| Error::CryptoError(err.to_string()))?; |
265 | + |
266 | + Ok(RsaKey { |
267 | + inner, |
268 | + padding: PhantomData, |
269 | + }) |
270 | + } |
271 | + } |
272 | + |
273 | + impl SigningKey for RsaKey<Sha1> { |
274 | + type Hasher = Sha1; |
275 | + |
276 | + fn sign(&self, data: &Output<Self::Hasher>) -> Result<Vec<u8>> { |
277 | + self.inner |
278 | + .sign(PaddingScheme::new_pkcs1v15_sign::<Self::Hasher>(), data) |
279 | + .map_err(|err| Error::CryptoError(err.to_string())) |
280 | + } |
281 | + |
282 | + fn algorithm(&self) -> Algorithm { |
283 | + Algorithm::RsaSha1 |
284 | + } |
285 | + } |
286 | + |
287 | + impl SigningKey for RsaKey<Sha256> { |
288 | + type Hasher = Sha256; |
289 | + |
290 | + fn sign(&self, data: &Output<Self::Hasher>) -> Result<Vec<u8>> { |
291 | + self.inner |
292 | + .sign(PaddingScheme::new_pkcs1v15_sign::<Self::Hasher>(), data) |
293 | + .map_err(|err| Error::CryptoError(err.to_string())) |
294 | } |
295 | |
296 | + fn algorithm(&self) -> Algorithm { |
297 | + Algorithm::RsaSha256 |
298 | + } |
299 | + } |
300 | + |
301 | + pub struct Ed25519Key { |
302 | + inner: ed25519_dalek::Keypair, |
303 | + } |
304 | + |
305 | + impl Ed25519Key { |
306 | /// Creates an Ed25519 private key |
307 | - pub fn from_ed25519(public_key_bytes: &[u8], private_key_bytes: &[u8]) -> crate::Result<Self> { |
308 | - Ok(PrivateKey::Ed25519(ed25519_dalek::Keypair { |
309 | - public: ed25519_dalek::PublicKey::from_bytes(public_key_bytes) |
310 | - .map_err(|err| Error::CryptoError(err.to_string()))?, |
311 | - secret: ed25519_dalek::SecretKey::from_bytes(private_key_bytes) |
312 | - .map_err(|err| Error::CryptoError(err.to_string()))?, |
313 | - })) |
314 | + pub fn from_bytes(public_key_bytes: &[u8], private_key_bytes: &[u8]) -> crate::Result<Self> { |
315 | + Ok(Self { |
316 | + inner: ed25519_dalek::Keypair { |
317 | + public: ed25519_dalek::PublicKey::from_bytes(public_key_bytes) |
318 | + .map_err(|err| Error::CryptoError(err.to_string()))?, |
319 | + secret: ed25519_dalek::SecretKey::from_bytes(private_key_bytes) |
320 | + .map_err(|err| Error::CryptoError(err.to_string()))?, |
321 | + }, |
322 | + }) |
323 | + } |
324 | + } |
325 | + |
326 | + impl SigningKey for Ed25519Key { |
327 | + type Hasher = Sha256; |
328 | + |
329 | + fn sign(&self, data: &Output<Self::Hasher>) -> Result<Vec<u8>> { |
330 | + Ok(self.inner.sign(data.as_ref()).to_bytes().to_vec()) |
331 | + } |
332 | + |
333 | + fn algorithm(&self) -> Algorithm { |
334 | + Algorithm::Ed25519Sha256 |
335 | } |
336 | } |
337 | |
338 | @@ -43,6 +118,18 @@ pub enum HashAlgorithm { |
339 | Sha256 = R_HASH_SHA256, |
340 | } |
341 | |
342 | + impl TryFrom<&ObjectIdentifier> for HashAlgorithm { |
343 | + type Error = Error; |
344 | + |
345 | + fn try_from(oid: &ObjectIdentifier) -> Result<Self> { |
346 | + match oid { |
347 | + oid if oid == &Sha256::OID => Ok(HashAlgorithm::Sha256), |
348 | + oid if oid == &Sha1::OID => Ok(HashAlgorithm::Sha1), |
349 | + _ => Err(Error::CryptoError("Unsupported hash algorithm".to_string())), |
350 | + } |
351 | + } |
352 | + } |
353 | + |
354 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
355 | pub enum Algorithm { |
356 | RsaSha1, |
357 | diff --git a/src/dkim/sign.rs b/src/dkim/sign.rs |
358 | index f20b8d6..cb77dde 100644 |
359 | --- a/src/dkim/sign.rs |
360 | +++ b/src/dkim/sign.rs |
361 | @@ -8,17 +8,13 @@ |
362 | * except according to those terms. |
363 | */ |
364 | |
365 | - use std::{borrow::Cow, io, time::SystemTime}; |
366 | + use std::{borrow::Cow, time::SystemTime}; |
367 | |
368 | - use ed25519_dalek::Signer; |
369 | use mail_builder::encoders::base64::base64_encode; |
370 | - use rsa::{pkcs8::AssociatedOid, PaddingScheme}; |
371 | - use sha1::Sha1; |
372 | - use sha2::{Digest, Sha256}; |
373 | + use sha1::Digest; |
374 | |
375 | - use crate::{Error, PrivateKey}; |
376 | - |
377 | - use super::{Algorithm, Canonicalization, HashAlgorithm, Signature}; |
378 | + use super::{Canonicalization, HashAlgorithm, Signature}; |
379 | + use crate::{common::crypto::SigningKey, Error}; |
380 | |
381 | impl<'x> Signature<'x> { |
382 | /// Creates a new DKIM signature. |
383 | @@ -31,39 +27,28 @@ impl<'x> Signature<'x> { |
384 | |
385 | /// Signs a message. |
386 | #[inline(always)] |
387 | - pub fn sign(mut self, message: &'x [u8], with_key: &PrivateKey) -> crate::Result<Self> { |
388 | + pub fn sign(mut self, message: &'x [u8], with_key: &impl SigningKey) -> crate::Result<Self> { |
389 | if !self.d.is_empty() && !self.s.is_empty() && !self.h.is_empty() { |
390 | let now = SystemTime::now() |
391 | .duration_since(SystemTime::UNIX_EPOCH) |
392 | .map(|d| d.as_secs()) |
393 | .unwrap_or(0); |
394 | - match (self.a, with_key) { |
395 | - (Algorithm::RsaSha256, PrivateKey::Rsa(_)) => { |
396 | - self.sign_::<Sha256>(message, with_key, now) |
397 | - } |
398 | - (Algorithm::RsaSha1, PrivateKey::Rsa(_)) => { |
399 | - self.sign_::<Sha1>(message, with_key, now) |
400 | - } |
401 | - (_, PrivateKey::Ed25519(_)) => { |
402 | - self.a = Algorithm::Ed25519Sha256; |
403 | - self.sign_::<Sha256>(message, with_key, now) |
404 | - } |
405 | - (_, PrivateKey::Rsa(_)) => { |
406 | - self.a = Algorithm::RsaSha256; |
407 | - self.sign_::<Sha256>(message, with_key, now) |
408 | - } |
409 | - } |
410 | + |
411 | + self.a = with_key.algorithm(); |
412 | + self.sign_(message, with_key, now) |
413 | } else { |
414 | Err(Error::MissingParameters) |
415 | } |
416 | } |
417 | |
418 | - fn sign_<T>(mut self, message: &'x [u8], with_key: &PrivateKey, now: u64) -> crate::Result<Self> |
419 | - where |
420 | - T: Digest + AssociatedOid + io::Write, |
421 | - { |
422 | - let mut body_hasher = T::new(); |
423 | - let mut header_hasher = T::new(); |
424 | + fn sign_( |
425 | + mut self, |
426 | + message: &'x [u8], |
427 | + with_key: &impl SigningKey, |
428 | + now: u64, |
429 | + ) -> crate::Result<Self> { |
430 | + let mut body_hasher = with_key.hasher(); |
431 | + let mut header_hasher = with_key.hasher(); |
432 | |
433 | // Canonicalize headers and body |
434 | let (body_len, signed_headers) = |
435 | @@ -86,17 +71,7 @@ impl<'x> Signature<'x> { |
436 | self.write(&mut header_hasher, false)?; |
437 | |
438 | // Sign |
439 | - let b = match with_key { |
440 | - PrivateKey::Rsa(private_key) => private_key |
441 | - .sign( |
442 | - PaddingScheme::new_pkcs1v15_sign::<T>(), |
443 | - &header_hasher.finalize(), |
444 | - ) |
445 | - .map_err(|err| Error::CryptoError(err.to_string()))?, |
446 | - PrivateKey::Ed25519(key_pair) => { |
447 | - key_pair.sign(&header_hasher.finalize()).to_bytes().to_vec() |
448 | - } |
449 | - }; |
450 | + let b = with_key.sign(&header_hasher.finalize())?; |
451 | |
452 | // Encode |
453 | self.b = base64_encode(&b)?; |
454 | @@ -146,12 +121,6 @@ impl<'x> Signature<'x> { |
455 | self |
456 | } |
457 | |
458 | - /// Sets the algorithm to use (must be compatible with the private key provided). |
459 | - pub fn algorithm(mut self, algorithm: Algorithm) -> Self { |
460 | - self.a = algorithm; |
461 | - self |
462 | - } |
463 | - |
464 | /// Include the body length in the signature. |
465 | pub fn body_length(mut self, body_length: bool) -> Self { |
466 | self.l = u64::from(body_length); |
467 | @@ -186,9 +155,12 @@ mod test { |
468 | use trust_dns_resolver::proto::op::ResponseCode; |
469 | |
470 | use crate::{ |
471 | - common::parse::TxtRecordParser, |
472 | + common::{ |
473 | + crypto::{Ed25519Key, RsaKey}, |
474 | + parse::TxtRecordParser, |
475 | + }, |
476 | dkim::{Atps, Canonicalization, DomainKey, DomainKeyReport, HashAlgorithm, Signature}, |
477 | - AuthenticatedMessage, DkimOutput, DkimResult, PrivateKey, Resolver, |
478 | + AuthenticatedMessage, DkimOutput, DkimResult, Resolver, |
479 | }; |
480 | |
481 | const RSA_PRIVATE_KEY: &str = r#"-----BEGIN RSA PRIVATE KEY----- |
482 | @@ -221,12 +193,12 @@ GMot/L2x0IYyMLAz6oLWh2hm7zwtb0CgOrPo1ke44hFYnfc= |
483 | |
484 | #[test] |
485 | fn dkim_sign() { |
486 | - let pk = PrivateKey::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
487 | + let pk = RsaKey::<Sha256>::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
488 | let signature = Signature::new() |
489 | .headers(["From", "To", "Subject"]) |
490 | .domain("stalw.art") |
491 | .selector("default") |
492 | - .sign_::<Sha256>( |
493 | + .sign_( |
494 | concat!( |
495 | "From: hello@stalw.art\r\n", |
496 | "To: dkim@stalw.art\r\n", |
497 | @@ -277,8 +249,8 @@ GMot/L2x0IYyMLAz6oLWh2hm7zwtb0CgOrPo1ke44hFYnfc= |
498 | ); |
499 | |
500 | // Create private keys |
501 | - let pk_rsa = PrivateKey::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
502 | - let pk_ed = PrivateKey::from_ed25519( |
503 | + let pk_rsa = RsaKey::<Sha256>::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
504 | + let pk_ed = Ed25519Key::from_bytes( |
505 | &base64_decode(ED25519_PUBLIC_KEY.rsplit_once("p=").unwrap().1.as_bytes()).unwrap(), |
506 | &base64_decode(ED25519_PRIVATE_KEY.as_bytes()).unwrap(), |
507 | ) |
508 | @@ -393,7 +365,7 @@ GMot/L2x0IYyMLAz6oLWh2hm7zwtb0CgOrPo1ke44hFYnfc= |
509 | .selector("default") |
510 | .expiration(12345) |
511 | .reporting(true) |
512 | - .sign_::<Sha256>(message.as_bytes(), &pk_rsa, 12345) |
513 | + .sign_(message.as_bytes(), &pk_rsa, 12345) |
514 | .unwrap(), |
515 | message, |
516 | Err(super::Error::SignatureExpired), |
517 | @@ -413,7 +385,7 @@ GMot/L2x0IYyMLAz6oLWh2hm7zwtb0CgOrPo1ke44hFYnfc= |
518 | .selector("default") |
519 | .atps("example.com") |
520 | .atpsh(HashAlgorithm::Sha256) |
521 | - .sign_::<Sha256>(message.as_bytes(), &pk_rsa, 12345) |
522 | + .sign_(message.as_bytes(), &pk_rsa, 12345) |
523 | .unwrap(), |
524 | message, |
525 | Err(super::Error::DNSRecordNotFound(ResponseCode::NXDomain)), |
526 | @@ -434,7 +406,7 @@ GMot/L2x0IYyMLAz6oLWh2hm7zwtb0CgOrPo1ke44hFYnfc= |
527 | .selector("default") |
528 | .atps("example.com") |
529 | .atpsh(HashAlgorithm::Sha256) |
530 | - .sign_::<Sha256>(message.as_bytes(), &pk_rsa, 12345) |
531 | + .sign_(message.as_bytes(), &pk_rsa, 12345) |
532 | .unwrap(), |
533 | message, |
534 | Ok(()), |
535 | @@ -454,7 +426,7 @@ GMot/L2x0IYyMLAz6oLWh2hm7zwtb0CgOrPo1ke44hFYnfc= |
536 | .domain("example.com") |
537 | .selector("default") |
538 | .atps("example.com") |
539 | - .sign_::<Sha256>(message.as_bytes(), &pk_rsa, 12345) |
540 | + .sign_(message.as_bytes(), &pk_rsa, 12345) |
541 | .unwrap(), |
542 | message, |
543 | Ok(()), |
544 | diff --git a/src/lib.rs b/src/lib.rs |
545 | index 01b5e16..3d90e4a 100644 |
546 | --- a/src/lib.rs |
547 | +++ b/src/lib.rs |
548 | @@ -60,7 +60,7 @@ |
549 | //! |
550 | //! ```rust |
551 | //! // Sign an e-mail message using RSA-SHA256 |
552 | - //! let pk_rsa = PrivateKey::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
553 | + //! let pk_rsa = RsaKey::<Sha256>::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
554 | //! let signature_rsa = Signature::new() |
555 | //! .headers(["From", "To", "Subject"]) |
556 | //! .domain("example.com") |
557 | @@ -69,7 +69,7 @@ |
558 | //! .unwrap(); |
559 | //! |
560 | //! // Sign an e-mail message using ED25519-SHA256 |
561 | - //! let pk_ed = PrivateKey::from_ed25519( |
562 | + //! let pk_ed = Ed25519Key::from_bytes( |
563 | //! &base64_decode(ED25519_PUBLIC_KEY.as_bytes()).unwrap(), |
564 | //! &base64_decode(ED25519_PRIVATE_KEY.as_bytes()).unwrap(), |
565 | //! ) |
566 | @@ -78,6 +78,7 @@ |
567 | //! .headers(["From", "To", "Subject"]) |
568 | //! .domain("example.com") |
569 | //! .selector("default-ed") |
570 | + //! .algorithm(Algorithm::Ed25519Sha256) |
571 | //! .sign(RFC5322_MESSAGE.as_bytes(), &pk_ed) |
572 | //! .unwrap(); |
573 | //! |
574 | @@ -127,7 +128,7 @@ |
575 | //! // Seal message |
576 | //! if arc_result.can_be_sealed() { |
577 | //! // Seal the e-mail message using RSA-SHA256 |
578 | - //! let pk_rsa = PrivateKey::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
579 | + //! let pk_rsa = RsaKey::<Sha256>::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); |
580 | //! let arc_set = ArcSet::new(&auth_results) |
581 | //! .domain("example.org") |
582 | //! .selector("default") |
583 | @@ -262,11 +263,7 @@ use std::{ |
584 | }; |
585 | |
586 | use arc::Set; |
587 | - use common::{ |
588 | - crypto::{HashAlgorithm, PrivateKey}, |
589 | - headers::Header, |
590 | - lru::LruCache, |
591 | - }; |
592 | + use common::{crypto::HashAlgorithm, headers::Header, lru::LruCache}; |
593 | use dkim::{Atps, Canonicalization, DomainKey, DomainKeyReport}; |
594 | use dmarc::Dmarc; |
595 | use spf::{Macro, Spf}; |