Skip to main content

httpsig_hyper/
hyper_http.rs

1use crate::error::{HyperSigError, HyperSigResult};
2use http::{HeaderMap, Request, Response};
3use http_body::Body;
4use httpsig::prelude::{
5  message_component::{
6    DerivedComponentName, HttpMessageComponent, HttpMessageComponentId, HttpMessageComponentName, HttpMessageComponentParam,
7  },
8  HttpSignatureBase, HttpSignatureHeaders, HttpSignatureHeadersMap, HttpSignatureParams, SigningKey, VerifyingKey,
9};
10use indexmap::{IndexMap, IndexSet};
11use std::future::Future;
12
13/// A type alias for the signature name
14type SignatureName = String;
15/// A type alias for the key id in base 64
16type KeyId = String;
17
18/* --------------------------------------- */
19/// A trait about the http message signature common to both request and response
20pub trait MessageSignature {
21  type Error;
22
23  /// Check if the request has signature and signature-input headers
24  fn has_message_signature(&self) -> bool;
25
26  /// Extract all key ids for signature bases contained in the request headers
27  fn get_key_ids(&self) -> Result<IndexMap<SignatureName, KeyId>, Self::Error>;
28
29  /// Extract all signature params used to generate signature bases contained in the request headers
30  fn get_signature_params(&self) -> Result<IndexMap<SignatureName, HttpSignatureParams>, Self::Error>;
31}
32
33/// A trait about http message signature for request
34pub trait MessageSignatureReq {
35  type Error;
36  /// Set the http message signature from given http signature params and signing key
37  fn set_message_signature<T>(
38    &mut self,
39    signature_params: &HttpSignatureParams,
40    signing_key: &T,
41    signature_name: Option<&str>,
42  ) -> impl Future<Output = Result<(), Self::Error>> + Send
43  where
44    Self: Sized,
45    T: SigningKey + Sync;
46
47  /// Set the http message signatures from given tuples of (http signature params, signing key, name)
48  fn set_message_signatures<T>(
49    &mut self,
50    params_key_name: &[(&HttpSignatureParams, &T, Option<&str>)],
51  ) -> impl Future<Output = Result<(), Self::Error>> + Send
52  where
53    Self: Sized,
54    T: SigningKey + Sync;
55
56  /// Verify the http message signature with given verifying key if the request has signature and signature-input headers
57  fn verify_message_signature<T>(
58    &self,
59    verifying_key: &T,
60    key_id: Option<&str>,
61  ) -> impl Future<Output = Result<SignatureName, Self::Error>> + Send
62  where
63    Self: Sized,
64    T: VerifyingKey + Sync;
65
66  /// Verify multiple signatures at once
67  fn verify_message_signatures<T>(
68    &self,
69    key_and_id: &[(&T, Option<&str>)],
70  ) -> impl Future<Output = Result<Vec<Result<SignatureName, Self::Error>>, Self::Error>> + Send
71  where
72    Self: Sized,
73    T: VerifyingKey + Sync;
74
75  /// Extract all signature bases contained in the request headers
76  fn extract_signatures(&self) -> Result<IndexMap<SignatureName, (HttpSignatureBase, HttpSignatureHeaders)>, Self::Error>;
77}
78
79/// A trait about http message signature for response
80pub trait MessageSignatureRes {
81  type Error;
82  /// Set the http message signature from given http signature params and signing key
83  fn set_message_signature<T, B>(
84    &mut self,
85    signature_params: &HttpSignatureParams,
86    signing_key: &T,
87    signature_name: Option<&str>,
88    req_for_param: Option<&Request<B>>,
89  ) -> impl Future<Output = Result<(), Self::Error>> + Send
90  where
91    Self: Sized,
92    T: SigningKey + Sync,
93    B: Sync;
94
95  /// Set the http message signatures from given tuples of (http signature params, signing key, name)
96  fn set_message_signatures<T, B>(
97    &mut self,
98    params_key_name: &[(&HttpSignatureParams, &T, Option<&str>)],
99    req_for_param: Option<&Request<B>>,
100  ) -> impl Future<Output = Result<(), Self::Error>> + Send
101  where
102    Self: Sized,
103    T: SigningKey + Sync,
104    B: Sync;
105
106  /// Verify the http message signature with given verifying key if the request has signature and signature-input headers
107  fn verify_message_signature<T, B>(
108    &self,
109    verifying_key: &T,
110    key_id: Option<&str>,
111    req_for_param: Option<&Request<B>>,
112  ) -> impl Future<Output = Result<SignatureName, Self::Error>> + Send
113  where
114    Self: Sized,
115    T: VerifyingKey + Sync,
116    B: Sync;
117
118  /// Verify multiple signatures at once
119  fn verify_message_signatures<T, B>(
120    &self,
121    key_and_id: &[(&T, Option<&str>)],
122    req_for_param: Option<&Request<B>>,
123  ) -> impl Future<Output = Result<Vec<Result<SignatureName, Self::Error>>, Self::Error>> + Send
124  where
125    Self: Sized,
126    T: VerifyingKey + Sync,
127    B: Sync;
128
129  /// Extract all signature bases contained in the request headers
130  fn extract_signatures<B>(
131    &self,
132    req_for_param: Option<&Request<B>>,
133  ) -> Result<IndexMap<SignatureName, (HttpSignatureBase, HttpSignatureHeaders)>, Self::Error>;
134}
135
136/* --------------------------------------- */
137#[cfg(feature = "blocking")]
138/// Synchronous counterpart of [`MessageSignatureReq`].
139///
140/// Every method delegates to the corresponding async method via `futures::executor::block_on`.
141///
142/// # Panics
143///
144/// All methods will panic if called from within an async runtime (e.g. a `tokio` task).
145/// Use the async [`MessageSignatureReq`] methods instead when you are already in an async context.
146pub trait MessageSignatureReqSync: MessageSignatureReq {
147  fn set_message_signature_sync<T>(
148    &mut self,
149    signature_params: &HttpSignatureParams,
150    signing_key: &T,
151    signature_name: Option<&str>,
152  ) -> Result<(), Self::Error>
153  where
154    Self: Sized,
155    T: SigningKey + Sync;
156
157  fn set_message_signatures_sync<T>(
158    &mut self,
159    params_key_name: &[(&HttpSignatureParams, &T, Option<&str>)],
160  ) -> Result<(), Self::Error>
161  where
162    Self: Sized,
163    T: SigningKey + Sync;
164
165  fn verify_message_signature_sync<T>(&self, verifying_key: &T, key_id: Option<&str>) -> Result<SignatureName, Self::Error>
166  where
167    Self: Sized,
168    T: VerifyingKey + Sync;
169
170  fn verify_message_signatures_sync<T>(
171    &self,
172    key_and_id: &[(&T, Option<&str>)],
173  ) -> Result<Vec<Result<SignatureName, Self::Error>>, Self::Error>
174  where
175    Self: Sized,
176    T: VerifyingKey + Sync;
177}
178
179#[cfg(feature = "blocking")]
180/// Synchronous counterpart of [`MessageSignatureRes`].
181///
182/// Every method delegates to the corresponding async method via `futures::executor::block_on`.
183///
184/// # Panics
185///
186/// All methods will panic if called from within an async runtime (e.g. a `tokio` task).
187/// Use the async [`MessageSignatureRes`] methods instead when you are already in an async context.
188pub trait MessageSignatureResSync: MessageSignatureRes {
189  fn set_message_signature_sync<T, B>(
190    &mut self,
191    signature_params: &HttpSignatureParams,
192    signing_key: &T,
193    signature_name: Option<&str>,
194    req_for_param: Option<&Request<B>>,
195  ) -> Result<(), Self::Error>
196  where
197    Self: Sized,
198    T: SigningKey + Sync,
199    B: Sync;
200
201  fn set_message_signatures_sync<T, B>(
202    &mut self,
203    params_key_name: &[(&HttpSignatureParams, &T, Option<&str>)],
204    req_for_param: Option<&Request<B>>,
205  ) -> Result<(), Self::Error>
206  where
207    Self: Sized,
208    T: SigningKey + Sync,
209    B: Sync;
210
211  fn verify_message_signature_sync<T, B>(
212    &self,
213    verifying_key: &T,
214    key_id: Option<&str>,
215    req_for_param: Option<&Request<B>>,
216  ) -> Result<SignatureName, Self::Error>
217  where
218    Self: Sized,
219    T: VerifyingKey + Sync,
220    B: Sync;
221
222  fn verify_message_signatures_sync<T, B>(
223    &self,
224    key_and_id: &[(&T, Option<&str>)],
225    req_for_param: Option<&Request<B>>,
226  ) -> Result<Vec<Result<SignatureName, Self::Error>>, Self::Error>
227  where
228    Self: Sized,
229    T: VerifyingKey + Sync,
230    B: Sync;
231}
232
233/* --------------------------------------- */
234impl<D> MessageSignature for Request<D>
235where
236  D: Send + Body + Sync,
237{
238  type Error = HyperSigError;
239
240  /// Check if the request has signature and signature-input headers
241  fn has_message_signature(&self) -> bool {
242    has_message_signature_inner(self.headers())
243  }
244
245  /// Extract all signature bases contained in the request headers
246  fn get_key_ids(&self) -> HyperSigResult<IndexMap<SignatureName, KeyId>> {
247    let req_or_res = RequestOrResponse::Request(self);
248    get_key_ids_inner(&req_or_res)
249  }
250
251  /// Extract all signature params used to generate signature bases contained in the request headers
252  fn get_signature_params(&self) -> Result<IndexMap<SignatureName, HttpSignatureParams>, Self::Error> {
253    let req_or_res = RequestOrResponse::Request(self);
254    get_signature_params_inner(&req_or_res)
255  }
256}
257
258impl<D> MessageSignatureReq for Request<D>
259where
260  D: Send + Body + Sync,
261{
262  type Error = HyperSigError;
263
264  /// Set the http message signature from given http signature params and signing key
265  async fn set_message_signature<T>(
266    &mut self,
267    signature_params: &HttpSignatureParams,
268    signing_key: &T,
269    signature_name: Option<&str>,
270  ) -> HyperSigResult<()>
271  where
272    Self: Sized,
273    T: SigningKey + Sync,
274  {
275    self
276      .set_message_signatures(&[(signature_params, signing_key, signature_name)])
277      .await
278  }
279
280  async fn set_message_signatures<T>(
281    &mut self,
282    params_key_name: &[(&HttpSignatureParams, &T, Option<&str>)],
283  ) -> Result<(), Self::Error>
284  where
285    Self: Sized,
286    T: SigningKey + Sync,
287  {
288    let req_or_res = RequestOrResponse::Request(self);
289    let vec_signature_headers_fut = params_key_name.iter().flat_map(|(params, key, name)| {
290      build_signature_base(&req_or_res, params, None as Option<&Request<()>>)
291        .map(|base| async move { base.build_signature_headers(*key, *name) })
292    });
293    let vec_signature_headers = futures::future::join_all(vec_signature_headers_fut)
294      .await
295      .into_iter()
296      .collect::<Result<Vec<_>, _>>()?;
297    vec_signature_headers.iter().try_for_each(|headers| {
298      self
299        .headers_mut()
300        .append("signature-input", headers.signature_input_header_value().parse()?);
301      self
302        .headers_mut()
303        .append("signature", headers.signature_header_value().parse()?);
304      Ok(()) as Result<(), HyperSigError>
305    })
306  }
307
308  /// Verify the http message signature with given verifying key if the request has signature and signature-input headers
309  /// Return Ok(()) if the signature is valid.
310  /// If invalid for the given key or error occurs (like the case where the request does not have signature and/or signature-input headers), return Err.
311  /// If key_id is given, it is used to match the key id in signature params
312  async fn verify_message_signature<T>(&self, verifying_key: &T, key_id: Option<&str>) -> HyperSigResult<SignatureName>
313  where
314    Self: Sized,
315    T: VerifyingKey + Sync,
316  {
317    self
318      .verify_message_signatures(&[(verifying_key, key_id)])
319      .await?
320      .pop()
321      .unwrap()
322  }
323
324  async fn verify_message_signatures<T>(
325    &self,
326    key_and_id: &[(&T, Option<&str>)],
327  ) -> Result<Vec<Result<SignatureName, Self::Error>>, Self::Error>
328  where
329    Self: Sized,
330    T: VerifyingKey + Sync,
331  {
332    if !self.has_message_signature() {
333      return Err(HyperSigError::NoSignatureHeaders(
334        "The request does not have signature and signature-input headers".to_string(),
335      ));
336    }
337    let map_signature_with_base = self.extract_signatures()?;
338    verify_message_signatures_inner(&map_signature_with_base, key_and_id).await
339  }
340
341  /// Extract all signature bases contained in the request headers
342  fn extract_signatures(&self) -> Result<IndexMap<SignatureName, (HttpSignatureBase, HttpSignatureHeaders)>, Self::Error> {
343    let req_or_res = RequestOrResponse::Request(self);
344    extract_signatures_inner(&req_or_res, None as Option<&Request<()>>)
345  }
346}
347
348/* --------------------------------------- */
349impl<D> MessageSignature for Response<D>
350where
351  D: Send + Body + Sync,
352{
353  type Error = HyperSigError;
354
355  /// Check if the response has signature and signature-input headers
356  fn has_message_signature(&self) -> bool {
357    has_message_signature_inner(self.headers())
358  }
359
360  /// Extract all key ids for signature bases contained in the response headers
361  fn get_key_ids(&self) -> Result<IndexMap<SignatureName, KeyId>, Self::Error> {
362    let req_or_res = RequestOrResponse::Response(self);
363    get_key_ids_inner(&req_or_res)
364  }
365
366  /// Extract all signature params used to generate signature bases contained in the response headers
367  fn get_signature_params(&self) -> Result<IndexMap<SignatureName, HttpSignatureParams>, Self::Error> {
368    let req_or_res = RequestOrResponse::Response(self);
369    get_signature_params_inner(&req_or_res)
370  }
371}
372
373impl<D> MessageSignatureRes for Response<D>
374where
375  D: Send + Body + Sync,
376{
377  type Error = HyperSigError;
378
379  /// Set the http message signature from given http signature params and signing key
380  async fn set_message_signature<T, B>(
381    &mut self,
382    signature_params: &HttpSignatureParams,
383    signing_key: &T,
384    signature_name: Option<&str>,
385    req_for_param: Option<&Request<B>>,
386  ) -> Result<(), Self::Error>
387  where
388    Self: Sized,
389    T: SigningKey + Sync,
390    B: Sync,
391  {
392    self
393      .set_message_signatures(&[(signature_params, signing_key, signature_name)], req_for_param)
394      .await
395  }
396
397  async fn set_message_signatures<T, B>(
398    &mut self,
399    params_key_name: &[(&HttpSignatureParams, &T, Option<&str>)],
400    req_for_param: Option<&Request<B>>,
401  ) -> Result<(), Self::Error>
402  where
403    Self: Sized,
404    T: SigningKey + Sync,
405  {
406    let req_or_res = RequestOrResponse::Response(self);
407
408    let vec_signature_headers_fut = params_key_name.iter().flat_map(|(params, key, name)| {
409      build_signature_base(&req_or_res, params, req_for_param)
410        .map(|base| async move { base.build_signature_headers(*key, *name) })
411    });
412    let vec_signature_headers = futures::future::join_all(vec_signature_headers_fut)
413      .await
414      .into_iter()
415      .collect::<Result<Vec<_>, _>>()?;
416
417    vec_signature_headers.iter().try_for_each(|headers| {
418      self
419        .headers_mut()
420        .append("signature-input", headers.signature_input_header_value().parse()?);
421      self
422        .headers_mut()
423        .append("signature", headers.signature_header_value().parse()?);
424      Ok(()) as Result<(), HyperSigError>
425    })
426  }
427
428  /// Verify the http message signature with given verifying key if the response has signature and signature-input headers
429  /// Return Ok(()) if the signature is valid.
430  /// If invalid for the given key or error occurs (like the case where the request does not have signature and/or signature-input headers), return Err.
431  /// If key_id is given, it is used to match the key id in signature params
432  async fn verify_message_signature<T, B>(
433    &self,
434    verifying_key: &T,
435    key_id: Option<&str>,
436    req_for_param: Option<&Request<B>>,
437  ) -> Result<SignatureName, Self::Error>
438  where
439    Self: Sized,
440    T: VerifyingKey + Sync,
441    B: Sync,
442  {
443    self
444      .verify_message_signatures(&[(verifying_key, key_id)], req_for_param)
445      .await?
446      .pop()
447      .unwrap()
448  }
449
450  async fn verify_message_signatures<T, B>(
451    &self,
452    key_and_id: &[(&T, Option<&str>)],
453    req_for_param: Option<&Request<B>>,
454  ) -> Result<Vec<Result<SignatureName, Self::Error>>, Self::Error>
455  where
456    Self: Sized,
457    T: VerifyingKey + Sync,
458  {
459    if !self.has_message_signature() {
460      return Err(HyperSigError::NoSignatureHeaders(
461        "The response does not have signature and signature-input headers".to_string(),
462      ));
463    }
464    let map_signature_with_base = self.extract_signatures(req_for_param)?;
465    verify_message_signatures_inner(&map_signature_with_base, key_and_id).await
466  }
467
468  /// Extract all signature bases contained in the response headers
469  fn extract_signatures<B>(
470    &self,
471    req_for_param: Option<&Request<B>>,
472  ) -> Result<IndexMap<SignatureName, (HttpSignatureBase, HttpSignatureHeaders)>, Self::Error> {
473    let req_or_res = RequestOrResponse::Response(self);
474    extract_signatures_inner(&req_or_res, req_for_param)
475  }
476}
477
478/* --------------------------------------- */
479#[cfg(feature = "blocking")]
480impl<D> MessageSignatureReqSync for Request<D>
481where
482  D: Send + Body + Sync,
483{
484  fn set_message_signature_sync<T>(
485    &mut self,
486    signature_params: &HttpSignatureParams,
487    signing_key: &T,
488    signature_name: Option<&str>,
489  ) -> Result<(), Self::Error>
490  where
491    Self: Sized,
492    T: SigningKey + Sync,
493  {
494    futures::executor::block_on(self.set_message_signature(signature_params, signing_key, signature_name))
495  }
496
497  fn set_message_signatures_sync<T>(
498    &mut self,
499    params_key_name: &[(&HttpSignatureParams, &T, Option<&str>)],
500  ) -> Result<(), Self::Error>
501  where
502    Self: Sized,
503    T: SigningKey + Sync,
504  {
505    futures::executor::block_on(self.set_message_signatures(params_key_name))
506  }
507
508  fn verify_message_signature_sync<T>(&self, verifying_key: &T, key_id: Option<&str>) -> Result<SignatureName, Self::Error>
509  where
510    Self: Sized,
511    T: VerifyingKey + Sync,
512  {
513    futures::executor::block_on(self.verify_message_signature(verifying_key, key_id))
514  }
515
516  fn verify_message_signatures_sync<T>(
517    &self,
518    key_and_id: &[(&T, Option<&str>)],
519  ) -> Result<Vec<Result<SignatureName, Self::Error>>, Self::Error>
520  where
521    Self: Sized,
522    T: VerifyingKey + Sync,
523  {
524    futures::executor::block_on(self.verify_message_signatures(key_and_id))
525  }
526}
527
528#[cfg(feature = "blocking")]
529impl<D> MessageSignatureResSync for Response<D>
530where
531  D: Send + Body + Sync,
532{
533  fn set_message_signature_sync<T, B>(
534    &mut self,
535    signature_params: &HttpSignatureParams,
536    signing_key: &T,
537    signature_name: Option<&str>,
538    req_for_param: Option<&Request<B>>,
539  ) -> Result<(), Self::Error>
540  where
541    Self: Sized,
542    T: SigningKey + Sync,
543    B: Sync,
544  {
545    futures::executor::block_on(self.set_message_signature(signature_params, signing_key, signature_name, req_for_param))
546  }
547
548  fn set_message_signatures_sync<T, B>(
549    &mut self,
550    params_key_name: &[(&HttpSignatureParams, &T, Option<&str>)],
551    req_for_param: Option<&Request<B>>,
552  ) -> Result<(), Self::Error>
553  where
554    Self: Sized,
555    T: SigningKey + Sync,
556    B: Sync,
557  {
558    futures::executor::block_on(self.set_message_signatures(params_key_name, req_for_param))
559  }
560
561  fn verify_message_signature_sync<T, B>(
562    &self,
563    verifying_key: &T,
564    key_id: Option<&str>,
565    req_for_param: Option<&Request<B>>,
566  ) -> Result<SignatureName, Self::Error>
567  where
568    Self: Sized,
569    T: VerifyingKey + Sync,
570    B: Sync,
571  {
572    futures::executor::block_on(self.verify_message_signature(verifying_key, key_id, req_for_param))
573  }
574
575  fn verify_message_signatures_sync<T, B>(
576    &self,
577    key_and_id: &[(&T, Option<&str>)],
578    req_for_param: Option<&Request<B>>,
579  ) -> Result<Vec<Result<SignatureName, Self::Error>>, Self::Error>
580  where
581    Self: Sized,
582    T: VerifyingKey + Sync,
583    B: Sync,
584  {
585    futures::executor::block_on(self.verify_message_signatures(key_and_id, req_for_param))
586  }
587}
588
589/* --------------------------------------- */
590// inner functions
591/// has message signature inner function
592fn has_message_signature_inner(headers: &HeaderMap) -> bool {
593  headers.contains_key("signature") && headers.contains_key("signature-input")
594}
595
596/// get key ids inner function
597fn get_key_ids_inner<B>(req_or_res: &RequestOrResponse<B>) -> HyperSigResult<IndexMap<SignatureName, KeyId>> {
598  let signature_headers_map = extract_signature_headers_with_name(req_or_res)?;
599  let res = signature_headers_map
600    .iter()
601    .filter_map(|(name, headers)| headers.signature_params().keyid.clone().map(|key_id| (name.clone(), key_id)))
602    .collect();
603  Ok(res)
604}
605
606/// get signature params inner function
607fn get_signature_params_inner<B>(
608  req_or_res: &RequestOrResponse<B>,
609) -> HyperSigResult<IndexMap<SignatureName, HttpSignatureParams>> {
610  let signature_headers_map = extract_signature_headers_with_name(req_or_res)?;
611  let res = signature_headers_map
612    .iter()
613    .map(|(name, headers)| (name.clone(), headers.signature_params().clone()))
614    .collect();
615  Ok(res)
616}
617
618/// extract signatures inner function
619fn extract_signatures_inner<B1, B2>(
620  req_or_res: &RequestOrResponse<B1>,
621  req_for_param: Option<&Request<B2>>,
622) -> HyperSigResult<IndexMap<SignatureName, (HttpSignatureBase, HttpSignatureHeaders)>> {
623  let signature_headers_map = extract_signature_headers_with_name(req_or_res)?;
624  let extracted = signature_headers_map
625    .iter()
626    .filter_map(|(name, headers)| {
627      build_signature_base(req_or_res, headers.signature_params(), req_for_param)
628        .ok()
629        .map(|base| (name.clone(), (base, headers.clone())))
630    })
631    .collect();
632  Ok(extracted)
633}
634
635/// Verify multiple signatures inner function
636async fn verify_message_signatures_inner<T>(
637  map_signature_with_base: &IndexMap<String, (HttpSignatureBase, HttpSignatureHeaders)>,
638  key_and_id: &[(&T, Option<&str>)],
639) -> HyperSigResult<Vec<HyperSigResult<SignatureName>>>
640where
641  T: VerifyingKey + Sync,
642{
643  // verify for each key_and_id tuple
644  let res_fut = key_and_id.iter().map(|(key, key_id)| {
645    let filtered = if let Some(key_id) = key_id {
646      map_signature_with_base
647        .iter()
648        .filter(|(_, (base, _))| base.keyid() == Some(key_id))
649        .collect::<IndexMap<_, _>>()
650    } else {
651      map_signature_with_base.iter().collect()
652    };
653
654    // check if any one of the signature headers is valid in async manner
655    async move {
656      if filtered.is_empty() {
657        return Err(HyperSigError::NoSignatureHeaders(
658          "No signature as appropriate target for verification".to_string(),
659        ));
660      }
661      // check if any one of the signature headers is valid
662      let successful_sig_names = filtered
663        .iter()
664        .filter_map(|(&name, (base, headers))| base.verify_signature_headers(*key, headers).ok().map(|_| name.clone()))
665        .collect::<IndexSet<_>>();
666      if !successful_sig_names.is_empty() {
667        Ok(successful_sig_names.first().unwrap().clone())
668      } else {
669        Err(HyperSigError::InvalidSignature(
670          "Invalid signature for the verifying key".to_string(),
671        ))
672      }
673    }
674  });
675  let res = futures::future::join_all(res_fut).await;
676  Ok(res)
677}
678
679/* --------------------------------------- */
680
681/// A type to represent either http request or response
682enum RequestOrResponse<'a, B> {
683  Request(&'a Request<B>),
684  Response(&'a Response<B>),
685}
686
687impl<B> RequestOrResponse<'_, B> {
688  fn method(&self) -> HyperSigResult<&http::Method> {
689    match self {
690      RequestOrResponse::Request(req) => Ok(req.method()),
691      _ => Err(HyperSigError::InvalidComponentName(
692        "`method` is only for request".to_string(),
693      )),
694    }
695  }
696
697  fn uri(&self) -> HyperSigResult<&http::Uri> {
698    match self {
699      RequestOrResponse::Request(req) => Ok(req.uri()),
700      _ => Err(HyperSigError::InvalidComponentName("`uri` is only for request".to_string())),
701    }
702  }
703
704  fn headers(&self) -> &HeaderMap {
705    match self {
706      RequestOrResponse::Request(req) => req.headers(),
707      RequestOrResponse::Response(res) => res.headers(),
708    }
709  }
710
711  fn status(&self) -> HyperSigResult<http::StatusCode> {
712    match self {
713      RequestOrResponse::Response(res) => Ok(res.status()),
714      _ => Err(HyperSigError::InvalidComponentName(
715        "`status` is only for response".to_string(),
716      )),
717    }
718  }
719}
720
721/// Extract signature and signature-input with signature-name indication from http request and response
722fn extract_signature_headers_with_name<B>(req_or_res: &RequestOrResponse<B>) -> HyperSigResult<HttpSignatureHeadersMap> {
723  let headers = req_or_res.headers();
724  if !(headers.contains_key("signature-input") && headers.contains_key("signature")) {
725    return Err(HyperSigError::NoSignatureHeaders(
726      "The request does not have signature and signature-input headers".to_string(),
727    ));
728  };
729
730  let signature_input_strings = headers
731    .get_all("signature-input")
732    .iter()
733    .map(|v| v.to_str())
734    .collect::<Result<Vec<_>, _>>()?
735    .join(", ");
736  let signature_strings = headers
737    .get_all("signature")
738    .iter()
739    .map(|v| v.to_str())
740    .collect::<Result<Vec<_>, _>>()?
741    .join(", ");
742
743  let signature_headers = HttpSignatureHeaders::try_parse(&signature_strings, &signature_input_strings)?;
744  Ok(signature_headers)
745}
746
747/// Build signature base from hyper http request/response and signature params
748/// - req_or_res: the hyper http request or response
749/// - signature_params: the http signature params
750/// - req_for_param: corresponding request to be considered in the signature base in response
751fn build_signature_base<B1, B2>(
752  req_or_res: &RequestOrResponse<B1>,
753  signature_params: &HttpSignatureParams,
754  req_for_param: Option<&Request<B2>>,
755) -> HyperSigResult<HttpSignatureBase> {
756  let component_lines = signature_params
757    .covered_components
758    .iter()
759    .map(|component_id| {
760      if component_id.params.0.contains(&HttpMessageComponentParam::Req) {
761        if matches!(req_or_res, RequestOrResponse::Request(_)) {
762          return Err(HyperSigError::InvalidComponentParam(
763            "`req` is not allowed in request".to_string(),
764          ));
765        }
766        if req_for_param.is_none() {
767          return Err(HyperSigError::InvalidComponentParam(
768            "`req` is required for the param".to_string(),
769          ));
770        }
771        let req = RequestOrResponse::Request(req_for_param.unwrap());
772        extract_http_message_component(&req, component_id)
773      } else {
774        extract_http_message_component(req_or_res, component_id)
775      }
776    })
777    .collect::<Result<Vec<_>, _>>()?;
778
779  HttpSignatureBase::try_new(&component_lines, signature_params).map_err(|e| e.into())
780}
781
782/// Extract http field from hyper http request/response
783fn extract_http_field<B>(req_or_res: &RequestOrResponse<B>, id: &HttpMessageComponentId) -> HyperSigResult<HttpMessageComponent> {
784  let HttpMessageComponentName::HttpField(header_name) = &id.name else {
785    return Err(HyperSigError::InvalidComponentName(
786      "invalid http message component name as http field".to_string(),
787    ));
788  };
789  let headers = match req_or_res {
790    RequestOrResponse::Request(req) => req.headers(),
791    RequestOrResponse::Response(res) => res.headers(),
792  };
793
794  let field_values = headers
795    .get_all(header_name)
796    .iter()
797    .map(|v| v.to_str().map(|s| s.to_owned()))
798    .collect::<Result<Vec<_>, _>>()?;
799
800  HttpMessageComponent::try_from((id, field_values.as_slice())).map_err(|e| e.into())
801}
802
803/// Extract derived component from hyper http request/response
804fn extract_derived_component<B>(
805  req_or_res: &RequestOrResponse<B>,
806  id: &HttpMessageComponentId,
807) -> HyperSigResult<HttpMessageComponent> {
808  let HttpMessageComponentName::Derived(derived_id) = &id.name else {
809    return Err(HyperSigError::InvalidComponentName(
810      "invalid http message component name as derived component".to_string(),
811    ));
812  };
813  if !id.params.0.is_empty()
814    && matches!(req_or_res, RequestOrResponse::Request(_))
815    && !(id.params.0.contains(&HttpMessageComponentParam::Req) && id.params.0.len() == 1)
816  {
817    return Err(HyperSigError::InvalidComponentParam(
818      "derived component does not allow parameters for request".to_string(),
819    ));
820  }
821
822  match req_or_res {
823    RequestOrResponse::Request(_) => {
824      if matches!(derived_id, DerivedComponentName::Status) {
825        return Err(HyperSigError::InvalidComponentName(
826          "`status` is only for response".to_string(),
827        ));
828      }
829    }
830    RequestOrResponse::Response(_) => {
831      if !matches!(derived_id, DerivedComponentName::Status) && !matches!(derived_id, DerivedComponentName::SignatureParams) {
832        return Err(HyperSigError::InvalidComponentName(
833          "Only `status` and `signature-params` are allowed for response".to_string(),
834        ));
835      }
836    }
837  }
838
839  let field_values: Vec<String> = match derived_id {
840    DerivedComponentName::Method => vec![req_or_res.method()?.as_str().to_string()],
841    DerivedComponentName::TargetUri => vec![req_or_res.uri()?.to_string()],
842    DerivedComponentName::Authority => vec![req_or_res.uri()?.authority().map(|s| s.to_string()).unwrap_or("".to_string())],
843    DerivedComponentName::Scheme => vec![req_or_res.uri()?.scheme_str().unwrap_or("").to_string()],
844    DerivedComponentName::RequestTarget => match *req_or_res.method()? {
845      http::Method::CONNECT => vec![req_or_res.uri()?.authority().map(|s| s.to_string()).unwrap_or("".to_string())],
846      http::Method::OPTIONS => vec!["*".to_string()],
847      _ => vec![req_or_res
848        .uri()?
849        .path_and_query()
850        .map(|s| s.to_string())
851        .unwrap_or("".to_string())],
852    },
853    DerivedComponentName::Path => vec![{
854      let p = req_or_res.uri()?.path();
855      if p.is_empty() {
856        "/".to_string()
857      } else {
858        p.to_string()
859      }
860    }],
861    DerivedComponentName::Query => vec![req_or_res.uri()?.query().map(|v| format!("?{v}")).unwrap_or("?".to_string())],
862    DerivedComponentName::QueryParam => {
863      let query = req_or_res.uri()?.query().unwrap_or("");
864      query
865        .split('&')
866        .filter(|s| !s.is_empty())
867        .map(|s| s.to_string())
868        .collect::<Vec<_>>()
869    }
870    DerivedComponentName::Status => vec![req_or_res.status()?.as_str().to_string()],
871    DerivedComponentName::SignatureParams => req_or_res
872      .headers()
873      .get_all("signature-input")
874      .iter()
875      .map(|v| v.to_str().unwrap_or("").to_string())
876      .collect::<Vec<_>>(),
877  };
878
879  HttpMessageComponent::try_from((id, field_values.as_slice())).map_err(|e| e.into())
880}
881
882/* --------------------------------------- */
883/// Extract http message component from hyper http request
884fn extract_http_message_component<B>(
885  req_or_res: &RequestOrResponse<B>,
886  target_component_id: &HttpMessageComponentId,
887) -> HyperSigResult<HttpMessageComponent> {
888  match &target_component_id.name {
889    HttpMessageComponentName::HttpField(_) => extract_http_field(req_or_res, target_component_id),
890    HttpMessageComponentName::Derived(_) => extract_derived_component(req_or_res, target_component_id),
891  }
892}
893
894/* --------------------------------------- */
895#[cfg(test)]
896mod tests {
897
898  use super::{
899    super::{
900      error::HyperDigestError,
901      hyper_content_digest::{RequestContentDigest, ResponseContentDigest},
902      ContentDigestType,
903    },
904    *,
905  };
906  use http_body_util::Full;
907  use httpsig::prelude::{PublicKey, SecretKey, SharedKey};
908
909  type BoxBody = http_body_util::combinators::BoxBody<bytes::Bytes, HyperDigestError>;
910
911  const EDDSA_SECRET_KEY: &str = r##"-----BEGIN PRIVATE KEY-----
912MC4CAQAwBQYDK2VwBCIEIDSHAE++q1BP7T8tk+mJtS+hLf81B0o6CFyWgucDFN/C
913-----END PRIVATE KEY-----
914"##;
915  const EDDSA_PUBLIC_KEY: &str = r##"-----BEGIN PUBLIC KEY-----
916MCowBQYDK2VwAyEA1ixMQcxO46PLlgQfYS46ivFd+n0CcDHSKUnuhm3i1O0=
917-----END PUBLIC KEY-----
918"##;
919  // const EDDSA_KEY_ID: &str = "gjrE7ACMxgzYfFHgabgf4kLTg1eKIdsJ94AiFTFj1is=";
920  const COVERED_COMPONENTS_REQ: &[&str] = &["@method", "date", "content-type", "content-digest"];
921  const COVERED_COMPONENTS_RES: &[&str] = &["@status", "\"@method\";req", "date", "content-type", "\"content-digest\";req"];
922
923  async fn build_request() -> Request<BoxBody> {
924    let body = Full::new(&b"{\"hello\": \"world\"}"[..]);
925    let req = Request::builder()
926      .method("GET")
927      .uri("https://example.com/parameters?var=this%20is%20a%20big%0Amultiline%20value&bar=with+plus+whitespace&fa%C3%A7ade%22%3A%20=something")
928      .header("date", "Sun, 09 May 2021 18:30:00 GMT")
929      .header("content-type", "application/json")
930      .header("content-type", "application/json-patch+json")
931      .body(body)
932      .unwrap();
933    req.set_content_digest(&ContentDigestType::Sha256).await.unwrap()
934  }
935
936  async fn build_response() -> Response<BoxBody> {
937    let body = Full::new(&b"{\"hello\": \"world!!\"}"[..]);
938    let res = Response::builder()
939      .status(200)
940      .header("date", "Sun, 09 May 2021 18:30:00 GMT")
941      .header("content-type", "application/json")
942      .header("content-type", "application/json-patch+json")
943      .body(body)
944      .unwrap();
945    res.set_content_digest(&ContentDigestType::Sha256).await.unwrap()
946  }
947
948  fn build_covered_components_req() -> Vec<HttpMessageComponentId> {
949    COVERED_COMPONENTS_REQ
950      .iter()
951      .map(|&s| HttpMessageComponentId::try_from(s).unwrap())
952      .collect()
953  }
954
955  fn build_covered_components_res() -> Vec<HttpMessageComponentId> {
956    COVERED_COMPONENTS_RES
957      .iter()
958      .map(|&s| HttpMessageComponentId::try_from(s).unwrap())
959      .collect()
960  }
961
962  #[tokio::test]
963  async fn test_extract_component_from_request() {
964    let req = build_request().await;
965    let req_or_res = RequestOrResponse::Request(&req);
966
967    let component_id_method = HttpMessageComponentId::try_from("\"@method\"").unwrap();
968    let component = extract_http_message_component(&req_or_res, &component_id_method).unwrap();
969    assert_eq!(component.to_string(), "\"@method\": GET");
970
971    let component_id = HttpMessageComponentId::try_from("\"date\"").unwrap();
972    let component = extract_http_message_component(&req_or_res, &component_id).unwrap();
973    assert_eq!(component.to_string(), "\"date\": Sun, 09 May 2021 18:30:00 GMT");
974
975    let component_id = HttpMessageComponentId::try_from("content-type").unwrap();
976    let component = extract_http_field(&req_or_res, &component_id).unwrap();
977    assert_eq!(
978      component.to_string(),
979      "\"content-type\": application/json, application/json-patch+json"
980    );
981
982    let component_id = HttpMessageComponentId::try_from("content-digest").unwrap();
983    let component = extract_http_message_component(&req_or_res, &component_id).unwrap();
984    assert_eq!(
985      component.to_string(),
986      "\"content-digest\": sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:"
987    );
988  }
989
990  #[tokio::test]
991  async fn test_extract_signature_params_from_request() {
992    let mut req = build_request().await;
993    let headers = req.headers_mut();
994    headers.insert(
995      "signature-input",
996      http::HeaderValue::from_static(r##"sig1=("@method" "@authority")"##),
997    );
998    let component_id = HttpMessageComponentId::try_from("@signature-params").unwrap();
999    let req_or_res = RequestOrResponse::Request(&req);
1000    let component = extract_http_message_component(&req_or_res, &component_id).unwrap();
1001    assert_eq!(component.to_string(), "\"@signature-params\": (\"@method\" \"@authority\")");
1002    assert_eq!(component.value.to_string(), r##"("@method" "@authority")"##);
1003    assert_eq!(component.value.as_field_value(), r##"sig1=("@method" "@authority")"##);
1004    assert_eq!(component.value.as_component_value(), r##"("@method" "@authority")"##);
1005    assert_eq!(component.value.key(), Some("sig1"));
1006  }
1007
1008  #[tokio::test]
1009  async fn test_build_signature_base_from_request() {
1010    let req = build_request().await;
1011
1012    const SIGPARA: &str = r##";created=1704972031;alg="ed25519";keyid="gjrE7ACMxgzYfFHgabgf4kLTg1eKIdsJ94AiFTFj1is=""##;
1013    let values = (r##""@method" "content-type" "date" "content-digest""##, SIGPARA);
1014    let signature_params = HttpSignatureParams::try_from(format!("({}){}", values.0, values.1).as_str()).unwrap();
1015
1016    let req_or_res = RequestOrResponse::Request(&req);
1017    let signature_base = build_signature_base(&req_or_res, &signature_params, None as Option<&Request<()>>).unwrap();
1018    assert_eq!(
1019      signature_base.to_string(),
1020      r##""@method": GET
1021"content-type": application/json, application/json-patch+json
1022"date": Sun, 09 May 2021 18:30:00 GMT
1023"content-digest": sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:
1024"@signature-params": ("@method" "content-type" "date" "content-digest");created=1704972031;alg="ed25519";keyid="gjrE7ACMxgzYfFHgabgf4kLTg1eKIdsJ94AiFTFj1is=""##
1025    );
1026  }
1027
1028  #[tokio::test]
1029  async fn test_extract_tuples_from_request() {
1030    let mut req = build_request().await;
1031    let headers = req.headers_mut();
1032    headers.insert(
1033      "signature-input",
1034      http::HeaderValue::from_static(r##"sig11=("@method" "@authority");created=1704972031"##),
1035    );
1036    headers.insert(
1037      "signature",
1038      http::HeaderValue::from_static(
1039        r##"sig11=:wqcAqbmYJ2ji2glfAMaRy4gruYYnx2nEFN2HN6jrnDnQCK1u02Gb04v9EDgwUPiu4A0w6vuQv5lIp5WPpBKRCw==:"##,
1040      ),
1041    );
1042
1043    let req_or_res = RequestOrResponse::Request(&req);
1044    let tuples = extract_signature_headers_with_name(&req_or_res).unwrap();
1045    assert_eq!(tuples.len(), 1);
1046    assert_eq!(tuples.get("sig11").unwrap().signature_name(), "sig11");
1047    assert_eq!(
1048      tuples.get("sig11").unwrap().signature_params().to_string(),
1049      r##"("@method" "@authority");created=1704972031"##
1050    );
1051  }
1052
1053  #[tokio::test]
1054  async fn test_set_verify_message_signature_req() {
1055    let mut req = build_request().await;
1056    let secret_key = SecretKey::from_pem(EDDSA_SECRET_KEY).unwrap();
1057    let mut signature_params = HttpSignatureParams::try_new(&build_covered_components_req()).unwrap();
1058    signature_params.set_key_info(&secret_key);
1059
1060    req.set_message_signature(&signature_params, &secret_key, None).await.unwrap();
1061    let signature_input = req.headers().get("signature-input").unwrap().to_str().unwrap();
1062    assert!(signature_input.starts_with(r##"sig=("@method" "date" "content-type" "content-digest")"##));
1063    // let signature = req.headers().get("signature").unwrap().to_str().unwrap();
1064
1065    let public_key = PublicKey::from_pem(EDDSA_PUBLIC_KEY).unwrap();
1066    let verification_res = req.verify_message_signature(&public_key, None).await;
1067    assert!(verification_res.is_ok());
1068  }
1069
1070  #[tokio::test]
1071  async fn test_set_verify_message_signature_res() {
1072    let req = build_request().await;
1073    let mut res = build_response().await;
1074
1075    let secret_key = SecretKey::from_pem(EDDSA_SECRET_KEY).unwrap();
1076
1077    let mut signature_params = HttpSignatureParams::try_new(&build_covered_components_res()).unwrap();
1078    signature_params.set_key_info(&secret_key);
1079    // let req_or_res = RequestOrResponse::Response(&res);
1080    // let base = build_signature_base(&req_or_res, &signature_params, Some(&req));
1081    // println!("{}", base.unwrap());
1082    // // println!("{:#?}", req);
1083
1084    res
1085      .set_message_signature(&signature_params, &secret_key, None, Some(&req))
1086      .await
1087      .unwrap();
1088    // println!("{:#?}", res.headers());
1089    let signature_input = res.headers().get("signature-input").unwrap().to_str().unwrap();
1090    assert!(signature_input.starts_with(r##"sig=("@status" "@method";req "date" "content-type" "content-digest";req)"##));
1091    // let signature = req.headers().get("signature").unwrap().to_str().unwrap();
1092
1093    let public_key = PublicKey::from_pem(EDDSA_PUBLIC_KEY).unwrap();
1094    let verification_res = res.verify_message_signature(&public_key, None, Some(&req)).await;
1095    assert!(verification_res.is_ok());
1096  }
1097
1098  #[tokio::test]
1099  async fn test_expired_signature() {
1100    let mut req = build_request().await;
1101    let secret_key = SecretKey::from_pem(EDDSA_SECRET_KEY).unwrap();
1102    let mut signature_params = HttpSignatureParams::try_new(&build_covered_components_req()).unwrap();
1103    signature_params.set_key_info(&secret_key);
1104    let created = signature_params.created.unwrap();
1105    signature_params.set_expires(created - 1);
1106    assert!(signature_params.is_expired());
1107
1108    req.set_message_signature(&signature_params, &secret_key, None).await.unwrap();
1109
1110    let public_key = PublicKey::from_pem(EDDSA_PUBLIC_KEY).unwrap();
1111    let verification_res = req.verify_message_signature(&public_key, None).await;
1112    assert!(verification_res.is_err());
1113  }
1114
1115  #[tokio::test]
1116  async fn test_set_verify_with_signature_name() {
1117    let mut req = build_request().await;
1118    let secret_key = SecretKey::from_pem(EDDSA_SECRET_KEY).unwrap();
1119    let mut signature_params = HttpSignatureParams::try_new(&build_covered_components_req()).unwrap();
1120    signature_params.set_key_info(&secret_key);
1121
1122    req
1123      .set_message_signature(&signature_params, &secret_key, Some("custom_sig_name"))
1124      .await
1125      .unwrap();
1126
1127    let req_or_res = RequestOrResponse::Request(&req);
1128    let signature_headers_map = extract_signature_headers_with_name(&req_or_res).unwrap();
1129    assert_eq!(signature_headers_map.len(), 1);
1130    assert_eq!(signature_headers_map[0].signature_name(), "custom_sig_name");
1131
1132    let public_key = PublicKey::from_pem(EDDSA_PUBLIC_KEY).unwrap();
1133    let verification_res = req.verify_message_signature(&public_key, None).await;
1134    assert!(verification_res.is_ok());
1135  }
1136
1137  #[tokio::test]
1138  async fn test_set_verify_with_key_id() {
1139    let mut req = build_request().await;
1140    let secret_key = SecretKey::from_pem(EDDSA_SECRET_KEY).unwrap();
1141    let mut signature_params = HttpSignatureParams::try_new(&build_covered_components_req()).unwrap();
1142    signature_params.set_key_info(&secret_key);
1143
1144    req.set_message_signature(&signature_params, &secret_key, None).await.unwrap();
1145
1146    let public_key = PublicKey::from_pem(EDDSA_PUBLIC_KEY).unwrap();
1147    let key_id = public_key.key_id();
1148    let verification_res = req.verify_message_signature(&public_key, Some(&key_id)).await;
1149    assert!(verification_res.is_ok());
1150
1151    let verification_res = req.verify_message_signature(&public_key, Some("NotFoundKeyId")).await;
1152    assert!(verification_res.is_err());
1153  }
1154
1155  const HMACSHA256_SECRET_KEY: &str =
1156    r##"uzvJfB4u3N0Jy4T7NZ75MDVcr8zSTInedJtkgcu46YW4XByzNJjxBdtjUkdJPBtbmHhIDi6pcl8jsasjlTMtDQ=="##;
1157
1158  #[tokio::test]
1159  async fn test_set_verify_with_key_id_hmac_sha256() {
1160    let mut req = build_request().await;
1161    let secret_key = SharedKey::from_base64(HMACSHA256_SECRET_KEY).unwrap();
1162    let mut signature_params = HttpSignatureParams::try_new(&build_covered_components_req()).unwrap();
1163    signature_params.set_key_info(&secret_key);
1164    // Random nonce is highly recommended for HMAC
1165    signature_params.set_random_nonce();
1166
1167    req.set_message_signature(&signature_params, &secret_key, None).await.unwrap();
1168
1169    let key_id = VerifyingKey::key_id(&secret_key);
1170    let verification_res = req.verify_message_signature(&secret_key, Some(&key_id)).await;
1171    assert!(verification_res.is_ok());
1172
1173    let verification_res = req.verify_message_signature(&secret_key, Some("NotFoundKeyId")).await;
1174    assert!(verification_res.is_err());
1175  }
1176
1177  #[tokio::test]
1178  async fn test_get_key_ids() {
1179    let mut req = build_request().await;
1180    let secret_key = SecretKey::from_pem(EDDSA_SECRET_KEY).unwrap();
1181    let mut signature_params = HttpSignatureParams::try_new(&build_covered_components_req()).unwrap();
1182    signature_params.set_key_info(&secret_key);
1183
1184    req.set_message_signature(&signature_params, &secret_key, None).await.unwrap();
1185    let key_ids = req.get_key_ids().unwrap();
1186    assert_eq!(key_ids.len(), 1);
1187    assert_eq!(key_ids[0], "gjrE7ACMxgzYfFHgabgf4kLTg1eKIdsJ94AiFTFj1is=");
1188  }
1189
1190  const P256_SECERT_KEY: &str = r##"-----BEGIN PRIVATE KEY-----
1191MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgv7zxW56ojrWwmSo1
11924uOdbVhUfj9Jd+5aZIB9u8gtWnihRANCAARGYsMe0CT6pIypwRvoJlLNs4+cTh2K
1193L7fUNb5i6WbKxkpAoO+6T3pMBG5Yw7+8NuGTvvtrZAXduA2giPxQ8zCf
1194-----END PRIVATE KEY-----
1195"##;
1196  const P256_PUBLIC_KEY: &str = r##"-----BEGIN PUBLIC KEY-----
1197MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERmLDHtAk+qSMqcEb6CZSzbOPnE4d
1198ii+31DW+YulmysZKQKDvuk96TARuWMO/vDbhk777a2QF3bgNoIj8UPMwnw==
1199-----END PUBLIC KEY-----
1200"##;
1201  #[tokio::test]
1202  async fn test_set_verify_multiple_signatures() {
1203    let mut req = build_request().await;
1204
1205    let secret_key_eddsa = SecretKey::from_pem(EDDSA_SECRET_KEY).unwrap();
1206    let mut signature_params_eddsa = HttpSignatureParams::try_new(&build_covered_components_req()).unwrap();
1207    signature_params_eddsa.set_key_info(&secret_key_eddsa);
1208
1209    let secret_key_p256 = SecretKey::from_pem(P256_SECERT_KEY).unwrap();
1210    let mut signature_params_hmac = HttpSignatureParams::try_new(&build_covered_components_req()).unwrap();
1211    signature_params_hmac.set_key_info(&secret_key_p256);
1212
1213    let params_key_name = &[
1214      (&signature_params_eddsa, &secret_key_eddsa, Some("eddsa_sig")),
1215      (&signature_params_hmac, &secret_key_p256, Some("p256_sig")),
1216    ];
1217
1218    req.set_message_signatures(params_key_name).await.unwrap();
1219
1220    let public_key_eddsa = PublicKey::from_pem(EDDSA_PUBLIC_KEY).unwrap();
1221    let public_key_p256 = PublicKey::from_pem(P256_PUBLIC_KEY).unwrap();
1222    let key_id_eddsa = public_key_eddsa.key_id();
1223    let key_id_p256 = public_key_p256.key_id();
1224
1225    let verification_res = req
1226      .verify_message_signatures(&[
1227        (&public_key_eddsa, Some(&key_id_eddsa)),
1228        (&public_key_p256, Some(&key_id_p256)),
1229      ])
1230      .await
1231      .unwrap();
1232
1233    assert!(verification_res.len() == 2 && verification_res.iter().all(|r| r.is_ok()));
1234    assert!(verification_res[0].as_ref().unwrap() == "eddsa_sig");
1235    assert!(verification_res[1].as_ref().unwrap() == "p256_sig");
1236  }
1237
1238  #[cfg(feature = "blocking")]
1239  #[test]
1240  fn test_blocking_set_verify_message_signature_req() {
1241    let mut req = futures::executor::block_on(build_request());
1242    let secret_key = SecretKey::from_pem(EDDSA_SECRET_KEY).unwrap();
1243    let mut signature_params = HttpSignatureParams::try_new(&build_covered_components_req()).unwrap();
1244    signature_params.set_key_info(&secret_key);
1245
1246    req.set_message_signature_sync(&signature_params, &secret_key, None).unwrap();
1247
1248    let public_key = PublicKey::from_pem(EDDSA_PUBLIC_KEY).unwrap();
1249    let verification_res = req.verify_message_signature_sync(&public_key, None);
1250    assert!(verification_res.is_ok());
1251  }
1252
1253  #[cfg(feature = "blocking")]
1254  #[test]
1255  fn test_blocking_set_verify_message_signature_res() {
1256    let req = futures::executor::block_on(build_request());
1257    let mut res = futures::executor::block_on(build_response());
1258    let secret_key = SecretKey::from_pem(EDDSA_SECRET_KEY).unwrap();
1259    let mut signature_params = HttpSignatureParams::try_new(&build_covered_components_res()).unwrap();
1260    signature_params.set_key_info(&secret_key);
1261    res
1262      .set_message_signature_sync(&signature_params, &secret_key, None, Some(&req))
1263      .unwrap();
1264
1265    let public_key = PublicKey::from_pem(EDDSA_PUBLIC_KEY).unwrap();
1266    let verification_res = res.verify_message_signature_sync(&public_key, None, Some(&req));
1267    assert!(verification_res.is_ok());
1268  }
1269}