Skip to main content

conf_extra/
password.rs

1//! Helper type for representing passwords in command line arguments etc. that should not be logged.
2//! Zeroizes on drop.
3use core::{fmt, str::FromStr};
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6use zeroize::Zeroize;
7
8/// A wrapper around a password string which does not log the password
9/// in display or debug output.
10#[derive(Clone)]
11#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
12#[cfg_attr(feature = "serde", serde(from = "String", into = "PasswordHelper"))]
13pub struct Password(String);
14
15impl Password {
16    pub fn as_str(&self) -> &str {
17        self.0.as_str()
18    }
19}
20
21impl From<String> for Password {
22    fn from(s: String) -> Self {
23        Self(s)
24    }
25}
26
27impl From<&str> for Password {
28    fn from(s: &str) -> Self {
29        Self(s.to_owned())
30    }
31}
32
33impl FromStr for Password {
34    type Err = std::convert::Infallible; // This should actually be !
35    fn from_str(s: &str) -> Result<Self, Self::Err> {
36        Ok(Self(s.to_owned()))
37    }
38}
39
40impl AsRef<str> for Password {
41    fn as_ref(&self) -> &str {
42        self.0.as_ref()
43    }
44}
45
46impl fmt::Display for Password {
47    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
48        write!(f, "***password***")
49    }
50}
51
52impl fmt::Debug for Password {
53    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
54        write!(f, "***password***")
55    }
56}
57
58impl Drop for Password {
59    fn drop(&mut self) {
60        unsafe { self.0.as_mut_vec().zeroize() }
61    }
62}
63
64// Helper to make serde serialize using display
65// See serde (into =) attribute documentation.
66// https://serde.rs/container-attrs.html
67#[cfg(feature = "serde")]
68#[derive(Serialize)]
69#[serde(transparent)]
70struct PasswordHelper(String);
71
72#[cfg(feature = "serde")]
73impl From<Password> for PasswordHelper {
74    fn from(src: Password) -> PasswordHelper {
75        PasswordHelper(src.to_string())
76    }
77}