1use crate::oid::{
2 AES_128_CBC_KEY_OID, AES_192_CBC_KEY_OID, AES_256_CBC_KEY_OID, AES_GROUP_KEY_OID, BLOWFISH_KEY_OID,
3 CAMELIA_KEY_OID, DES_CBC_KEY_OID, DES_EDE3_CBC_KEY_OID, HMAC_SHA1_KEY_OID, HMAC_SHA224_KEY_OID,
4 HMAC_SHA256_KEY_OID, HMAC_SHA384_KEY_OID, HMAC_SHA512_KEY_OID, RC2_CBC_KEY_OID, RC4_KEY_OID,
5};
6use cms::cert::x509::spki::ObjectIdentifier;
7use rand::{RngCore, TryRngCore, rngs::OsRng};
8use std::fmt;
9use std::time::UNIX_EPOCH;
10
11#[derive(Clone, PartialEq, Eq)]
13pub struct Secret {
14 pub(crate) key_type: SecretKeyType,
15 pub(crate) key: Vec<u8>,
16 pub(crate) local_key_id: Vec<u8>,
17}
18
19impl Secret {
21 pub fn get_key(&self) -> &[u8] {
23 &self.key
24 }
25
26 pub fn get_key_type(&self) -> SecretKeyType {
28 self.key_type
29 }
30
31 pub fn get_local_key_id(&self) -> Vec<u8> {
33 self.local_key_id.clone()
34 }
35
36 pub fn builder(key_type: SecretKeyType) -> SecretBuilder {
46 SecretBuilder::new(key_type)
47 }
48
49 pub fn get_key_len(&self) -> usize {
51 self.key.len()
52 }
53}
54
55pub struct SecretBuilder {
76 key_type: SecretKeyType,
77 key: Option<Vec<u8>>,
78 local_key_id: Option<Vec<u8>>,
79 key_len: Option<usize>,
80 rng: Box<dyn RandomGenerator>,
81}
82
83impl SecretBuilder {
85 pub fn new(key_type: SecretKeyType) -> Self {
88 let key_len = key_type.default_len();
89 SecretBuilder {
90 key_type,
91 key: None,
92 local_key_id: None,
93 key_len,
94 rng: Box::new(OsRngRandomGenerator),
95 }
96 }
97
98 pub fn with_length(&mut self, len: usize) -> &mut Self {
101 self.key_len = Some(len);
102 self
103 }
104
105 pub fn with_key(&mut self, key: Vec<u8>) -> &mut Self {
107 self.key_len = Some(key.len());
108 self.key = Some(key);
109 self
110 }
111
112 pub fn with_local_key_id(&mut self, local_key_id: Vec<u8>) -> &mut Self {
114 self.local_key_id = Some(local_key_id);
115 self
116 }
117
118 pub fn with_rng<R: RandomGenerator + 'static>(&mut self, rng: R) -> &mut Self {
129 self.rng = Box::new(rng);
130 self
131 }
132
133 pub fn build(&mut self) -> Result<Secret, SecretKeyBuilderError> {
135 if self.local_key_id.is_none() {
136 let key_id_rng = self.rng.try_next_u32();
137
138 match key_id_rng {
139 Ok(key_id) => {
140 let ts = UNIX_EPOCH.elapsed().unwrap_or_default().as_millis();
141 self.local_key_id = Some(format!("{ts:0}:{key_id:0}").as_bytes().to_vec());
142 }
143 Err(_) => return Err(SecretKeyBuilderError::RandomGenerationError),
144 }
145 }
146
147 if self.key.is_none() {
148 if let Some(key_len) = self.key_len {
149 let mut key = vec![0u8; key_len];
150 if self.rng.try_fill_bytes(&mut key).is_err() {
151 return Err(SecretKeyBuilderError::RandomGenerationError);
152 }
153 self.key = Some(key);
154 } else {
155 return Err(SecretKeyBuilderError::MissingKeyLength);
156 }
157 }
158
159 if let (Some(key), Some(local_key_id)) = (&self.key, &self.local_key_id) {
160 Ok(Secret {
161 key_type: self.key_type,
162 key: key.clone(),
163 local_key_id: local_key_id.clone(),
164 })
165 } else {
166 Err(SecretKeyBuilderError::MissingKeyOrLocalKeyId)
167 }
168 }
169}
170pub trait RandomGenerator {
172 fn try_next_u32(&mut self) -> Result<u32, SecretKeyBuilderError>;
174
175 fn try_fill_bytes(&mut self, buf: &mut [u8]) -> Result<(), SecretKeyBuilderError>;
177}
178
179impl<R: RngCore + ?Sized> RandomGenerator for R {
181 fn try_next_u32(&mut self) -> Result<u32, SecretKeyBuilderError> {
183 Ok(R::next_u32(self))
184 }
185 fn try_fill_bytes(&mut self, buf: &mut [u8]) -> Result<(), SecretKeyBuilderError> {
187 R::fill_bytes(self, buf);
188 Ok(())
189 }
190}
191
192#[derive(Default)]
194pub struct OsRngRandomGenerator;
195
196impl RandomGenerator for OsRngRandomGenerator {
198 fn try_next_u32(&mut self) -> Result<u32, SecretKeyBuilderError> {
199 match OsRng.try_next_u32() {
200 Ok(rnd) => Ok(rnd),
201 Err(_) => Err(SecretKeyBuilderError::RandomGenerationError),
202 }
203 }
204
205 fn try_fill_bytes(&mut self, buf: &mut [u8]) -> Result<(), SecretKeyBuilderError> {
207 match OsRng.try_fill_bytes(buf) {
208 Ok(_) => Ok(()),
209 Err(_) => Err(SecretKeyBuilderError::RandomGenerationError),
210 }
211 }
212}
213
214#[derive(Debug, PartialEq)]
216pub enum SecretKeyBuilderError {
217 MissingKeyLength,
218 MissingKeyOrLocalKeyId,
219 RandomGenerationError,
220}
221
222#[derive(Debug, Clone, Copy, PartialEq, Eq)]
224pub enum SecretKeyType {
225 AES,
226 AES128Cbc,
227 AES192Cbc,
228 AES256Cbc,
229 DesCbc,
230 DesEde3Cbc,
231 Blowfish,
232 Rc2Cbc,
233 Rc4,
234 Camelia,
235 HmacSha1,
236 HmacSha224,
237 HmacSha256,
238 HmacSha384,
239 HmacSha512,
240 Unknown(ObjectIdentifier),
241}
242
243impl SecretKeyType {
246 pub fn from_oid(oid: &ObjectIdentifier) -> Self {
248 match *oid {
249 o if o == AES_GROUP_KEY_OID => SecretKeyType::AES,
250 o if o == AES_128_CBC_KEY_OID => SecretKeyType::AES128Cbc,
251 o if o == AES_192_CBC_KEY_OID => SecretKeyType::AES192Cbc,
252 o if o == AES_256_CBC_KEY_OID => SecretKeyType::AES256Cbc,
253 o if o == DES_CBC_KEY_OID => SecretKeyType::DesCbc,
254 o if o == DES_EDE3_CBC_KEY_OID => SecretKeyType::DesEde3Cbc,
255 o if o == BLOWFISH_KEY_OID => SecretKeyType::Blowfish,
256 o if o == RC2_CBC_KEY_OID => SecretKeyType::Rc2Cbc,
257 o if o == RC4_KEY_OID => SecretKeyType::Rc4,
258 o if o == CAMELIA_KEY_OID => SecretKeyType::Camelia,
259 o if o == HMAC_SHA1_KEY_OID => SecretKeyType::HmacSha1,
260 o if o == HMAC_SHA224_KEY_OID => SecretKeyType::HmacSha224,
261 o if o == HMAC_SHA256_KEY_OID => SecretKeyType::HmacSha256,
262 o if o == HMAC_SHA384_KEY_OID => SecretKeyType::HmacSha384,
263 o if o == HMAC_SHA512_KEY_OID => SecretKeyType::HmacSha512,
264 _ => SecretKeyType::Unknown(*oid),
265 }
266 }
267
268 pub fn to_oid(&self) -> ObjectIdentifier {
270 match self {
271 SecretKeyType::AES => AES_GROUP_KEY_OID,
272 SecretKeyType::AES128Cbc => AES_128_CBC_KEY_OID,
273 SecretKeyType::AES192Cbc => AES_192_CBC_KEY_OID,
274 SecretKeyType::AES256Cbc => AES_256_CBC_KEY_OID,
275 SecretKeyType::DesCbc => DES_CBC_KEY_OID,
276 SecretKeyType::DesEde3Cbc => DES_EDE3_CBC_KEY_OID,
277 SecretKeyType::Blowfish => BLOWFISH_KEY_OID,
278 SecretKeyType::Rc2Cbc => RC2_CBC_KEY_OID,
279 SecretKeyType::Rc4 => RC4_KEY_OID,
280 SecretKeyType::Camelia => CAMELIA_KEY_OID,
281 SecretKeyType::HmacSha1 => HMAC_SHA1_KEY_OID,
282 SecretKeyType::HmacSha224 => HMAC_SHA224_KEY_OID,
283 SecretKeyType::HmacSha256 => HMAC_SHA256_KEY_OID,
284 SecretKeyType::HmacSha384 => HMAC_SHA384_KEY_OID,
285 SecretKeyType::HmacSha512 => HMAC_SHA512_KEY_OID,
286 SecretKeyType::Unknown(oid) => *oid,
287 }
288 }
289
290 pub(crate) fn default_len(&self) -> Option<usize> {
292 match self {
293 SecretKeyType::AES128Cbc => Some(16), SecretKeyType::AES192Cbc => Some(24), SecretKeyType::AES256Cbc => Some(32), SecretKeyType::HmacSha1 | SecretKeyType::HmacSha224 => Some(64), SecretKeyType::HmacSha256 | SecretKeyType::HmacSha384 | SecretKeyType::HmacSha512 => Some(128), _ => None,
299 }
300 }
301
302 pub fn from_oid_str(oid_str: &str) -> Self {
304 SecretKeyType::from_oid(&ObjectIdentifier::new_unwrap(oid_str))
305 }
306}
307
308impl fmt::Debug for Secret {
310 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311 f.debug_struct("PrivateKeyChain")
312 .field("algorithm_oid", &self.key_type)
313 .field("key", &"<KEY>")
314 .field("local_key_id", &hex::encode(&self.local_key_id))
315 .finish()
316 }
317}
318
319#[cfg(test)]
320mod tests {
321 use crate::oid::*;
322 use crate::secret::{Secret, SecretKeyBuilderError, SecretKeyType};
323 use der::oid::ObjectIdentifier;
324 use rand::rngs::ThreadRng;
325
326 #[test]
327 fn test_from_oid_str() {
328 assert_eq!(
329 SecretKeyType::AES,
330 SecretKeyType::from_oid_str(&AES_GROUP_KEY_OID.to_string())
331 );
332 assert_eq!(
333 SecretKeyType::AES128Cbc,
334 SecretKeyType::from_oid_str(&AES_128_CBC_KEY_OID.to_string())
335 );
336 assert_eq!(
337 SecretKeyType::AES192Cbc,
338 SecretKeyType::from_oid_str(&AES_192_CBC_KEY_OID.to_string())
339 );
340 assert_eq!(
341 SecretKeyType::AES256Cbc,
342 SecretKeyType::from_oid_str(&AES_256_CBC_KEY_OID.to_string())
343 );
344 assert_eq!(
345 SecretKeyType::DesCbc,
346 SecretKeyType::from_oid_str(&DES_CBC_KEY_OID.to_string())
347 );
348 assert_eq!(
349 SecretKeyType::DesEde3Cbc,
350 SecretKeyType::from_oid_str(&DES_EDE3_CBC_KEY_OID.to_string())
351 );
352 assert_eq!(
353 SecretKeyType::Blowfish,
354 SecretKeyType::from_oid_str(&BLOWFISH_KEY_OID.to_string())
355 );
356 assert_eq!(
357 SecretKeyType::Rc2Cbc,
358 SecretKeyType::from_oid_str(&RC2_CBC_KEY_OID.to_string())
359 );
360 assert_eq!(
361 SecretKeyType::Rc4,
362 SecretKeyType::from_oid_str(&RC4_KEY_OID.to_string())
363 );
364 assert_eq!(
365 SecretKeyType::Camelia,
366 SecretKeyType::from_oid_str(&CAMELIA_KEY_OID.to_string())
367 );
368 assert_eq!(
369 SecretKeyType::HmacSha1,
370 SecretKeyType::from_oid_str(&HMAC_SHA1_KEY_OID.to_string())
371 );
372 assert_eq!(
373 SecretKeyType::HmacSha224,
374 SecretKeyType::from_oid_str(&HMAC_SHA224_KEY_OID.to_string())
375 );
376 assert_eq!(
377 SecretKeyType::HmacSha256,
378 SecretKeyType::from_oid_str(&HMAC_SHA256_KEY_OID.to_string())
379 );
380 assert_eq!(
381 SecretKeyType::HmacSha384,
382 SecretKeyType::from_oid_str(&HMAC_SHA384_KEY_OID.to_string())
383 );
384 assert_eq!(
385 SecretKeyType::HmacSha512,
386 SecretKeyType::from_oid_str(&HMAC_SHA512_KEY_OID.to_string())
387 );
388
389 let dummy_oid = ObjectIdentifier::new_unwrap("1.2.3.4.5.6.7");
391 assert_eq!(
392 SecretKeyType::Unknown(dummy_oid),
393 SecretKeyType::from_oid_str("1.2.3.4.5.6.7")
394 );
395 }
396
397 #[test]
398 fn test_from_oid() {
399 assert_eq!(SecretKeyType::AES, SecretKeyType::from_oid(&AES_GROUP_KEY_OID));
400 assert_eq!(SecretKeyType::AES128Cbc, SecretKeyType::from_oid(&AES_128_CBC_KEY_OID));
401 assert_eq!(SecretKeyType::AES192Cbc, SecretKeyType::from_oid(&AES_192_CBC_KEY_OID));
402 assert_eq!(SecretKeyType::AES256Cbc, SecretKeyType::from_oid(&AES_256_CBC_KEY_OID));
403 assert_eq!(SecretKeyType::DesCbc, SecretKeyType::from_oid(&DES_CBC_KEY_OID));
404 assert_eq!(
405 SecretKeyType::DesEde3Cbc,
406 SecretKeyType::from_oid(&DES_EDE3_CBC_KEY_OID)
407 );
408 assert_eq!(SecretKeyType::Blowfish, SecretKeyType::from_oid(&BLOWFISH_KEY_OID));
409 assert_eq!(SecretKeyType::Rc2Cbc, SecretKeyType::from_oid(&RC2_CBC_KEY_OID));
410 assert_eq!(SecretKeyType::Rc4, SecretKeyType::from_oid(&RC4_KEY_OID));
411 assert_eq!(SecretKeyType::Camelia, SecretKeyType::from_oid(&CAMELIA_KEY_OID));
412 assert_eq!(SecretKeyType::HmacSha1, SecretKeyType::from_oid(&HMAC_SHA1_KEY_OID));
413 assert_eq!(SecretKeyType::HmacSha224, SecretKeyType::from_oid(&HMAC_SHA224_KEY_OID));
414 assert_eq!(SecretKeyType::HmacSha256, SecretKeyType::from_oid(&HMAC_SHA256_KEY_OID));
415 assert_eq!(SecretKeyType::HmacSha384, SecretKeyType::from_oid(&HMAC_SHA384_KEY_OID));
416 assert_eq!(SecretKeyType::HmacSha512, SecretKeyType::from_oid(&HMAC_SHA512_KEY_OID));
417
418 let dummy_oid = ObjectIdentifier::new_unwrap("1.2.3.4.5.6.7");
420 assert_eq!(SecretKeyType::Unknown(dummy_oid), SecretKeyType::from_oid(&dummy_oid));
421 }
422
423 #[test]
424 fn test_getters() {
425 let initial_key = vec![1, 2, 3];
426 let initial_key_type = SecretKeyType::AES128Cbc;
427 let initial_local_key_id = vec![10, 20, 30];
428
429 let secret = Secret {
430 key: initial_key.clone(),
431 key_type: initial_key_type,
432 local_key_id: initial_local_key_id.clone(),
433 };
434
435 assert_eq!(secret.get_key(), &initial_key[..]);
437 assert_eq!(secret.get_key_type(), initial_key_type);
438 assert_eq!(secret.get_local_key_id(), initial_local_key_id);
439 }
440
441 #[test]
442 fn test_secret_builder() {
443 let secret = Secret::builder(SecretKeyType::AES256Cbc).build();
444 assert!(secret.is_ok());
445 if let Ok(secret) = secret {
446 assert_eq!(secret.get_key_type(), SecretKeyType::AES256Cbc);
447 assert_eq!(secret.get_key_len(), 32);
448 }
449 }
450
451 #[test]
452 fn test_secret_builder_with_aes128_generic() {
453 let secret = Secret::builder(SecretKeyType::AES).with_length(16).build();
454 assert!(secret.is_ok());
455 if let Ok(secret) = secret {
456 assert_eq!(secret.get_key_type(), SecretKeyType::AES);
457 assert_eq!(secret.get_key_len(), 16);
458 }
459 }
460
461 #[test]
462 fn test_secret_builder_with_aes192() {
463 let secret = Secret::builder(SecretKeyType::AES192Cbc).build();
464 assert!(secret.is_ok());
465 if let Ok(secret) = secret {
466 assert_eq!(secret.get_key_type(), SecretKeyType::AES192Cbc);
467 assert_eq!(secret.get_key_len(), 24);
468 }
469 }
470
471 #[test]
472 fn test_secret_builder_with_missing_len() {
473 let secret = Secret::builder(SecretKeyType::AES).build();
474 assert!(secret.is_err());
475 if let Err(e) = secret {
476 assert_eq!(e, SecretKeyBuilderError::MissingKeyLength);
477 }
478 }
479
480 #[test]
481 fn test_secret_builder_with_val() {
482 let key_val = [[17u8; 32]].as_flattened().to_vec();
483 let secret = Secret::builder(SecretKeyType::AES).with_key(key_val.clone()).build();
484 assert!(secret.is_ok());
485 if let Ok(secret) = secret {
486 assert_eq!(secret.get_key_type(), SecretKeyType::AES);
487 assert_eq!(secret.get_key_len(), 32);
488 assert_eq!(key_val, secret.get_key());
489 }
490 }
491
492 #[test]
493 fn test_secret_builder_with_val_n_id() {
494 let key_val = [[17u8; 32]].as_flattened().to_vec();
495 let key_id_val = [[0u8; 20]].as_flattened().to_vec();
496 let secret = Secret::builder(SecretKeyType::AES256Cbc)
497 .with_key(key_val.clone())
498 .with_local_key_id(key_id_val.clone())
499 .build();
500 assert!(secret.is_ok());
501 if let Ok(secret) = secret {
502 assert_eq!(secret.get_key_type(), SecretKeyType::AES256Cbc);
503 assert_eq!(secret.get_key_len(), 32);
504 assert_eq!(key_val, secret.get_key());
505 assert_eq!(key_id_val, secret.get_local_key_id());
506 }
507 }
508
509 #[test]
510 fn test_secret_builder_with_non_default_rng() {
511 let secret = Secret::builder(SecretKeyType::AES256Cbc)
512 .with_rng(ThreadRng::default())
513 .build();
514 assert!(secret.is_ok());
515 if let Ok(secret) = secret {
516 assert_eq!(secret.get_key_type(), SecretKeyType::AES256Cbc);
517 assert_eq!(secret.get_key_len(), 32);
518 }
519 }
520}