1use serde::{Deserialize, Serialize};
4
5use crate::key::{
6 CryptographicKeyContext,
7 KeyMechanism,
8 KeyType,
9 SignatureType,
10 key_type_and_mechanisms_match_signature_type,
11 key_type_matches_length,
12 key_type_matches_mechanisms,
13};
14
15#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
20pub struct SigningKeySetup {
21 key_type: KeyType,
22 key_mechanisms: Vec<KeyMechanism>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 key_length: Option<u32>,
25 signature_type: SignatureType,
26 key_context: CryptographicKeyContext,
27}
28
29impl SigningKeySetup {
30 pub fn new(
91 key_type: KeyType,
92 key_mechanisms: Vec<KeyMechanism>,
93 key_length: Option<u32>,
94 signature_type: SignatureType,
95 cryptographic_key_context: CryptographicKeyContext,
96 ) -> Result<Self, crate::Error> {
97 key_type_matches_mechanisms(key_type, &key_mechanisms)?;
98 key_type_matches_length(key_type, key_length)?;
99 key_type_and_mechanisms_match_signature_type(key_type, &key_mechanisms, signature_type)?;
100 cryptographic_key_context.validate_signing_key_setup(
101 key_type,
102 &key_mechanisms,
103 signature_type,
104 )?;
105
106 Ok(Self {
107 key_type,
108 key_mechanisms,
109 key_length,
110 signature_type,
111 key_context: cryptographic_key_context,
112 })
113 }
114
115 pub fn key_type(&self) -> KeyType {
117 self.key_type
118 }
119
120 pub fn key_mechanisms(&self) -> &[KeyMechanism] {
122 &self.key_mechanisms
123 }
124
125 pub fn key_length(&self) -> Option<u32> {
127 self.key_length
128 }
129
130 pub fn signature_type(&self) -> SignatureType {
132 self.signature_type
133 }
134
135 pub fn key_context(&self) -> &CryptographicKeyContext {
137 &self.key_context
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use rstest::rstest;
144 use testresult::TestResult;
145
146 use super::*;
147 use crate::key::Error;
148
149 #[test]
150 fn signing_key_setup_new_succeeds() -> TestResult {
151 let setup = SigningKeySetup::new(
152 KeyType::Curve25519,
153 vec![KeyMechanism::EdDsaSignature],
154 None,
155 SignatureType::EdDsa,
156 CryptographicKeyContext::Raw,
157 )?;
158
159 assert_eq!(setup.key_type(), KeyType::Curve25519);
160 assert_eq!(setup.key_mechanisms(), [KeyMechanism::EdDsaSignature]);
161 assert_eq!(setup.key_length(), None);
162 assert_eq!(setup.signature_type(), SignatureType::EdDsa);
163 assert_eq!(setup.key_context(), &CryptographicKeyContext::Raw);
164
165 Ok(())
166 }
167
168 #[rstest]
169 #[case::curve25519_ecdsa(KeyType::Curve25519, vec![KeyMechanism::EcdsaSignature])]
170 #[case::rsa_ecdsa(KeyType::Rsa, vec![KeyMechanism::EcdsaSignature])]
171 fn signing_key_setup_new_fails_on_key_type_mechanism_mismatch(
172 #[case] key_type: KeyType,
173 #[case] key_mechanisms: Vec<KeyMechanism>,
174 ) -> TestResult {
175 let result = SigningKeySetup::new(
176 key_type,
177 key_mechanisms,
178 None,
179 SignatureType::EdDsa,
180 CryptographicKeyContext::Raw,
181 );
182
183 match result {
184 Err(crate::Error::Key(Error::InvalidKeyMechanism { .. })) => {}
185 Err(error) => {
186 panic!("Expected an Error::InvalidKeyMechanism, but got {error}");
187 }
188 Ok(setup) => {
189 panic!(
190 "Should have failed, but succeeded in creating a SigningKeySetup: {setup:?}"
191 );
192 }
193 }
194
195 Ok(())
196 }
197
198 #[rstest]
199 #[case::curve25519_with_length(KeyType::Curve25519, vec![KeyMechanism::EdDsaSignature], Some(1024))]
200 #[case::ecp521_with_length(KeyType::EcP521, vec![KeyMechanism::EcdsaSignature], Some(1024))]
201 fn signing_key_setup_new_fails_on_key_length_unsupported(
202 #[case] key_type: KeyType,
203 #[case] key_mechanisms: Vec<KeyMechanism>,
204 #[case] key_length: Option<u32>,
205 ) -> TestResult {
206 let result = SigningKeySetup::new(
207 key_type,
208 key_mechanisms,
209 key_length,
210 SignatureType::EdDsa,
211 CryptographicKeyContext::Raw,
212 );
213
214 match result {
215 Err(crate::Error::Key(Error::KeyLengthUnsupported { .. })) => {}
216 Err(error) => {
217 panic!("Expected an Error::KeyLengthUnsupported, but got {error}");
218 }
219 Ok(setup) => {
220 panic!(
221 "Should have failed, but succeeded in creating a SigningKeySetup: {setup:?}"
222 );
223 }
224 }
225
226 Ok(())
227 }
228
229 #[rstest]
230 #[case::rsa_too_short(KeyType::Rsa, vec![KeyMechanism::RsaSignaturePkcs1], Some(1024))]
231 #[case::rsa_no_length(KeyType::Rsa, vec![KeyMechanism::RsaSignaturePkcs1], None)]
232 fn signing_key_setup_new_fails_on_key_length_required_or_too_short(
233 #[case] key_type: KeyType,
234 #[case] key_mechanisms: Vec<KeyMechanism>,
235 #[case] key_length: Option<u32>,
236 ) -> TestResult {
237 let result = SigningKeySetup::new(
238 key_type,
239 key_mechanisms,
240 key_length,
241 SignatureType::EdDsa,
242 CryptographicKeyContext::Raw,
243 );
244
245 match result {
246 Err(crate::Error::Key(Error::KeyLengthRequired { .. }))
247 | Err(crate::Error::Key(Error::InvalidKeyLengthRsa { .. })) => {}
248 Err(error) => {
249 panic!(
250 "Expected an Error::KeyLengthRequired or Error::InvalidKeyLengthRsa, but got {error}"
251 );
252 }
253 Ok(setup) => {
254 panic!(
255 "Should have failed, but succeeded in creating a SigningKeySetup: {setup:?}"
256 );
257 }
258 }
259
260 Ok(())
261 }
262
263 #[rstest]
264 #[case::curve25519_ecdsap521(KeyType::Curve25519, vec![KeyMechanism::EdDsaSignature], SignatureType::EcdsaP521)]
265 #[case::ecdsap521_eddsa(KeyType::EcP521, vec![KeyMechanism::EcdsaSignature], SignatureType::EdDsa)]
266 fn signing_key_setup_new_fails_signature_type_mismatch(
267 #[case] key_type: KeyType,
268 #[case] key_mechanisms: Vec<KeyMechanism>,
269 #[case] signature_type: SignatureType,
270 ) -> TestResult {
271 let result = SigningKeySetup::new(
272 key_type,
273 key_mechanisms,
274 None,
275 signature_type,
276 CryptographicKeyContext::Raw,
277 );
278
279 match result {
280 Err(crate::Error::Key(Error::InvalidKeyTypeForSignatureType { .. }))
281 | Err(crate::Error::Key(Error::InvalidKeyMechanismsForSignatureType { .. })) => {}
282 Err(error) => {
283 panic!(
284 "Expected an Error::InvalidKeyTypeForSignatureType or Error::InvalidKeyMechanismsForSignatureType, but got {error}"
285 )
286 }
287 Ok(setup) => {
288 panic!("Should have failed, but succeeded in creating a SigningKeySetup: {setup:?}")
289 }
290 }
291
292 Ok(())
293 }
294}