Skip to main content

coven_crypto/
secret.rs

1//! Bytes and text crossing custody or provider boundaries remain secrets.
2
3use zeroize::Zeroizing;
4
5/// Secret bytes for custody or a restore code, erased on drop and never printed.
6/// Callers retaining a copy are responsible for erasing that copy too.
7pub struct SecretBytes(pub(crate) Zeroizing<Vec<u8>>);
8
9impl SecretBytes {
10    /// Take ownership of secret bytes, including any allocation capacity.
11    pub fn new(bytes: Vec<u8>) -> Self {
12        Self(Zeroizing::new(bytes))
13    }
14
15    /// Borrow the bytes while writing custody or encoding a restore code (ยง13).
16    pub fn as_bytes(&self) -> &[u8] {
17        &self.0
18    }
19
20    /// Allocation capacity for tests checking that secret encoders never grow it.
21    #[cfg(feature = "test-utils")]
22    pub fn capacity(&self) -> usize {
23        self.0.capacity()
24    }
25}
26
27impl std::fmt::Debug for SecretBytes {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        f.write_str("SecretBytes([REDACTED])")
30    }
31}
32
33/// UTF-8 secret text, erased on drop and redacted in diagnostic output.
34/// Callers retaining a copy are responsible for erasing that copy too.
35#[derive(Clone, serde::Serialize, serde::Deserialize)]
36#[serde(transparent)]
37pub struct SecretText(Zeroizing<String>);
38
39impl SecretText {
40    /// Take ownership of secret text, including its allocation capacity.
41    pub fn new(text: String) -> Self {
42        Self(Zeroizing::new(text))
43    }
44
45    /// Borrow text while making a provider request or committing to custody.
46    pub fn as_str(&self) -> &str {
47        &self.0
48    }
49}
50
51impl std::fmt::Debug for SecretText {
52    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53        f.write_str("SecretText([REDACTED])")
54    }
55}
56
57#[cfg(test)]
58#[path = "secret_tests.rs"]
59mod tests;