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}