identity_jose/jws/custom_verification/jws_verifier.rs
1// Copyright 2020-2023 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use super::SignatureVerificationError;
5use crate::jwk::Jwk;
6use crate::jws::JwsAlgorithm;
7
8/// Input a [`JwsVerifier`] verifies.
9pub struct VerificationInput {
10 /// The `alg` parsed from the protected header.
11 pub alg: JwsAlgorithm,
12 /// The signing input.
13 ///
14 /// See [RFC 7515: section 5.2 part 8.](https://www.rfc-editor.org/rfc/rfc7515#section-5.2) and
15 /// [RFC 7797 section 3](https://www.rfc-editor.org/rfc/rfc7797#section-3).
16 pub signing_input: Box<[u8]>,
17 /// The decoded signature to validate the `signing_input` against in the manner defined by the `alg` field.
18 pub decoded_signature: Box<[u8]>,
19}
20
21/// Trait for cryptographically verifying a JWS signature.
22///
23/// Any type implementing this trait can be passed to
24/// [`JwsValidationItem::verify`](`crate::jws::JwsValidationItem::verify`) which is intended
25/// as the most convenient way to verify a decoded JWS.
26///
27/// [`JwsValidationItem::verify`](crate::jws::JwsValidationItem::verify)
28///
29/// ## Implementation
30///
31/// Implementers are expected to provide a procedure for step 8 of
32/// [RFC 7515 section 5.2](https://www.rfc-editor.org/rfc/rfc7515#section-5.2) for
33/// the JWS signature algorithms they want to support.
34///
35/// Custom implementations can be constructed inline by converting a suitable closure into a [`JwsVerifierFn`]
36/// using the [`From`] trait.
37///
38/// ## Default implementation
39///
40/// When the `eddsa` feature is enabled one can construct an implementor
41/// provided by the IOTA Identity library. See
42/// [`EdDSAJwsVerifier::verify`](EdDSAJwsVerifier::verify).
43pub trait JwsVerifier {
44 /// Validate the `decoded_signature` against the `signing_input` in the manner defined by `alg` using the
45 /// `public_key`.
46 ///
47 /// Implementors may decide to error with
48 /// [`SignatureVerificationErrorKind::UnsupportedAlg`](crate::jws::SignatureVerificationErrorKind::UnsupportedAlg) if
49 /// they are not interested in supporting a given algorithm.
50 fn verify(&self, input: VerificationInput, public_key: &Jwk) -> Result<(), SignatureVerificationError>;
51}
52
53impl JwsVerifier for Box<dyn JwsVerifier> {
54 fn verify(&self, input: VerificationInput, public_key: &Jwk) -> Result<(), SignatureVerificationError> {
55 <dyn JwsVerifier>::verify(self, input, public_key)
56 }
57}
58
59// =================================================================================================================
60// Implementation
61// ================================================================================================================
62
63/// Simple wrapper around a closure capable of verifying a JWS signature. This wrapper implements
64/// [`JwsVerifier`].
65///
66/// Note: One can convert a closure to this wrapper using the [`From`] trait.
67pub struct JwsVerifierFn<F>(F);
68impl<F> From<F> for JwsVerifierFn<F>
69where
70 F: Fn(VerificationInput, &Jwk) -> Result<(), SignatureVerificationError>,
71{
72 fn from(value: F) -> Self {
73 Self(value)
74 }
75}
76
77impl<F> JwsVerifier for JwsVerifierFn<F>
78where
79 F: Fn(VerificationInput, &Jwk) -> Result<(), SignatureVerificationError>,
80{
81 fn verify(&self, input: VerificationInput, public_key: &Jwk) -> Result<(), SignatureVerificationError> {
82 self.0(input, public_key)
83 }
84}