Commit
+335 -345 +/-3 browse
1 | diff --git a/src/common/crypto.rs b/src/common/crypto.rs |
2 | deleted file mode 100644 |
3 | index 76e20bb..0000000 |
4 | --- a/src/common/crypto.rs |
5 | +++ /dev/null |
6 | @@ -1,345 +0,0 @@ |
7 | - use sha1::{digest::Output, Digest}; |
8 | - |
9 | - use crate::{dkim::Canonicalization, Error, Result}; |
10 | - |
11 | - use super::headers::Writer; |
12 | - |
13 | - pub trait SigningKey { |
14 | - type Hasher: HashImpl; |
15 | - |
16 | - fn sign(&self, data: HashOutput) -> Result<Vec<u8>>; |
17 | - |
18 | - fn hasher(&self) -> <Self::Hasher as HashImpl>::Context { |
19 | - <Self::Hasher as HashImpl>::hasher() |
20 | - } |
21 | - |
22 | - fn algorithm(&self) -> Algorithm; |
23 | - } |
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 | - use super::{ |
35 | - Algorithm, Error, HashContext, HashImpl, HashOutput, Result, Sha1, Sha256, SigningKey, |
36 | - VerifyingKey, |
37 | - }; |
38 | - |
39 | - #[derive(Clone, Debug)] |
40 | - pub struct RsaKey<T> { |
41 | - inner: RsaPrivateKey, |
42 | - padding: PhantomData<T>, |
43 | - } |
44 | - |
45 | - impl<T: HashImpl> RsaKey<T> { |
46 | - /// Creates a new RSA private key from a PKCS1 PEM string. |
47 | - pub fn from_pkcs1_pem(private_key_pem: &str) -> Result<Self> { |
48 | - let inner = RsaPrivateKey::from_pkcs1_pem(private_key_pem) |
49 | - .map_err(|err| Error::CryptoError(err.to_string()))?; |
50 | - |
51 | - Ok(RsaKey { |
52 | - inner, |
53 | - padding: PhantomData, |
54 | - }) |
55 | - } |
56 | - |
57 | - /// Creates a new RSA private key from a PKCS1 binary slice. |
58 | - pub fn from_pkcs1_der(private_key_bytes: &[u8]) -> Result<Self> { |
59 | - let inner = RsaPrivateKey::from_pkcs1_der(private_key_bytes) |
60 | - .map_err(|err| Error::CryptoError(err.to_string()))?; |
61 | - |
62 | - Ok(RsaKey { |
63 | - inner, |
64 | - padding: PhantomData, |
65 | - }) |
66 | - } |
67 | - } |
68 | - |
69 | - impl SigningKey for RsaKey<Sha1> { |
70 | - type Hasher = Sha1; |
71 | - |
72 | - fn sign(&self, data: HashOutput) -> Result<Vec<u8>> { |
73 | - self.inner |
74 | - .sign( |
75 | - PaddingScheme::new_pkcs1v15_sign::<<Self::Hasher as HashImpl>::Context>(), |
76 | - data.as_ref(), |
77 | - ) |
78 | - .map_err(|err| Error::CryptoError(err.to_string())) |
79 | - } |
80 | - |
81 | - fn algorithm(&self) -> Algorithm { |
82 | - Algorithm::RsaSha1 |
83 | - } |
84 | - } |
85 | - |
86 | - impl SigningKey for RsaKey<Sha256> { |
87 | - type Hasher = Sha256; |
88 | - |
89 | - fn sign(&self, data: HashOutput) -> Result<Vec<u8>> { |
90 | - self.inner |
91 | - .sign( |
92 | - PaddingScheme::new_pkcs1v15_sign::<<Self::Hasher as HashImpl>::Context>(), |
93 | - data.as_ref(), |
94 | - ) |
95 | - .map_err(|err| Error::CryptoError(err.to_string())) |
96 | - } |
97 | - |
98 | - fn algorithm(&self) -> Algorithm { |
99 | - Algorithm::RsaSha256 |
100 | - } |
101 | - } |
102 | - |
103 | - pub struct Ed25519Key { |
104 | - inner: ed25519_dalek::Keypair, |
105 | - } |
106 | - |
107 | - impl Ed25519Key { |
108 | - /// Creates an Ed25519 private key |
109 | - pub fn from_bytes( |
110 | - public_key_bytes: &[u8], |
111 | - private_key_bytes: &[u8], |
112 | - ) -> crate::Result<Self> { |
113 | - Ok(Self { |
114 | - inner: ed25519_dalek::Keypair { |
115 | - public: ed25519_dalek::PublicKey::from_bytes(public_key_bytes) |
116 | - .map_err(|err| Error::CryptoError(err.to_string()))?, |
117 | - secret: ed25519_dalek::SecretKey::from_bytes(private_key_bytes) |
118 | - .map_err(|err| Error::CryptoError(err.to_string()))?, |
119 | - }, |
120 | - }) |
121 | - } |
122 | - } |
123 | - |
124 | - impl SigningKey for Ed25519Key { |
125 | - type Hasher = Sha256; |
126 | - |
127 | - fn sign(&self, data: HashOutput) -> Result<Vec<u8>> { |
128 | - Ok(self.inner.sign(data.as_ref()).to_bytes().to_vec()) |
129 | - } |
130 | - |
131 | - fn algorithm(&self) -> Algorithm { |
132 | - Algorithm::Ed25519Sha256 |
133 | - } |
134 | - } |
135 | - |
136 | - pub(crate) struct RsaPublicKey { |
137 | - inner: rsa::RsaPublicKey, |
138 | - } |
139 | - |
140 | - impl RsaPublicKey { |
141 | - pub(crate) fn verifying_key_from_bytes( |
142 | - bytes: &[u8], |
143 | - ) -> Result<Box<dyn VerifyingKey + Send + Sync>> { |
144 | - Ok(Box::new(RsaPublicKey { |
145 | - inner: <rsa::RsaPublicKey as rsa::pkcs8::DecodePublicKey>::from_public_key_der( |
146 | - bytes, |
147 | - ) |
148 | - .or_else(|_| rsa::pkcs1::DecodeRsaPublicKey::from_pkcs1_der(bytes)) |
149 | - .map_err(|err| Error::CryptoError(err.to_string()))?, |
150 | - })) |
151 | - } |
152 | - } |
153 | - |
154 | - impl VerifyingKey for RsaPublicKey { |
155 | - fn verify<'a>( |
156 | - &self, |
157 | - headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>, |
158 | - signature: &[u8], |
159 | - canonicalization: Canonicalization, |
160 | - algorithm: Algorithm, |
161 | - ) -> Result<()> { |
162 | - match algorithm { |
163 | - Algorithm::RsaSha256 => { |
164 | - let hash = canonicalization.hash_headers::<Sha256>(headers); |
165 | - self.inner |
166 | - .verify( |
167 | - PaddingScheme::new_pkcs1v15_sign::<sha2::Sha256>(), |
168 | - hash.as_ref(), |
169 | - signature, |
170 | - ) |
171 | - .map_err(|_| Error::FailedVerification) |
172 | - } |
173 | - Algorithm::RsaSha1 => { |
174 | - let hash = canonicalization.hash_headers::<Sha1>(headers); |
175 | - self.inner |
176 | - .verify( |
177 | - PaddingScheme::new_pkcs1v15_sign::<sha1::Sha1>(), |
178 | - hash.as_ref(), |
179 | - signature, |
180 | - ) |
181 | - .map_err(|_| Error::FailedVerification) |
182 | - } |
183 | - Algorithm::Ed25519Sha256 => Err(Error::IncompatibleAlgorithms), |
184 | - } |
185 | - } |
186 | - } |
187 | - |
188 | - pub(crate) struct Ed25519PublicKey { |
189 | - inner: ed25519_dalek::PublicKey, |
190 | - } |
191 | - |
192 | - impl Ed25519PublicKey { |
193 | - pub(crate) fn verifying_key_from_bytes( |
194 | - bytes: &[u8], |
195 | - ) -> Result<Box<dyn VerifyingKey + Send + Sync>> { |
196 | - Ok(Box::new(Ed25519PublicKey { |
197 | - inner: ed25519_dalek::PublicKey::from_bytes(bytes) |
198 | - .map_err(|err| Error::CryptoError(err.to_string()))?, |
199 | - })) |
200 | - } |
201 | - } |
202 | - |
203 | - impl VerifyingKey for Ed25519PublicKey { |
204 | - fn verify<'a>( |
205 | - &self, |
206 | - headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>, |
207 | - signature: &[u8], |
208 | - canonicalization: Canonicalization, |
209 | - algorithm: Algorithm, |
210 | - ) -> Result<()> { |
211 | - if !matches!(algorithm, Algorithm::Ed25519Sha256) { |
212 | - return Err(Error::IncompatibleAlgorithms); |
213 | - } |
214 | - |
215 | - let hash = canonicalization.hash_headers::<Sha256>(headers); |
216 | - self.inner |
217 | - .verify_strict( |
218 | - hash.as_ref(), |
219 | - &ed25519_dalek::Signature::from_bytes(signature) |
220 | - .map_err(|err| Error::CryptoError(err.to_string()))?, |
221 | - ) |
222 | - .map_err(|_| Error::FailedVerification) |
223 | - } |
224 | - } |
225 | - |
226 | - impl Writer for sha1::Sha1 { |
227 | - fn write(&mut self, buf: &[u8]) { |
228 | - self.update(buf); |
229 | - } |
230 | - } |
231 | - |
232 | - impl Writer for sha2::Sha256 { |
233 | - fn write(&mut self, buf: &[u8]) { |
234 | - self.update(buf); |
235 | - } |
236 | - } |
237 | - |
238 | - impl HashImpl for Sha1 { |
239 | - type Context = sha1::Sha1; |
240 | - |
241 | - fn hasher() -> Self::Context { |
242 | - <Self::Context as Digest>::new() |
243 | - } |
244 | - } |
245 | - |
246 | - impl HashImpl for Sha256 { |
247 | - type Context = sha2::Sha256; |
248 | - |
249 | - fn hasher() -> Self::Context { |
250 | - <Self::Context as Digest>::new() |
251 | - } |
252 | - } |
253 | - |
254 | - impl HashContext for sha1::Sha1 { |
255 | - fn finish(self) -> HashOutput { |
256 | - HashOutput::Sha1(self.finalize()) |
257 | - } |
258 | - } |
259 | - |
260 | - impl HashContext for sha2::Sha256 { |
261 | - fn finish(self) -> HashOutput { |
262 | - HashOutput::Sha256(self.finalize()) |
263 | - } |
264 | - } |
265 | - } |
266 | - |
267 | - pub use rust_crypto::{Ed25519Key, RsaKey}; |
268 | - pub(crate) use rust_crypto::{Ed25519PublicKey, RsaPublicKey}; |
269 | - |
270 | - pub trait VerifyingKey { |
271 | - fn verify<'a>( |
272 | - &self, |
273 | - headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>, |
274 | - signature: &[u8], |
275 | - canonicalication: Canonicalization, |
276 | - algorithm: Algorithm, |
277 | - ) -> Result<()>; |
278 | - } |
279 | - |
280 | - pub(crate) enum VerifyingKeyType { |
281 | - Rsa, |
282 | - Ed25519, |
283 | - } |
284 | - |
285 | - impl VerifyingKeyType { |
286 | - pub(crate) fn verifying_key( |
287 | - &self, |
288 | - bytes: &[u8], |
289 | - ) -> Result<Box<dyn VerifyingKey + Send + Sync>> { |
290 | - match self { |
291 | - Self::Rsa => RsaPublicKey::verifying_key_from_bytes(bytes), |
292 | - Self::Ed25519 => Ed25519PublicKey::verifying_key_from_bytes(bytes), |
293 | - } |
294 | - } |
295 | - } |
296 | - |
297 | - pub trait HashContext: Writer + Sized { |
298 | - fn finish(self) -> HashOutput; |
299 | - } |
300 | - |
301 | - pub trait HashImpl { |
302 | - type Context: HashContext; |
303 | - |
304 | - fn hasher() -> Self::Context; |
305 | - } |
306 | - |
307 | - #[derive(Clone, Copy)] |
308 | - pub struct Sha1; |
309 | - |
310 | - #[derive(Clone, Copy)] |
311 | - pub struct Sha256; |
312 | - |
313 | - #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
314 | - #[repr(u64)] |
315 | - pub enum HashAlgorithm { |
316 | - Sha1 = R_HASH_SHA1, |
317 | - Sha256 = R_HASH_SHA256, |
318 | - } |
319 | - |
320 | - impl HashAlgorithm { |
321 | - pub fn hash(&self, data: &[u8]) -> HashOutput { |
322 | - match self { |
323 | - Self::Sha1 => HashOutput::Sha1(sha1::Sha1::digest(data)), |
324 | - Self::Sha256 => HashOutput::Sha256(sha2::Sha256::digest(data)), |
325 | - } |
326 | - } |
327 | - } |
328 | - |
329 | - pub enum HashOutput { |
330 | - Sha1(Output<sha1::Sha1>), |
331 | - Sha256(Output<sha2::Sha256>), |
332 | - } |
333 | - |
334 | - impl AsRef<[u8]> for HashOutput { |
335 | - fn as_ref(&self) -> &[u8] { |
336 | - match self { |
337 | - Self::Sha1(output) => output.as_ref(), |
338 | - Self::Sha256(output) => output.as_ref(), |
339 | - } |
340 | - } |
341 | - } |
342 | - |
343 | - #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
344 | - pub enum Algorithm { |
345 | - RsaSha1, |
346 | - RsaSha256, |
347 | - Ed25519Sha256, |
348 | - } |
349 | - |
350 | - pub(crate) const R_HASH_SHA1: u64 = 0x01; |
351 | - pub(crate) const R_HASH_SHA256: u64 = 0x02; |
352 | diff --git a/src/common/crypto/mod.rs b/src/common/crypto/mod.rs |
353 | new file mode 100644 |
354 | index 0000000..bfb494d |
355 | --- /dev/null |
356 | +++ b/src/common/crypto/mod.rs |
357 | @@ -0,0 +1,104 @@ |
358 | + use sha1::{digest::Output, Digest}; |
359 | + |
360 | + use crate::{dkim::Canonicalization, Result}; |
361 | + |
362 | + use super::headers::Writer; |
363 | + |
364 | + mod rust_crypto; |
365 | + pub use rust_crypto::{Ed25519Key, RsaKey}; |
366 | + pub(crate) use rust_crypto::{Ed25519PublicKey, RsaPublicKey}; |
367 | + |
368 | + pub trait SigningKey { |
369 | + type Hasher: HashImpl; |
370 | + |
371 | + fn sign(&self, data: HashOutput) -> Result<Vec<u8>>; |
372 | + |
373 | + fn hasher(&self) -> <Self::Hasher as HashImpl>::Context { |
374 | + <Self::Hasher as HashImpl>::hasher() |
375 | + } |
376 | + |
377 | + fn algorithm(&self) -> Algorithm; |
378 | + } |
379 | + |
380 | + pub trait VerifyingKey { |
381 | + fn verify<'a>( |
382 | + &self, |
383 | + headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>, |
384 | + signature: &[u8], |
385 | + canonicalication: Canonicalization, |
386 | + algorithm: Algorithm, |
387 | + ) -> Result<()>; |
388 | + } |
389 | + |
390 | + pub(crate) enum VerifyingKeyType { |
391 | + Rsa, |
392 | + Ed25519, |
393 | + } |
394 | + |
395 | + impl VerifyingKeyType { |
396 | + pub(crate) fn verifying_key( |
397 | + &self, |
398 | + bytes: &[u8], |
399 | + ) -> Result<Box<dyn VerifyingKey + Send + Sync>> { |
400 | + match self { |
401 | + Self::Rsa => RsaPublicKey::verifying_key_from_bytes(bytes), |
402 | + Self::Ed25519 => Ed25519PublicKey::verifying_key_from_bytes(bytes), |
403 | + } |
404 | + } |
405 | + } |
406 | + |
407 | + pub trait HashContext: Writer + Sized { |
408 | + fn finish(self) -> HashOutput; |
409 | + } |
410 | + |
411 | + pub trait HashImpl { |
412 | + type Context: HashContext; |
413 | + |
414 | + fn hasher() -> Self::Context; |
415 | + } |
416 | + |
417 | + #[derive(Clone, Copy)] |
418 | + pub struct Sha1; |
419 | + |
420 | + #[derive(Clone, Copy)] |
421 | + pub struct Sha256; |
422 | + |
423 | + #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
424 | + #[repr(u64)] |
425 | + pub enum HashAlgorithm { |
426 | + Sha1 = R_HASH_SHA1, |
427 | + Sha256 = R_HASH_SHA256, |
428 | + } |
429 | + |
430 | + impl HashAlgorithm { |
431 | + pub fn hash(&self, data: &[u8]) -> HashOutput { |
432 | + match self { |
433 | + Self::Sha1 => HashOutput::Sha1(sha1::Sha1::digest(data)), |
434 | + Self::Sha256 => HashOutput::Sha256(sha2::Sha256::digest(data)), |
435 | + } |
436 | + } |
437 | + } |
438 | + |
439 | + pub enum HashOutput { |
440 | + Sha1(Output<sha1::Sha1>), |
441 | + Sha256(Output<sha2::Sha256>), |
442 | + } |
443 | + |
444 | + impl AsRef<[u8]> for HashOutput { |
445 | + fn as_ref(&self) -> &[u8] { |
446 | + match self { |
447 | + Self::Sha1(output) => output.as_ref(), |
448 | + Self::Sha256(output) => output.as_ref(), |
449 | + } |
450 | + } |
451 | + } |
452 | + |
453 | + #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
454 | + pub enum Algorithm { |
455 | + RsaSha1, |
456 | + RsaSha256, |
457 | + Ed25519Sha256, |
458 | + } |
459 | + |
460 | + pub(crate) const R_HASH_SHA1: u64 = 0x01; |
461 | + pub(crate) const R_HASH_SHA256: u64 = 0x02; |
462 | diff --git a/src/common/crypto/rust_crypto.rs b/src/common/crypto/rust_crypto.rs |
463 | new file mode 100644 |
464 | index 0000000..dd59436 |
465 | --- /dev/null |
466 | +++ b/src/common/crypto/rust_crypto.rs |
467 | @@ -0,0 +1,231 @@ |
468 | + use std::marker::PhantomData; |
469 | + |
470 | + use ed25519_dalek::Signer; |
471 | + use rsa::{pkcs1::DecodeRsaPrivateKey, PaddingScheme, PublicKey as _, RsaPrivateKey}; |
472 | + use sha2::digest::Digest; |
473 | + |
474 | + use crate::{common::headers::Writer, dkim::Canonicalization, Error, Result}; |
475 | + |
476 | + use super::{Algorithm, HashContext, HashImpl, HashOutput, Sha1, Sha256, SigningKey, VerifyingKey}; |
477 | + |
478 | + #[derive(Clone, Debug)] |
479 | + pub struct RsaKey<T> { |
480 | + inner: RsaPrivateKey, |
481 | + padding: PhantomData<T>, |
482 | + } |
483 | + |
484 | + impl<T: HashImpl> RsaKey<T> { |
485 | + /// Creates a new RSA private key from a PKCS1 PEM string. |
486 | + pub fn from_pkcs1_pem(private_key_pem: &str) -> Result<Self> { |
487 | + let inner = RsaPrivateKey::from_pkcs1_pem(private_key_pem) |
488 | + .map_err(|err| Error::CryptoError(err.to_string()))?; |
489 | + |
490 | + Ok(RsaKey { |
491 | + inner, |
492 | + padding: PhantomData, |
493 | + }) |
494 | + } |
495 | + |
496 | + /// Creates a new RSA private key from a PKCS1 binary slice. |
497 | + pub fn from_pkcs1_der(private_key_bytes: &[u8]) -> Result<Self> { |
498 | + let inner = RsaPrivateKey::from_pkcs1_der(private_key_bytes) |
499 | + .map_err(|err| Error::CryptoError(err.to_string()))?; |
500 | + |
501 | + Ok(RsaKey { |
502 | + inner, |
503 | + padding: PhantomData, |
504 | + }) |
505 | + } |
506 | + } |
507 | + |
508 | + impl SigningKey for RsaKey<Sha1> { |
509 | + type Hasher = Sha1; |
510 | + |
511 | + fn sign(&self, data: HashOutput) -> Result<Vec<u8>> { |
512 | + self.inner |
513 | + .sign( |
514 | + PaddingScheme::new_pkcs1v15_sign::<<Self::Hasher as HashImpl>::Context>(), |
515 | + data.as_ref(), |
516 | + ) |
517 | + .map_err(|err| Error::CryptoError(err.to_string())) |
518 | + } |
519 | + |
520 | + fn algorithm(&self) -> Algorithm { |
521 | + Algorithm::RsaSha1 |
522 | + } |
523 | + } |
524 | + |
525 | + impl SigningKey for RsaKey<Sha256> { |
526 | + type Hasher = Sha256; |
527 | + |
528 | + fn sign(&self, data: HashOutput) -> Result<Vec<u8>> { |
529 | + self.inner |
530 | + .sign( |
531 | + PaddingScheme::new_pkcs1v15_sign::<<Self::Hasher as HashImpl>::Context>(), |
532 | + data.as_ref(), |
533 | + ) |
534 | + .map_err(|err| Error::CryptoError(err.to_string())) |
535 | + } |
536 | + |
537 | + fn algorithm(&self) -> Algorithm { |
538 | + Algorithm::RsaSha256 |
539 | + } |
540 | + } |
541 | + |
542 | + pub struct Ed25519Key { |
543 | + inner: ed25519_dalek::Keypair, |
544 | + } |
545 | + |
546 | + impl Ed25519Key { |
547 | + /// Creates an Ed25519 private key |
548 | + pub fn from_bytes(public_key_bytes: &[u8], private_key_bytes: &[u8]) -> crate::Result<Self> { |
549 | + Ok(Self { |
550 | + inner: ed25519_dalek::Keypair { |
551 | + public: ed25519_dalek::PublicKey::from_bytes(public_key_bytes) |
552 | + .map_err(|err| Error::CryptoError(err.to_string()))?, |
553 | + secret: ed25519_dalek::SecretKey::from_bytes(private_key_bytes) |
554 | + .map_err(|err| Error::CryptoError(err.to_string()))?, |
555 | + }, |
556 | + }) |
557 | + } |
558 | + } |
559 | + |
560 | + impl SigningKey for Ed25519Key { |
561 | + type Hasher = Sha256; |
562 | + |
563 | + fn sign(&self, data: HashOutput) -> Result<Vec<u8>> { |
564 | + Ok(self.inner.sign(data.as_ref()).to_bytes().to_vec()) |
565 | + } |
566 | + |
567 | + fn algorithm(&self) -> Algorithm { |
568 | + Algorithm::Ed25519Sha256 |
569 | + } |
570 | + } |
571 | + |
572 | + pub(crate) struct RsaPublicKey { |
573 | + inner: rsa::RsaPublicKey, |
574 | + } |
575 | + |
576 | + impl RsaPublicKey { |
577 | + pub(crate) fn verifying_key_from_bytes( |
578 | + bytes: &[u8], |
579 | + ) -> Result<Box<dyn VerifyingKey + Send + Sync>> { |
580 | + Ok(Box::new(RsaPublicKey { |
581 | + inner: <rsa::RsaPublicKey as rsa::pkcs8::DecodePublicKey>::from_public_key_der(bytes) |
582 | + .or_else(|_| rsa::pkcs1::DecodeRsaPublicKey::from_pkcs1_der(bytes)) |
583 | + .map_err(|err| Error::CryptoError(err.to_string()))?, |
584 | + })) |
585 | + } |
586 | + } |
587 | + |
588 | + impl VerifyingKey for RsaPublicKey { |
589 | + fn verify<'a>( |
590 | + &self, |
591 | + headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>, |
592 | + signature: &[u8], |
593 | + canonicalization: Canonicalization, |
594 | + algorithm: Algorithm, |
595 | + ) -> Result<()> { |
596 | + match algorithm { |
597 | + Algorithm::RsaSha256 => { |
598 | + let hash = canonicalization.hash_headers::<Sha256>(headers); |
599 | + self.inner |
600 | + .verify( |
601 | + PaddingScheme::new_pkcs1v15_sign::<sha2::Sha256>(), |
602 | + hash.as_ref(), |
603 | + signature, |
604 | + ) |
605 | + .map_err(|_| Error::FailedVerification) |
606 | + } |
607 | + Algorithm::RsaSha1 => { |
608 | + let hash = canonicalization.hash_headers::<Sha1>(headers); |
609 | + self.inner |
610 | + .verify( |
611 | + PaddingScheme::new_pkcs1v15_sign::<sha1::Sha1>(), |
612 | + hash.as_ref(), |
613 | + signature, |
614 | + ) |
615 | + .map_err(|_| Error::FailedVerification) |
616 | + } |
617 | + Algorithm::Ed25519Sha256 => Err(Error::IncompatibleAlgorithms), |
618 | + } |
619 | + } |
620 | + } |
621 | + |
622 | + pub(crate) struct Ed25519PublicKey { |
623 | + inner: ed25519_dalek::PublicKey, |
624 | + } |
625 | + |
626 | + impl Ed25519PublicKey { |
627 | + pub(crate) fn verifying_key_from_bytes( |
628 | + bytes: &[u8], |
629 | + ) -> Result<Box<dyn VerifyingKey + Send + Sync>> { |
630 | + Ok(Box::new(Ed25519PublicKey { |
631 | + inner: ed25519_dalek::PublicKey::from_bytes(bytes) |
632 | + .map_err(|err| Error::CryptoError(err.to_string()))?, |
633 | + })) |
634 | + } |
635 | + } |
636 | + |
637 | + impl VerifyingKey for Ed25519PublicKey { |
638 | + fn verify<'a>( |
639 | + &self, |
640 | + headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>, |
641 | + signature: &[u8], |
642 | + canonicalization: Canonicalization, |
643 | + algorithm: Algorithm, |
644 | + ) -> Result<()> { |
645 | + if !matches!(algorithm, Algorithm::Ed25519Sha256) { |
646 | + return Err(Error::IncompatibleAlgorithms); |
647 | + } |
648 | + |
649 | + let hash = canonicalization.hash_headers::<Sha256>(headers); |
650 | + self.inner |
651 | + .verify_strict( |
652 | + hash.as_ref(), |
653 | + &ed25519_dalek::Signature::from_bytes(signature) |
654 | + .map_err(|err| Error::CryptoError(err.to_string()))?, |
655 | + ) |
656 | + .map_err(|_| Error::FailedVerification) |
657 | + } |
658 | + } |
659 | + |
660 | + impl Writer for sha1::Sha1 { |
661 | + fn write(&mut self, buf: &[u8]) { |
662 | + self.update(buf); |
663 | + } |
664 | + } |
665 | + |
666 | + impl Writer for sha2::Sha256 { |
667 | + fn write(&mut self, buf: &[u8]) { |
668 | + self.update(buf); |
669 | + } |
670 | + } |
671 | + |
672 | + impl HashImpl for Sha1 { |
673 | + type Context = sha1::Sha1; |
674 | + |
675 | + fn hasher() -> Self::Context { |
676 | + <Self::Context as Digest>::new() |
677 | + } |
678 | + } |
679 | + |
680 | + impl HashImpl for Sha256 { |
681 | + type Context = sha2::Sha256; |
682 | + |
683 | + fn hasher() -> Self::Context { |
684 | + <Self::Context as Digest>::new() |
685 | + } |
686 | + } |
687 | + |
688 | + impl HashContext for sha1::Sha1 { |
689 | + fn finish(self) -> HashOutput { |
690 | + HashOutput::Sha1(self.finalize()) |
691 | + } |
692 | + } |
693 | + |
694 | + impl HashContext for sha2::Sha256 { |
695 | + fn finish(self) -> HashOutput { |
696 | + HashOutput::Sha256(self.finalize()) |
697 | + } |
698 | + } |