Skip to main content

moq_token/
algorithm.rs

1use std::{fmt, str::FromStr};
2
3/// A subset of jsonwebtoken algorithms.
4///
5/// We could support all of them, but there's currently no point using public key crypto.
6/// The relay can fetch any resource it wants; it doesn't need to forge tokens.
7///
8#[derive(Clone, Copy, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash)]
9pub enum Algorithm {
10	HS256,
11	HS384,
12	HS512,
13	ES256,
14	ES384,
15	RS256,
16	RS384,
17	RS512,
18	PS256,
19	PS384,
20	PS512,
21	EdDSA,
22}
23
24impl From<Algorithm> for jsonwebtoken::Algorithm {
25	fn from(val: Algorithm) -> Self {
26		match val {
27			Algorithm::HS256 => jsonwebtoken::Algorithm::HS256,
28			Algorithm::HS384 => jsonwebtoken::Algorithm::HS384,
29			Algorithm::HS512 => jsonwebtoken::Algorithm::HS512,
30			Algorithm::ES256 => jsonwebtoken::Algorithm::ES256,
31			Algorithm::ES384 => jsonwebtoken::Algorithm::ES384,
32			Algorithm::RS256 => jsonwebtoken::Algorithm::RS256,
33			Algorithm::RS384 => jsonwebtoken::Algorithm::RS384,
34			Algorithm::RS512 => jsonwebtoken::Algorithm::RS512,
35			Algorithm::PS256 => jsonwebtoken::Algorithm::PS256,
36			Algorithm::PS384 => jsonwebtoken::Algorithm::PS384,
37			Algorithm::PS512 => jsonwebtoken::Algorithm::PS512,
38			Algorithm::EdDSA => jsonwebtoken::Algorithm::EdDSA,
39		}
40	}
41}
42
43impl FromStr for Algorithm {
44	type Err = anyhow::Error;
45
46	fn from_str(s: &str) -> Result<Self, Self::Err> {
47		match s {
48			"HS256" => Ok(Algorithm::HS256),
49			"HS384" => Ok(Algorithm::HS384),
50			"HS512" => Ok(Algorithm::HS512),
51			"ES256" => Ok(Algorithm::ES256),
52			"ES384" => Ok(Algorithm::ES384),
53			"RS256" => Ok(Algorithm::RS256),
54			"RS384" => Ok(Algorithm::RS384),
55			"RS512" => Ok(Algorithm::RS512),
56			"PS256" => Ok(Algorithm::PS256),
57			"PS384" => Ok(Algorithm::PS384),
58			"PS512" => Ok(Algorithm::PS512),
59			"EdDSA" => Ok(Algorithm::EdDSA),
60			_ => anyhow::bail!("invalid algorithm: {s}"),
61		}
62	}
63}
64
65impl fmt::Display for Algorithm {
66	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67		match self {
68			Algorithm::HS256 => write!(f, "HS256"),
69			Algorithm::HS384 => write!(f, "HS384"),
70			Algorithm::HS512 => write!(f, "HS512"),
71			Algorithm::ES256 => write!(f, "ES256"),
72			Algorithm::ES384 => write!(f, "ES384"),
73			Algorithm::RS256 => write!(f, "RS256"),
74			Algorithm::RS384 => write!(f, "RS384"),
75			Algorithm::RS512 => write!(f, "RS512"),
76			Algorithm::PS256 => write!(f, "PS256"),
77			Algorithm::PS384 => write!(f, "PS384"),
78			Algorithm::PS512 => write!(f, "PS512"),
79			Algorithm::EdDSA => write!(f, "EdDSA"),
80		}
81	}
82}
83
84#[cfg(test)]
85mod tests {
86	use super::*;
87
88	#[test]
89	fn test_algorithm_from_str_valid() {
90		assert_eq!(Algorithm::from_str("HS256").unwrap(), Algorithm::HS256);
91		assert_eq!(Algorithm::from_str("HS384").unwrap(), Algorithm::HS384);
92		assert_eq!(Algorithm::from_str("HS512").unwrap(), Algorithm::HS512);
93		assert_eq!(Algorithm::from_str("ES256").unwrap(), Algorithm::ES256);
94		assert_eq!(Algorithm::from_str("ES384").unwrap(), Algorithm::ES384);
95		assert_eq!(Algorithm::from_str("RS256").unwrap(), Algorithm::RS256);
96		assert_eq!(Algorithm::from_str("RS384").unwrap(), Algorithm::RS384);
97		assert_eq!(Algorithm::from_str("RS512").unwrap(), Algorithm::RS512);
98		assert_eq!(Algorithm::from_str("PS256").unwrap(), Algorithm::PS256);
99		assert_eq!(Algorithm::from_str("PS384").unwrap(), Algorithm::PS384);
100		assert_eq!(Algorithm::from_str("PS512").unwrap(), Algorithm::PS512);
101		assert_eq!(Algorithm::from_str("EdDSA").unwrap(), Algorithm::EdDSA);
102	}
103
104	#[test]
105	fn test_algorithm_from_str_invalid() {
106		assert!(Algorithm::from_str("HS128").is_err());
107		assert!(Algorithm::from_str("RS128").is_err());
108		assert!(Algorithm::from_str("ES512").is_err());
109		assert!(Algorithm::from_str("EDDSA").is_err());
110		assert!(Algorithm::from_str("invalid").is_err());
111		assert!(Algorithm::from_str("").is_err());
112	}
113
114	#[test]
115	fn test_algorithm_display() {
116		assert_eq!(Algorithm::HS256.to_string(), "HS256");
117		assert_eq!(Algorithm::HS384.to_string(), "HS384");
118		assert_eq!(Algorithm::HS512.to_string(), "HS512");
119		assert_eq!(Algorithm::ES256.to_string(), "ES256");
120		assert_eq!(Algorithm::ES384.to_string(), "ES384");
121		assert_eq!(Algorithm::RS256.to_string(), "RS256");
122		assert_eq!(Algorithm::RS384.to_string(), "RS384");
123		assert_eq!(Algorithm::RS512.to_string(), "RS512");
124		assert_eq!(Algorithm::PS256.to_string(), "PS256");
125		assert_eq!(Algorithm::PS384.to_string(), "PS384");
126		assert_eq!(Algorithm::PS512.to_string(), "PS512");
127		assert_eq!(Algorithm::EdDSA.to_string(), "EdDSA");
128	}
129
130	#[test]
131	fn test_algorithm_to_jsonwebtoken_algorithm() {
132		assert_eq!(
133			jsonwebtoken::Algorithm::from(Algorithm::HS256),
134			jsonwebtoken::Algorithm::HS256
135		);
136		assert_eq!(
137			jsonwebtoken::Algorithm::from(Algorithm::HS384),
138			jsonwebtoken::Algorithm::HS384
139		);
140		assert_eq!(
141			jsonwebtoken::Algorithm::from(Algorithm::HS512),
142			jsonwebtoken::Algorithm::HS512
143		);
144		assert_eq!(
145			jsonwebtoken::Algorithm::from(Algorithm::ES256),
146			jsonwebtoken::Algorithm::ES256
147		);
148		assert_eq!(
149			jsonwebtoken::Algorithm::from(Algorithm::ES384),
150			jsonwebtoken::Algorithm::ES384
151		);
152		assert_eq!(
153			jsonwebtoken::Algorithm::from(Algorithm::RS256),
154			jsonwebtoken::Algorithm::RS256
155		);
156		assert_eq!(
157			jsonwebtoken::Algorithm::from(Algorithm::RS384),
158			jsonwebtoken::Algorithm::RS384
159		);
160		assert_eq!(
161			jsonwebtoken::Algorithm::from(Algorithm::RS512),
162			jsonwebtoken::Algorithm::RS512
163		);
164		assert_eq!(
165			jsonwebtoken::Algorithm::from(Algorithm::PS256),
166			jsonwebtoken::Algorithm::PS256
167		);
168		assert_eq!(
169			jsonwebtoken::Algorithm::from(Algorithm::PS384),
170			jsonwebtoken::Algorithm::PS384
171		);
172		assert_eq!(
173			jsonwebtoken::Algorithm::from(Algorithm::PS512),
174			jsonwebtoken::Algorithm::PS512
175		);
176		assert_eq!(
177			jsonwebtoken::Algorithm::from(Algorithm::EdDSA),
178			jsonwebtoken::Algorithm::EdDSA
179		);
180	}
181
182	#[test]
183	fn test_algorithm_serde() {
184		let alg = Algorithm::HS256;
185		let json = serde_json::to_string(&alg).unwrap();
186		assert_eq!(json, "\"HS256\"");
187
188		let deserialized: Algorithm = serde_json::from_str(&json).unwrap();
189		assert_eq!(deserialized, alg);
190	}
191
192	#[test]
193	fn test_algorithm_equality() {
194		assert_eq!(Algorithm::HS256, Algorithm::HS256);
195		assert_ne!(Algorithm::HS256, Algorithm::HS384);
196		assert_ne!(Algorithm::HS384, Algorithm::HS512);
197		assert_eq!(Algorithm::ES256, Algorithm::ES256);
198		assert_eq!(Algorithm::ES384, Algorithm::ES384);
199		assert_ne!(Algorithm::HS384, Algorithm::ES256);
200		assert_ne!(Algorithm::ES256, Algorithm::ES384);
201		assert_eq!(Algorithm::RS256, Algorithm::RS256);
202		assert_eq!(Algorithm::RS384, Algorithm::RS384);
203		assert_eq!(Algorithm::RS512, Algorithm::RS512);
204		assert_ne!(Algorithm::RS256, Algorithm::RS512);
205		assert_ne!(Algorithm::RS256, Algorithm::PS256);
206		assert_eq!(Algorithm::PS256, Algorithm::PS256);
207		assert_eq!(Algorithm::PS384, Algorithm::PS384);
208		assert_eq!(Algorithm::PS512, Algorithm::PS512);
209		assert_ne!(Algorithm::PS256, Algorithm::PS512);
210		assert_eq!(Algorithm::EdDSA, Algorithm::EdDSA);
211		assert_ne!(Algorithm::EdDSA, Algorithm::ES256);
212		assert_ne!(Algorithm::EdDSA, Algorithm::RS512);
213	}
214
215	#[test]
216	fn test_algorithm_clone() {
217		let alg = Algorithm::HS256;
218		let cloned = alg;
219		assert_eq!(alg, cloned);
220	}
221}