use zeroize::Zeroizing;
#[derive(Debug)]
pub struct SecureString(Zeroizing<String>);
impl SecureString {
pub fn new(s: String) -> Self {
Self(Zeroizing::new(s))
}
pub fn as_str(&self) -> &str {
self.0.as_str()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl Clone for SecureString {
fn clone(&self) -> Self {
Self::new(self.0.as_str().to_string())
}
}
#[derive(Debug, Clone)]
pub struct SecureKey(Zeroizing<[u8; 32]>);
impl SecureKey {
pub fn new(key: [u8; 32]) -> Self {
Self(Zeroizing::new(key))
}
pub fn as_bytes(&self) -> &[u8; 32] {
&self.0
}
}
#[derive(Debug, Clone)]
pub struct SecureBytes(Zeroizing<Vec<u8>>);
impl SecureBytes {
pub fn new(data: Vec<u8>) -> Self {
Self(Zeroizing::new(data))
}
pub fn as_slice(&self) -> &[u8] {
&self.0
}
pub fn with_capacity(capacity: usize) -> Self {
Self(Zeroizing::new(Vec::with_capacity(capacity)))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_secure_string_basic() {
let s = SecureString::new("test_password".to_string());
assert_eq!(s.as_str(), "test_password");
assert!(!s.is_empty());
let empty = SecureString::new(String::new());
assert!(empty.is_empty());
}
#[test]
fn test_secure_string_clone() {
let original = SecureString::new("test_password".to_string());
let cloned = original.clone();
assert_eq!(original.as_str(), cloned.as_str());
}
#[test]
fn test_secure_key_basic() {
let key_bytes = [42u8; 32];
let key = SecureKey::new(key_bytes);
assert_eq!(key.as_bytes(), &key_bytes);
}
#[test]
fn test_secure_key_clone() {
let key_bytes = [42u8; 32];
let original = SecureKey::new(key_bytes);
let cloned = original.clone();
assert_eq!(original.as_bytes(), cloned.as_bytes());
}
#[test]
fn test_secure_bytes_basic() {
let data = vec![1, 2, 3, 4, 5];
let secure_data = SecureBytes::new(data.clone());
assert_eq!(secure_data.as_slice(), data.as_slice());
}
#[test]
fn test_secure_bytes_with_capacity() {
let capacity = 100;
let secure_data = SecureBytes::with_capacity(capacity);
assert!(secure_data.as_slice().is_empty());
}
}