Expand description
§Secure Types
The goal of this crate is to provide a simple way to properly handle sensitive data in memory (eg. passwords, private keys, etc).
Currently there are 3 types:
SecureString: For working with strings.SecureVec: For working withVec<T>.SecureArray: For working with&[T; LENGTH].
§Features
- Zeroization on Drop: Memory is wiped when dropped.
- Memory Locking: (OS-only) The allocation is
mlocked (Windows:VirtualLock) and excluded from core dumps (MADV_DONTDUMP), so it cannot be swapped out or captured in a crash dump. While nounlock*scope is active the pages are alsomprotectedPROT_NONE, which is what keeps the contents away from other processes. On Linux the allocation is backed bymemfd_secretwhen the kernel supports it. - Safe Scoped Access: Direct access on these types is not possible, data is protected by default and only accessible within safe blocks.
- Send, not Sync: Values can be moved to another thread. Sharing one instance across threads requires an explicit lock (
Arc<Mutex<_>>). Concurrentunlockwould race on page protection. no_stdSupport: For embedded and Web environments (with zeroization only). Select it by turning off the default features — see Feature Flags.- Serde Support: Optional serialization/deserialization for
SecureString,SecureVec<u8>andSecureArray<u8, LENGTH>.
§How memory is locked
-
Windows: Using VirtualProtect & VirtualLock.
-
Linux: Using mlock & madvise. If the kernel supports it, it will allocate with memfd_secret.
Locking is best-effort in one respect: memsec discards the return value of mlock, so
exhausting RLIMIT_MEMLOCK does not fail construction — the allocation is still
mprotected. The constructors return Error::LockFailed when that mprotect fails, and a
failed re-lock after an unlock* scope panics in every profile rather than silently
leaving the memory readable.
§Usage
§SecureString
use secure_types::SecureString;
// Create a SecureString
let mut secret = SecureString::from("my_super_secret");
// The memory is locked here
// Safely append more data.
secret.push_str("_password");
// The memory is locked here.
// Use a scope to safely access the content as a &str.
secret.unlock_str(|exposed_str| {
assert_eq!(exposed_str, "my_super_secret_password");
});
// When `secret` is dropped, its data zeroized.§SecureVec
use secure_types::SecureVec;
// Create a new, empty secure vector.
let mut secret_key: SecureVec<u8> = SecureVec::new().unwrap();
// Push some sensitive data into it.
secret_key.push(0);
secret_key.push(1);
secret_key.push(2);
// The memory is locked here.
// Use a scope to safely access the contents as a slice.
secret_key.unlock_slice(|unlocked_slice| {
assert_eq!(unlocked_slice, &[0, 1, 2]);
});§SecureArray
use secure_types::SecureArray;
let exposed_array: &mut [u8; 3] = &mut [1, 2, 3];
let mut secure_array = SecureArray::from_slice_mut(exposed_array).unwrap();
secure_array.unlock_mut(|unlocked_slice| {
assert_eq!(unlocked_slice, &[1, 2, 3]);
});§See also the examples.
§Feature Flags
use_os(default): Enables all OS-level security features.no_os: No-op, kept for backwards compatibility.no_stdis selected by disabling the default features (--no-default-features), which leaves only the zeroize-on-drop guarantee.serde: Enables serialization/deserialization.serde_json: Addsserialize_json_into_secure_bytes/serialize_json_into_secure_string, which serialize straight into aSecureVec<u8>/SecureStringinstead of an ordinaryVec/String. Impliesserdeand requiresuse_os.expose-ptr: For testing purposes. Exposes the locked memory region pointer.
§Security notes
- Serialization writes plaintext.
Serializecannot wipe the buffer the serializer builds for it:serde_json::to_string/to_vecleave the plaintext in an ordinaryString/Vecthat nothing zeroizes, so zeroize that buffer yourself if you call them. zeroized on drop. Preferserialize_json_into_secure_bytes(featureserde_json) when the JSON is going to be compressed or encrypted, orserialize_json_into_secure_stringif you want the text form or wire any serializer aroundSecureBytesWriterthe plaintext then only ever lives in locked memory that is zeroized on drop. - Deserializing reads from a buffer you own.
serde_json::from_str/from_slicetake a plain&str/&[u8], and nothing can wipe that input for you. Parse from inside the locked buffer instead —secure_json.unlock_str(|json| serde_json::from_str::<Vault>(json))— so the plaintext is unlocked only for the duration of the parse. Note that when a JSON string contains escape sequences,serde_jsonunescapes it into an internal scratch buffer of its own before handing it over; that copy is not ours to erase (strings without escapes are read straight out of your input). - Owned buffers a deserializer hands over are wiped. When a format gives up ownership of a
String/Vec<u8>(visit_string/visit_byte_buf), the contents are copied into locked memory and the buffer is zeroized before it is released, instead of being dropped with the plaintext still inside. - Leaking a
Drainstill skips drops.SecureVec::drainunlocks the memory only while an item is read and while the iterator compacts the vector, so acore::mem::forgetped iterator leaves the memory locked but the elements left in the drained range are never dropped or zeroized, and the length stays at the drain start. Consume or drop the iterator. clear()does not wipe.SecureVec::clearonly sets the length to zero the bytes are still there. Useerase()to zeroize the contents.SecureArray::empty()has a strict contract. Only the elements that were actually written are tracked as initialized, so dropping a partially-filled array never reads the unwritten slots. Those slots are not validTs though: fill the whole array (for example viaunlock_mut) before reading it.
§Running tests
cargo test --features serde,expose-ptr§License
Licensed under the MIT license.
§Credits
Re-exports§
pub use array::SecureArray;pub use string::SecureString;pub use vec::SecureBytes;pub use vec::SecureVec;pub use writer::SecureBytesWriter;pub use memsec;
Modules§
- array
- string
- vec
- writer
- An
std::io::Writeadapter that appends into locked, zeroizing memory.
Enums§
Traits§
- Zeroize
- Trait for securely erasing values from memory.