mini_mail_auth/common/
crypto.rs1use super::headers::{Writable, Writer};
2use crate::Result;
3use rsa::{pkcs1::DecodeRsaPrivateKey, Pkcs1v15Sign, RsaPrivateKey};
4use sha2::digest::Digest;
5use std::marker::PhantomData;
6
7pub trait SigningKey {
10 type Hasher: HashImpl;
11 fn sign(&self, input: impl Writable) -> Result<Vec<u8>>;
12 fn hash(&self, data: impl Writable) -> HashOutput {
13 let mut hasher = <Self::Hasher as HashImpl>::hasher();
14 data.write(&mut hasher);
15 hasher.complete()
16 }
17 fn algorithm(&self) -> Algorithm;
18}
19
20pub trait HashContext: Writer + Sized {
21 fn complete(self) -> HashOutput;
22}
23
24pub trait HashImpl {
25 type Context: HashContext;
26 fn hasher() -> Self::Context;
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
32pub enum Algorithm {
33 #[default]
34 RsaSha256,
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38#[repr(u64)]
39pub enum HashAlgorithm {
40 Sha256,
41}
42
43pub struct Sha256;
44
45#[non_exhaustive]
46pub enum HashOutput {
47 RustCryptoSha256(sha2::digest::Output<sha2::Sha256>),
48}
49
50impl AsRef<[u8]> for HashOutput {
53 fn as_ref(&self) -> &[u8] {
54 match self {
55 Self::RustCryptoSha256(output) => output.as_ref(),
56 }
57 }
58}
59
60impl From<Algorithm> for HashAlgorithm {
61 fn from(_: Algorithm) -> Self {
62 HashAlgorithm::Sha256
63 }
64}
65
66#[derive(Debug)]
69pub struct RsaKey<T> {
70 inner: RsaPrivateKey,
71 padding: PhantomData<T>,
72}
73
74impl<T: HashImpl> RsaKey<T> {
75 pub fn from_pkcs1_pem(private_key_pem: &str) -> Result<Self> {
76 let inner = RsaPrivateKey::from_pkcs1_pem(private_key_pem)?;
77 Ok(RsaKey {
78 inner,
79 padding: PhantomData,
80 })
81 }
82}
83
84impl SigningKey for RsaKey<Sha256> {
85 type Hasher = Sha256;
86
87 fn sign(&self, input: impl Writable) -> Result<Vec<u8>> {
88 let hash = self.hash(input);
89 self.inner
90 .sign(
91 Pkcs1v15Sign::new::<<Self::Hasher as HashImpl>::Context>(),
92 hash.as_ref(),
93 )
94 .map_err(|e| e.into())
95 }
96
97 fn algorithm(&self) -> Algorithm {
98 Algorithm::RsaSha256
99 }
100}
101
102impl Writer for sha2::Sha256 {
105 fn write(&mut self, buf: &[u8]) {
106 self.update(buf);
107 }
108}
109
110impl HashImpl for Sha256 {
111 type Context = sha2::Sha256;
112 fn hasher() -> Self::Context {
113 <Self::Context as Digest>::new()
114 }
115}
116
117impl HashContext for sha2::Sha256 {
118 fn complete(self) -> HashOutput {
119 HashOutput::RustCryptoSha256(self.finalize())
120 }
121}