secure_string/secure_types/
string.rs1use core::fmt;
2use std::str::FromStr;
3
4use crate::{secure_utils::memlock, SecureVec};
5
6#[derive(Clone, Eq)]
8pub struct SecureString(SecureVec<u8>);
9
10impl SecureString {
11 #[cfg_attr(feature = "pre", pre::pre)]
13 pub fn unsecure(&self) -> &str {
14 #[cfg_attr(
15 feature = "pre",
16 forward(pre),
17 assure(
18 "the content of `v` is valid UTF-8",
19 reason = "it is not possible to create a `SecureString` with invalid UTF-8 content
20 and it is also not possible to modify the content as non-UTF-8 directly, so
21 they must still be valid UTF-8 here"
22 )
23 )]
24 unsafe {
25 std::str::from_utf8_unchecked(self.0.unsecure())
26 }
27 }
28
29 #[cfg_attr(feature = "pre", pre::pre)]
31 pub fn unsecure_mut(&mut self) -> &mut str {
32 #[cfg_attr(
33 feature = "pre",
34 forward(pre),
35 assure(
36 "the content of `v` is valid UTF-8",
37 reason = "it is not possible to create a `SecureString` with invalid UTF-8 content
38 and it is also not possible to modify the content as non-UTF-8 directly, so
39 they must still be valid UTF-8 here"
40 )
41 )]
42 unsafe {
43 std::str::from_utf8_unchecked_mut(self.0.unsecure_mut())
44 }
45 }
46
47 #[cfg_attr(feature = "pre", pre::pre)]
49 pub fn into_unsecure(mut self) -> String {
50 memlock::munlock(self.0.content.as_mut_ptr(), self.0.content.capacity());
51 let content = std::mem::take(&mut self.0.content);
52 std::mem::forget(self);
53 #[cfg_attr(
54 feature = "pre",
55 forward(impl pre::std::string::String),
56 assure(
57 "the content of `bytes` is valid UTF-8",
58 reason = "it is not possible to create a `SecureString` with invalid UTF-8 content
59 and it is also not possible to modify the content as non-UTF-8 directly, so
60 they must still be valid UTF-8 here"
61 )
62 )]
63 unsafe {
64 String::from_utf8_unchecked(content)
65 }
66 }
67
68 pub fn zero_out(&mut self) {
72 self.0.zero_out()
73 }
74}
75
76impl PartialEq for SecureString {
77 fn eq(&self, other: &SecureString) -> bool {
78 self.0 == other.0
80 }
81}
82
83impl fmt::Debug for SecureString {
84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 f.write_str("***SECRET***").map_err(|_| fmt::Error)
86 }
87}
88
89impl fmt::Display for SecureString {
90 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91 f.write_str("***SECRET***").map_err(|_| fmt::Error)
92 }
93}
94
95impl<U> From<U> for SecureString
96where
97 U: Into<String>,
98{
99 fn from(s: U) -> SecureString {
100 SecureString(SecureVec::new(s.into().into_bytes()))
101 }
102}
103
104impl FromStr for SecureString {
105 type Err = std::convert::Infallible;
106
107 fn from_str(s: &str) -> Result<Self, Self::Err> {
108 Ok(SecureString(SecureVec::new(s.into())))
109 }
110}
111
112#[cfg(feature = "serde")]
113impl serde::Serialize for SecureString {
114 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
115 where
116 S: serde::Serializer,
117 {
118 serializer.serialize_str(self.unsecure())
119 }
120}
121
122#[cfg(feature = "serde")]
123impl<'de> serde::Deserialize<'de> for SecureString {
124 fn deserialize<D>(deserializer: D) -> Result<SecureString, D::Error>
125 where
126 D: serde::Deserializer<'de>,
127 {
128 struct SecureStringVisitor;
129 impl<'de> serde::de::Visitor<'de> for SecureStringVisitor {
130 type Value = SecureString;
131 fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
132 write!(formatter, "an utf-8 encoded string")
133 }
134 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
135 where
136 E: serde::de::Error,
137 {
138 Ok(SecureString::from(v.to_string()))
139 }
140 }
141 deserializer.deserialize_string(SecureStringVisitor)
142 }
143}