p12_keystore/
secret.rs

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/// Holds a secret key of a given type.
12#[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
19/// Implementation of the `Secret` methods.
20impl Secret {
21    /// Get key data
22    pub fn get_key(&self) -> &[u8] {
23        &self.key
24    }
25
26    /// Get the key type
27    pub fn get_key_type(&self) -> SecretKeyType {
28        self.key_type
29    }
30
31    /// gets the local_key_id as bytes
32    pub fn get_local_key_id(&self) -> Vec<u8> {
33        self.local_key_id.clone()
34    }
35
36    /// The builder to build a secret of a given type. If the type has no length assigned,
37    /// it needs also a .with_length(<bytes>).
38    /// # Example:
39    /// ```
40    /// use p12_keystore::secret::Secret;
41    /// use p12_keystore::secret::SecretKeyType::AES;
42    /// let secret = Secret::builder(AES).with_length(24).build();
43    /// ```
44    ///
45    pub fn builder(key_type: SecretKeyType) -> SecretBuilder {
46        SecretBuilder::new(key_type)
47    }
48
49    /// returns the key length in bytes
50    pub fn get_key_len(&self) -> usize {
51        self.key.len()
52    }
53}
54
55/// The builder for secrets. It starts with a secret type. If the key type has a length associated,
56/// then you do not need to set the length. You can overwrite the `local_key_id` and the `key` itself.
57///
58/// # Examples:
59/// ```
60/// use p12_keystore::secret::Secret;
61/// use p12_keystore::secret::SecretKeyType::{AES256Cbc, AES};
62///
63/// // creates a generic AES secret with any length (128,192,256 bits)
64/// let secret_aes = Secret::builder(AES).with_length(24).build();
65/// let secret_aes_256 = Secret::builder(AES256Cbc).build();
66///
67/// // build with a given local_key_id
68/// let local_key_id = vec![4,7,1,1];
69/// let secret_aes = Secret::builder(AES).with_length(32).with_local_key_id(local_key_id).build();
70///
71/// // build with a given key
72/// let key = [0u8,16];
73/// let secret_aes = Secret::builder(AES).with_key(Vec::from(key)).build();
74/// ```
75pub 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
83/// Implementation for the SecretBuilder methods
84impl SecretBuilder {
85    /// Creates a new SecretBuilder with a given key type. If SecretKeyType has a length assigned,
86    /// there is no need to set the key length
87    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    /// Provides the key length in byes. This is only required if you do not use a SecretKeyType
99    /// with a length assigned, or you do not provide a key value.
100    pub fn with_length(&mut self, len: usize) -> &mut Self {
101        self.key_len = Some(len);
102        self
103    }
104
105    /// Preloads the key, if omitted, it will be generated using OsRng
106    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    /// Predefines the local_key_id. If omitted, it is generated based on timestamp and random.
113    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    /// allows overwriting the default OsRng based `RandomGenerator` implementation
119    /// # Examples:
120    /// ```
121    /// use rand::rngs::ThreadRng;
122    /// use p12_keystore::secret::Secret;
123    /// use p12_keystore::secret::SecretKeyType::AES;
124    ///
125    /// let key = Secret::builder(AES).with_length(32).with_rng(ThreadRng::default()).build();
126    ///
127    /// ```
128    pub fn with_rng<R: RandomGenerator + 'static>(&mut self, rng: R) -> &mut Self {
129        self.rng = Box::new(rng);
130        self
131    }
132
133    /// builds the secret
134    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}
170/// Implements a simplified random generator which can be used dynamically
171pub trait RandomGenerator {
172    /// returns a random u32
173    fn try_next_u32(&mut self) -> Result<u32, SecretKeyBuilderError>;
174
175    /// fills a byte buffer with random
176    fn try_fill_bytes(&mut self, buf: &mut [u8]) -> Result<(), SecretKeyBuilderError>;
177}
178
179/// Implements random generator for all RngCore implementations
180impl<R: RngCore + ?Sized> RandomGenerator for R {
181    /// returns a random u32
182    fn try_next_u32(&mut self) -> Result<u32, SecretKeyBuilderError> {
183        Ok(R::next_u32(self))
184    }
185    /// fills a byte buffer with random
186    fn try_fill_bytes(&mut self, buf: &mut [u8]) -> Result<(), SecretKeyBuilderError> {
187        R::fill_bytes(self, buf);
188        Ok(())
189    }
190}
191
192/// OsRng based RandomGenerator
193#[derive(Default)]
194pub struct OsRngRandomGenerator;
195
196/// Implementation for OsRng
197impl 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    /// fills a byte buffer with random
206    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/// Error, which can be returned by the `SecretBuilder`
215#[derive(Debug, PartialEq)]
216pub enum SecretKeyBuilderError {
217    MissingKeyLength,
218    MissingKeyOrLocalKeyId,
219    RandomGenerationError,
220}
221
222/// Available types of secrets. If the type is unknown, use `Unknown(<oid>)`
223#[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
243/// Implements important conversions for `SecretKeyType`
244///
245impl SecretKeyType {
246    /// Builds a `SecretKeyType` from an `ObjectIdentifier`
247    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    /// Return the `ObjectIdentifier` for a `SecretKeyType`
269    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    /// returns default key length in bytes
291    pub(crate) fn default_len(&self) -> Option<usize> {
292        match self {
293            SecretKeyType::AES128Cbc => Some(16),                            // 128 bit
294            SecretKeyType::AES192Cbc => Some(24),                            // 196 bit
295            SecretKeyType::AES256Cbc => Some(32),                            // 256 bit
296            SecretKeyType::HmacSha1 | SecretKeyType::HmacSha224 => Some(64), // 512 bit
297            SecretKeyType::HmacSha256 | SecretKeyType::HmacSha384 | SecretKeyType::HmacSha512 => Some(128), // 1024 bit
298            _ => None,
299        }
300    }
301
302    /// Builds a `SecretKeyType` from an OID String
303    pub fn from_oid_str(oid_str: &str) -> Self {
304        SecretKeyType::from_oid(&ObjectIdentifier::new_unwrap(oid_str))
305    }
306}
307
308/// Implements debug for formatted output
309impl 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        // Unknown OID check (any OID not in the mapping)
390        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        // Unknown OID check (any OID not in the mapping)
419        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        // Test getters for initial values
436        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}