jose_jwk/crypto/
keyinfo.rs

1// SPDX-FileCopyrightText: 2022 Profian Inc. <opensource@profian.com>
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4use core::ops::Deref;
5
6use alloc::{boxed::Box, vec::Vec};
7use jose_jwa::{Algorithm, Algorithm::Signing, Signing::*};
8
9use crate::{Ec, EcCurves, Jwk, Key, Oct, Okp, OkpCurves, Rsa};
10
11/// Information about a cryptographic key.
12pub trait KeyInfo {
13    /// Returns the strength of the key
14    ///
15    /// The units here is the number of bytes of a symmetric key. For
16    /// example, a P-256 elliptic curve key has an approximate strength of
17    /// `16` since it is comparable to a 16-byte symmetric key.
18    fn strength(&self) -> usize;
19
20    /// Tests if the provide algorithm is supported.
21    fn is_supported(&self, algo: &Algorithm) -> bool;
22}
23
24impl<T: KeyInfo + ?Sized> KeyInfo for &T {
25    fn strength(&self) -> usize {
26        (**self).strength()
27    }
28
29    fn is_supported(&self, algo: &Algorithm) -> bool {
30        (**self).is_supported(algo)
31    }
32}
33
34impl<T: KeyInfo + ?Sized> KeyInfo for &mut T {
35    fn strength(&self) -> usize {
36        (**self).strength()
37    }
38
39    fn is_supported(&self, algo: &Algorithm) -> bool {
40        (**self).is_supported(algo)
41    }
42}
43
44impl<T: KeyInfo + ?Sized> KeyInfo for Box<T> {
45    fn strength(&self) -> usize {
46        self.deref().strength()
47    }
48
49    fn is_supported(&self, algo: &Algorithm) -> bool {
50        self.deref().is_supported(algo)
51    }
52}
53
54impl KeyInfo for Vec<u8> {
55    fn strength(&self) -> usize {
56        self.deref().strength()
57    }
58
59    fn is_supported(&self, algo: &Algorithm) -> bool {
60        self.deref().is_supported(algo)
61    }
62}
63
64impl KeyInfo for [u8] {
65    fn strength(&self) -> usize {
66        self.len()
67    }
68
69    #[allow(clippy::match_like_matches_macro)]
70    fn is_supported(&self, algo: &Algorithm) -> bool {
71        match (algo, self.strength()) {
72            (Signing(Hs256), 16..) => true,
73            (Signing(Hs384), 24..) => true,
74            (Signing(Hs512), 32..) => true,
75            _ => false,
76        }
77    }
78}
79
80impl KeyInfo for Jwk {
81    fn strength(&self) -> usize {
82        self.key.strength()
83    }
84
85    fn is_supported(&self, algo: &Algorithm) -> bool {
86        self.key.is_supported(algo) && algo == self.prm.alg.as_ref().unwrap_or(algo)
87    }
88}
89
90impl KeyInfo for Key {
91    fn strength(&self) -> usize {
92        match self {
93            Key::Ec(x) => x.strength(),
94            Key::Rsa(x) => x.strength(),
95            Key::Oct(x) => x.strength(),
96            Key::Okp(x) => x.strength(),
97        }
98    }
99
100    fn is_supported(&self, algo: &Algorithm) -> bool {
101        match self {
102            Key::Ec(x) => x.is_supported(algo),
103            Key::Rsa(x) => x.is_supported(algo),
104            Key::Oct(x) => x.is_supported(algo),
105            Key::Okp(x) => x.is_supported(algo),
106        }
107    }
108}
109
110impl KeyInfo for Ec {
111    fn strength(&self) -> usize {
112        match self.crv {
113            EcCurves::P256 => 16,
114            EcCurves::P256K => 16,
115            EcCurves::P384 => 24,
116            EcCurves::P521 => 32,
117        }
118    }
119
120    #[allow(clippy::match_like_matches_macro)]
121    fn is_supported(&self, algo: &Algorithm) -> bool {
122        match (self.crv, algo) {
123            (EcCurves::P256, Signing(Es256)) => true,
124            (EcCurves::P256K, Signing(Es256K)) => true,
125            (EcCurves::P384, Signing(Es384)) => true,
126            (EcCurves::P521, Signing(Es512)) => true,
127            _ => false,
128        }
129    }
130}
131
132impl KeyInfo for Oct {
133    fn strength(&self) -> usize {
134        self.k.len()
135    }
136
137    #[allow(clippy::match_like_matches_macro)]
138    fn is_supported(&self, algo: &Algorithm) -> bool {
139        match (algo, self.strength()) {
140            (Signing(Hs256), 16..) => true,
141            (Signing(Hs384), 24..) => true,
142            (Signing(Hs512), 32..) => true,
143            _ => false,
144        }
145    }
146}
147
148impl KeyInfo for Okp {
149    fn strength(&self) -> usize {
150        match self.crv {
151            OkpCurves::Ed25519 => 16,
152            OkpCurves::Ed448 => 24,
153            OkpCurves::X25519 => 16,
154            OkpCurves::X448 => 24,
155        }
156    }
157
158    fn is_supported(&self, algo: &Algorithm) -> bool {
159        matches!(algo, Signing(EdDsa))
160    }
161}
162
163impl KeyInfo for Rsa {
164    fn strength(&self) -> usize {
165        self.n.len() / 16
166    }
167
168    #[allow(clippy::match_like_matches_macro)]
169    fn is_supported(&self, algo: &Algorithm) -> bool {
170        match (algo, self.strength()) {
171            (Signing(Rs256), 16..) => true,
172            (Signing(Rs384), 24..) => true,
173            (Signing(Rs512), 32..) => true,
174            (Signing(Ps256), 16..) => true,
175            (Signing(Ps384), 24..) => true,
176            (Signing(Ps512), 32..) => true,
177            _ => false,
178        }
179    }
180}