jwt/algorithm/
mod.rs

1//! Algorithms capable of signing and verifying tokens. By default only the
2//! `hmac` crate's `Hmac` type is supported. For more algorithms, enable the
3//! feature `openssl` and see the [openssl](openssl/index.html)
4//! module. The `none` algorithm is explicitly not supported.
5//! ## Examples
6//! ```
7//! use hmac::{Hmac, Mac};
8//! use sha2::Sha256;
9//!
10//! let hs256_key: Hmac<Sha256> = Hmac::new_from_slice(b"some-secret").unwrap();
11//! ```
12
13use serde::{Deserialize, Serialize};
14
15use crate::error::Error;
16
17#[cfg(feature = "openssl")]
18pub mod openssl;
19pub mod rust_crypto;
20pub mod store;
21
22/// The type of an algorithm, corresponding to the
23/// [JWA](https://tools.ietf.org/html/rfc7518) specification.
24#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
25#[serde(rename_all = "UPPERCASE")]
26pub enum AlgorithmType {
27    Hs256,
28    Hs384,
29    Hs512,
30    Rs256,
31    Rs384,
32    Rs512,
33    Es256,
34    Es384,
35    Es512,
36    Ps256,
37    Ps384,
38    Ps512,
39    #[serde(rename = "none")]
40    None,
41}
42
43impl Default for AlgorithmType {
44    fn default() -> Self {
45        AlgorithmType::Hs256
46    }
47}
48
49/// An algorithm capable of signing base64 encoded header and claims strings.
50/// strings.
51pub trait SigningAlgorithm {
52    fn algorithm_type(&self) -> AlgorithmType;
53
54    fn sign(&self, header: &str, claims: &str) -> Result<String, Error>;
55}
56
57/// An algorithm capable of verifying base64 encoded header and claims strings.
58pub trait VerifyingAlgorithm {
59    fn algorithm_type(&self) -> AlgorithmType;
60
61    fn verify_bytes(&self, header: &str, claims: &str, signature: &[u8]) -> Result<bool, Error>;
62
63    fn verify(&self, header: &str, claims: &str, signature: &str) -> Result<bool, Error> {
64        let signature_bytes = base64::decode_config(signature, base64::URL_SAFE_NO_PAD)?;
65        self.verify_bytes(header, claims, &*signature_bytes)
66    }
67}
68
69// TODO: investigate if these AsRef impls are necessary
70impl<T: AsRef<dyn VerifyingAlgorithm>> VerifyingAlgorithm for T {
71    fn algorithm_type(&self) -> AlgorithmType {
72        self.as_ref().algorithm_type()
73    }
74
75    fn verify_bytes(&self, header: &str, claims: &str, signature: &[u8]) -> Result<bool, Error> {
76        self.as_ref().verify_bytes(header, claims, signature)
77    }
78}
79
80impl<T: AsRef<dyn SigningAlgorithm>> SigningAlgorithm for T {
81    fn algorithm_type(&self) -> AlgorithmType {
82        self.as_ref().algorithm_type()
83    }
84
85    fn sign(&self, header: &str, claims: &str) -> Result<String, Error> {
86        self.as_ref().sign(header, claims)
87    }
88}