Skip to main content

paysec_keyblock/
secret.rs

1use std::fmt::{Debug, Formatter};
2
3use zeroize::Zeroizing;
4
5/// Plaintext cryptographic key material owned by `paysec-keyblock`.
6///
7/// `SecretKey` provides basic in-process protection for plaintext key
8/// material:
9///
10/// - its contents are redacted from [`Debug`] output,
11/// - its owned byte buffer is zeroized when dropped,
12/// - raw key bytes are available only through an explicit
13///   [`SecretKey::expose_secret`] call.
14///
15/// This type is intended for plaintext key material handled by the TR-31
16/// domain layer. It is not used for provider-managed keys such as KBPK,
17/// KBEK, or KBAK, which may be represented by opaque HSM handles or other
18/// provider-specific types.
19///
20/// # Security
21///
22/// `SecretKey` provides memory-hygiene and accidental-disclosure protection.
23/// It does not guarantee that key material has never existed elsewhere in
24/// process memory. For example, callers may retain their own copies, and
25/// operating-system facilities such as swap, crash dumps, or process memory
26/// inspection are outside the scope of this type.
27pub struct SecretKey {
28    bytes: Zeroizing<Vec<u8>>,
29}
30
31impl SecretKey {
32    /// Create a secret key by taking ownership of an existing byte vector.
33    ///
34    /// Taking ownership avoids making an additional copy of the key material.
35    pub fn new(bytes: Vec<u8>) -> Self {
36        Self {
37            bytes: Zeroizing::new(bytes),
38        }
39    }
40
41    /// Create a secret key by copying key material from a byte slice.
42    ///
43    /// The caller remains responsible for any original copy represented by
44    /// `bytes`.
45    pub fn from_slice(bytes: &[u8]) -> Self {
46        Self::new(bytes.to_vec())
47    }
48
49    /// Explicitly expose the plaintext key bytes.
50    ///
51    /// This operation is intentionally named to make access to plaintext key
52    /// material visible during code review.
53    pub fn expose_secret(&self) -> &[u8] {
54        self.bytes.as_slice()
55    }
56
57    /// Return the key length in bytes without exposing the key material.
58    pub fn len(&self) -> usize {
59        self.bytes.len()
60    }
61
62    /// Return whether the key contains no bytes.
63    pub fn is_empty(&self) -> bool {
64        self.bytes.is_empty()
65    }
66}
67
68impl Debug for SecretKey {
69    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
70        f.write_str("SecretKey([REDACTED])")
71    }
72}
73
74impl From<Vec<u8>> for SecretKey {
75    fn from(bytes: Vec<u8>) -> Self {
76        Self::new(bytes)
77    }
78}