Commit
Author: Dirkjan Ochtman [dirkjan@ochtman.nl]
Hash: f172046f6c325312c8f71f2c1ab5304d728009c3
Timestamp: Wed, 14 Dec 2022 14:06:15 +0000 (1 year ago)

+219 -197 +/-1 browse
Move RustCrypto impls into an inline module
1diff --git a/src/common/crypto.rs b/src/common/crypto.rs
2index b5e353d..76e20bb 100644
3--- a/src/common/crypto.rs
4+++ b/src/common/crypto.rs
5 @@ -1,9 +1,4 @@
6- use std::marker::PhantomData;
7-
8- use ed25519_dalek::Signer;
9- use rsa::{pkcs1::DecodeRsaPrivateKey, PaddingScheme, PublicKey as _, RsaPrivateKey};
10- use sha1::digest::Output;
11- use sha2::digest::Digest;
12+ use sha1::{digest::Output, Digest};
13
14 use crate::{dkim::Canonicalization, Error, Result};
15
16 @@ -21,100 +16,251 @@ pub trait SigningKey {
17 fn algorithm(&self) -> Algorithm;
18 }
19
20- #[derive(Debug, Clone)]
21- pub struct RsaKey<T> {
22- inner: RsaPrivateKey,
23- padding: PhantomData<T>,
24- }
25+ mod rust_crypto {
26+ use std::marker::PhantomData;
27+
28+ use ed25519_dalek::Signer;
29+ use rsa::{pkcs1::DecodeRsaPrivateKey, PaddingScheme, PublicKey as _, RsaPrivateKey};
30+ use sha2::digest::Digest;
31+
32+ use crate::{common::headers::Writer, dkim::Canonicalization};
33
34- impl<T: HashImpl> RsaKey<T> {
35- /// Creates a new RSA private key from a PKCS1 PEM string.
36- pub fn from_pkcs1_pem(private_key_pem: &str) -> Result<Self> {
37- let inner = RsaPrivateKey::from_pkcs1_pem(private_key_pem)
38- .map_err(|err| Error::CryptoError(err.to_string()))?;
39+ use super::{
40+ Algorithm, Error, HashContext, HashImpl, HashOutput, Result, Sha1, Sha256, SigningKey,
41+ VerifyingKey,
42+ };
43
44- Ok(RsaKey {
45- inner,
46- padding: PhantomData,
47- })
48+ #[derive(Clone, Debug)]
49+ pub struct RsaKey<T> {
50+ inner: RsaPrivateKey,
51+ padding: PhantomData<T>,
52 }
53
54- /// Creates a new RSA private key from a PKCS1 binary slice.
55- pub fn from_pkcs1_der(private_key_bytes: &[u8]) -> Result<Self> {
56- let inner = RsaPrivateKey::from_pkcs1_der(private_key_bytes)
57- .map_err(|err| Error::CryptoError(err.to_string()))?;
58+ impl<T: HashImpl> RsaKey<T> {
59+ /// Creates a new RSA private key from a PKCS1 PEM string.
60+ pub fn from_pkcs1_pem(private_key_pem: &str) -> Result<Self> {
61+ let inner = RsaPrivateKey::from_pkcs1_pem(private_key_pem)
62+ .map_err(|err| Error::CryptoError(err.to_string()))?;
63
64- Ok(RsaKey {
65- inner,
66- padding: PhantomData,
67- })
68+ Ok(RsaKey {
69+ inner,
70+ padding: PhantomData,
71+ })
72+ }
73+
74+ /// Creates a new RSA private key from a PKCS1 binary slice.
75+ pub fn from_pkcs1_der(private_key_bytes: &[u8]) -> Result<Self> {
76+ let inner = RsaPrivateKey::from_pkcs1_der(private_key_bytes)
77+ .map_err(|err| Error::CryptoError(err.to_string()))?;
78+
79+ Ok(RsaKey {
80+ inner,
81+ padding: PhantomData,
82+ })
83+ }
84 }
85- }
86
87- impl SigningKey for RsaKey<Sha1> {
88- type Hasher = Sha1;
89+ impl SigningKey for RsaKey<Sha1> {
90+ type Hasher = Sha1;
91+
92+ fn sign(&self, data: HashOutput) -> Result<Vec<u8>> {
93+ self.inner
94+ .sign(
95+ PaddingScheme::new_pkcs1v15_sign::<<Self::Hasher as HashImpl>::Context>(),
96+ data.as_ref(),
97+ )
98+ .map_err(|err| Error::CryptoError(err.to_string()))
99+ }
100
101- fn sign(&self, data: HashOutput) -> Result<Vec<u8>> {
102- self.inner
103- .sign(
104- PaddingScheme::new_pkcs1v15_sign::<<Self::Hasher as HashImpl>::Context>(),
105- data.as_ref(),
106- )
107- .map_err(|err| Error::CryptoError(err.to_string()))
108+ fn algorithm(&self) -> Algorithm {
109+ Algorithm::RsaSha1
110+ }
111 }
112
113- fn algorithm(&self) -> Algorithm {
114- Algorithm::RsaSha1
115+ impl SigningKey for RsaKey<Sha256> {
116+ type Hasher = Sha256;
117+
118+ fn sign(&self, data: HashOutput) -> Result<Vec<u8>> {
119+ self.inner
120+ .sign(
121+ PaddingScheme::new_pkcs1v15_sign::<<Self::Hasher as HashImpl>::Context>(),
122+ data.as_ref(),
123+ )
124+ .map_err(|err| Error::CryptoError(err.to_string()))
125+ }
126+
127+ fn algorithm(&self) -> Algorithm {
128+ Algorithm::RsaSha256
129+ }
130 }
131- }
132
133- impl SigningKey for RsaKey<Sha256> {
134- type Hasher = Sha256;
135+ pub struct Ed25519Key {
136+ inner: ed25519_dalek::Keypair,
137+ }
138
139- fn sign(&self, data: HashOutput) -> Result<Vec<u8>> {
140- self.inner
141- .sign(
142- PaddingScheme::new_pkcs1v15_sign::<<Self::Hasher as HashImpl>::Context>(),
143- data.as_ref(),
144- )
145- .map_err(|err| Error::CryptoError(err.to_string()))
146+ impl Ed25519Key {
147+ /// Creates an Ed25519 private key
148+ pub fn from_bytes(
149+ public_key_bytes: &[u8],
150+ private_key_bytes: &[u8],
151+ ) -> crate::Result<Self> {
152+ Ok(Self {
153+ inner: ed25519_dalek::Keypair {
154+ public: ed25519_dalek::PublicKey::from_bytes(public_key_bytes)
155+ .map_err(|err| Error::CryptoError(err.to_string()))?,
156+ secret: ed25519_dalek::SecretKey::from_bytes(private_key_bytes)
157+ .map_err(|err| Error::CryptoError(err.to_string()))?,
158+ },
159+ })
160+ }
161 }
162
163- fn algorithm(&self) -> Algorithm {
164- Algorithm::RsaSha256
165+ impl SigningKey for Ed25519Key {
166+ type Hasher = Sha256;
167+
168+ fn sign(&self, data: HashOutput) -> Result<Vec<u8>> {
169+ Ok(self.inner.sign(data.as_ref()).to_bytes().to_vec())
170+ }
171+
172+ fn algorithm(&self) -> Algorithm {
173+ Algorithm::Ed25519Sha256
174+ }
175 }
176- }
177
178- pub struct Ed25519Key {
179- inner: ed25519_dalek::Keypair,
180- }
181+ pub(crate) struct RsaPublicKey {
182+ inner: rsa::RsaPublicKey,
183+ }
184
185- impl Ed25519Key {
186- /// Creates an Ed25519 private key
187- pub fn from_bytes(public_key_bytes: &[u8], private_key_bytes: &[u8]) -> crate::Result<Self> {
188- Ok(Self {
189- inner: ed25519_dalek::Keypair {
190- public: ed25519_dalek::PublicKey::from_bytes(public_key_bytes)
191- .map_err(|err| Error::CryptoError(err.to_string()))?,
192- secret: ed25519_dalek::SecretKey::from_bytes(private_key_bytes)
193+ impl RsaPublicKey {
194+ pub(crate) fn verifying_key_from_bytes(
195+ bytes: &[u8],
196+ ) -> Result<Box<dyn VerifyingKey + Send + Sync>> {
197+ Ok(Box::new(RsaPublicKey {
198+ inner: <rsa::RsaPublicKey as rsa::pkcs8::DecodePublicKey>::from_public_key_der(
199+ bytes,
200+ )
201+ .or_else(|_| rsa::pkcs1::DecodeRsaPublicKey::from_pkcs1_der(bytes))
202+ .map_err(|err| Error::CryptoError(err.to_string()))?,
203+ }))
204+ }
205+ }
206+
207+ impl VerifyingKey for RsaPublicKey {
208+ fn verify<'a>(
209+ &self,
210+ headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>,
211+ signature: &[u8],
212+ canonicalization: Canonicalization,
213+ algorithm: Algorithm,
214+ ) -> Result<()> {
215+ match algorithm {
216+ Algorithm::RsaSha256 => {
217+ let hash = canonicalization.hash_headers::<Sha256>(headers);
218+ self.inner
219+ .verify(
220+ PaddingScheme::new_pkcs1v15_sign::<sha2::Sha256>(),
221+ hash.as_ref(),
222+ signature,
223+ )
224+ .map_err(|_| Error::FailedVerification)
225+ }
226+ Algorithm::RsaSha1 => {
227+ let hash = canonicalization.hash_headers::<Sha1>(headers);
228+ self.inner
229+ .verify(
230+ PaddingScheme::new_pkcs1v15_sign::<sha1::Sha1>(),
231+ hash.as_ref(),
232+ signature,
233+ )
234+ .map_err(|_| Error::FailedVerification)
235+ }
236+ Algorithm::Ed25519Sha256 => Err(Error::IncompatibleAlgorithms),
237+ }
238+ }
239+ }
240+
241+ pub(crate) struct Ed25519PublicKey {
242+ inner: ed25519_dalek::PublicKey,
243+ }
244+
245+ impl Ed25519PublicKey {
246+ pub(crate) fn verifying_key_from_bytes(
247+ bytes: &[u8],
248+ ) -> Result<Box<dyn VerifyingKey + Send + Sync>> {
249+ Ok(Box::new(Ed25519PublicKey {
250+ inner: ed25519_dalek::PublicKey::from_bytes(bytes)
251 .map_err(|err| Error::CryptoError(err.to_string()))?,
252- },
253- })
254+ }))
255+ }
256 }
257- }
258
259- impl SigningKey for Ed25519Key {
260- type Hasher = Sha256;
261+ impl VerifyingKey for Ed25519PublicKey {
262+ fn verify<'a>(
263+ &self,
264+ headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>,
265+ signature: &[u8],
266+ canonicalization: Canonicalization,
267+ algorithm: Algorithm,
268+ ) -> Result<()> {
269+ if !matches!(algorithm, Algorithm::Ed25519Sha256) {
270+ return Err(Error::IncompatibleAlgorithms);
271+ }
272+
273+ let hash = canonicalization.hash_headers::<Sha256>(headers);
274+ self.inner
275+ .verify_strict(
276+ hash.as_ref(),
277+ &ed25519_dalek::Signature::from_bytes(signature)
278+ .map_err(|err| Error::CryptoError(err.to_string()))?,
279+ )
280+ .map_err(|_| Error::FailedVerification)
281+ }
282+ }
283+
284+ impl Writer for sha1::Sha1 {
285+ fn write(&mut self, buf: &[u8]) {
286+ self.update(buf);
287+ }
288+ }
289+
290+ impl Writer for sha2::Sha256 {
291+ fn write(&mut self, buf: &[u8]) {
292+ self.update(buf);
293+ }
294+ }
295+
296+ impl HashImpl for Sha1 {
297+ type Context = sha1::Sha1;
298+
299+ fn hasher() -> Self::Context {
300+ <Self::Context as Digest>::new()
301+ }
302+ }
303+
304+ impl HashImpl for Sha256 {
305+ type Context = sha2::Sha256;
306+
307+ fn hasher() -> Self::Context {
308+ <Self::Context as Digest>::new()
309+ }
310+ }
311
312- fn sign(&self, data: HashOutput) -> Result<Vec<u8>> {
313- Ok(self.inner.sign(data.as_ref()).to_bytes().to_vec())
314+ impl HashContext for sha1::Sha1 {
315+ fn finish(self) -> HashOutput {
316+ HashOutput::Sha1(self.finalize())
317+ }
318 }
319
320- fn algorithm(&self) -> Algorithm {
321- Algorithm::Ed25519Sha256
322+ impl HashContext for sha2::Sha256 {
323+ fn finish(self) -> HashOutput {
324+ HashOutput::Sha256(self.finalize())
325+ }
326 }
327 }
328
329+ pub use rust_crypto::{Ed25519Key, RsaKey};
330+ pub(crate) use rust_crypto::{Ed25519PublicKey, RsaPublicKey};
331+
332 pub trait VerifyingKey {
333 fn verify<'a>(
334 &self,
335 @@ -142,118 +288,10 @@ impl VerifyingKeyType {
336 }
337 }
338
339- pub(crate) struct RsaPublicKey {
340- inner: rsa::RsaPublicKey,
341- }
342-
343- impl RsaPublicKey {
344- fn verifying_key_from_bytes(bytes: &[u8]) -> Result<Box<dyn VerifyingKey + Send + Sync>> {
345- Ok(Box::new(RsaPublicKey {
346- inner: <rsa::RsaPublicKey as rsa::pkcs8::DecodePublicKey>::from_public_key_der(bytes)
347- .or_else(|_| rsa::pkcs1::DecodeRsaPublicKey::from_pkcs1_der(bytes))
348- .map_err(|err| Error::CryptoError(err.to_string()))?,
349- }))
350- }
351- }
352-
353- impl VerifyingKey for RsaPublicKey {
354- fn verify<'a>(
355- &self,
356- headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>,
357- signature: &[u8],
358- canonicalization: Canonicalization,
359- algorithm: Algorithm,
360- ) -> Result<()> {
361- match algorithm {
362- Algorithm::RsaSha256 => {
363- let hash = canonicalization.hash_headers::<Sha256>(headers);
364- self.inner
365- .verify(
366- PaddingScheme::new_pkcs1v15_sign::<sha2::Sha256>(),
367- hash.as_ref(),
368- signature,
369- )
370- .map_err(|_| Error::FailedVerification)
371- }
372- Algorithm::RsaSha1 => {
373- let hash = canonicalization.hash_headers::<Sha1>(headers);
374- self.inner
375- .verify(
376- PaddingScheme::new_pkcs1v15_sign::<sha1::Sha1>(),
377- hash.as_ref(),
378- signature,
379- )
380- .map_err(|_| Error::FailedVerification)
381- }
382- Algorithm::Ed25519Sha256 => Err(Error::IncompatibleAlgorithms),
383- }
384- }
385- }
386-
387- pub(crate) struct Ed25519PublicKey {
388- inner: ed25519_dalek::PublicKey,
389- }
390-
391- impl Ed25519PublicKey {
392- fn verifying_key_from_bytes(bytes: &[u8]) -> Result<Box<dyn VerifyingKey + Send + Sync>> {
393- Ok(Box::new(Ed25519PublicKey {
394- inner: ed25519_dalek::PublicKey::from_bytes(bytes)
395- .map_err(|err| Error::CryptoError(err.to_string()))?,
396- }))
397- }
398- }
399-
400- impl VerifyingKey for Ed25519PublicKey {
401- fn verify<'a>(
402- &self,
403- headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>,
404- signature: &[u8],
405- canonicalization: Canonicalization,
406- algorithm: Algorithm,
407- ) -> Result<()> {
408- if !matches!(algorithm, Algorithm::Ed25519Sha256) {
409- return Err(Error::IncompatibleAlgorithms);
410- }
411-
412- let hash = canonicalization.hash_headers::<Sha256>(headers);
413- self.inner
414- .verify_strict(
415- hash.as_ref(),
416- &ed25519_dalek::Signature::from_bytes(signature)
417- .map_err(|err| Error::CryptoError(err.to_string()))?,
418- )
419- .map_err(|_| Error::FailedVerification)
420- }
421- }
422-
423- impl Writer for sha1::Sha1 {
424- fn write(&mut self, buf: &[u8]) {
425- self.update(buf);
426- }
427- }
428-
429- impl Writer for sha2::Sha256 {
430- fn write(&mut self, buf: &[u8]) {
431- self.update(buf);
432- }
433- }
434-
435 pub trait HashContext: Writer + Sized {
436 fn finish(self) -> HashOutput;
437 }
438
439- impl HashContext for sha1::Sha1 {
440- fn finish(self) -> HashOutput {
441- HashOutput::Sha1(self.finalize())
442- }
443- }
444-
445- impl HashContext for sha2::Sha256 {
446- fn finish(self) -> HashOutput {
447- HashOutput::Sha256(self.finalize())
448- }
449- }
450-
451 pub trait HashImpl {
452 type Context: HashContext;
453
454 @@ -263,25 +301,9 @@ pub trait HashImpl {
455 #[derive(Clone, Copy)]
456 pub struct Sha1;
457
458- impl HashImpl for Sha1 {
459- type Context = sha1::Sha1;
460-
461- fn hasher() -> Self::Context {
462- <Self::Context as Digest>::new()
463- }
464- }
465-
466 #[derive(Clone, Copy)]
467 pub struct Sha256;
468
469- impl HashImpl for Sha256 {
470- type Context = sha2::Sha256;
471-
472- fn hasher() -> Self::Context {
473- <Self::Context as Digest>::new()
474- }
475- }
476-
477 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
478 #[repr(u64)]
479 pub enum HashAlgorithm {