fix: zeroize identity record

This commit is contained in:
kaichaosun 2026-02-27 15:48:44 +08:00
parent fdacfae108
commit 0e62c44b7e
No known key found for this signature in database
GPG Key ID: 223E0F992F4F03BF
3 changed files with 42 additions and 2 deletions

1
Cargo.lock generated
View File

@ -505,6 +505,7 @@ dependencies = [
"tempfile", "tempfile",
"thiserror", "thiserror",
"x25519-dalek", "x25519-dalek",
"zeroize",
] ]
[[package]] [[package]]

View File

@ -19,6 +19,7 @@ safer-ffi = "0.1.13"
thiserror = "2.0.17" thiserror = "2.0.17"
x25519-dalek = { version = "2.0.1", features = ["static_secrets", "reusable_secrets", "getrandom"] } x25519-dalek = { version = "2.0.1", features = ["static_secrets", "reusable_secrets", "getrandom"] }
storage = { path = "../storage" } storage = { path = "../storage" }
zeroize = { version = "1.8.2", features = ["derive"] }
[dev-dependencies] [dev-dependencies]
tempfile = "3" tempfile = "3"

View File

@ -1,10 +1,13 @@
//! Storage record types for serialization/deserialization. //! Storage record types for serialization/deserialization.
use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::crypto::PrivateKey; use crate::crypto::PrivateKey;
use crate::identity::Identity; use crate::identity::Identity;
/// Record for storing identity (secret key). /// Record for storing identity (secret key).
#[derive(Debug)] /// Implements ZeroizeOnDrop to securely clear secret key from memory.
#[derive(Debug, Zeroize, ZeroizeOnDrop)]
pub struct IdentityRecord { pub struct IdentityRecord {
/// The identity name. /// The identity name.
pub name: String, pub name: String,
@ -14,7 +17,42 @@ pub struct IdentityRecord {
impl From<IdentityRecord> for Identity { impl From<IdentityRecord> for Identity {
fn from(record: IdentityRecord) -> Self { fn from(record: IdentityRecord) -> Self {
let name = record.name.clone();
let secret = PrivateKey::from(record.secret_key); let secret = PrivateKey::from(record.secret_key);
Identity::from_secret(record.name, secret) Identity::from_secret(name, secret)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_identity_record_zeroize() {
let secret_key = [0xAB_u8; 32];
let mut record = IdentityRecord {
name: "test".to_string(),
secret_key,
};
// Get a pointer to the secret key before zeroizing
let ptr = record.secret_key.as_ptr();
// Manually zeroize (simulates what ZeroizeOnDrop does)
record.zeroize();
// Verify the memory is zeroed
// SAFETY: ptr still points to valid memory within record
unsafe {
let slice = std::slice::from_raw_parts(ptr, 32);
assert!(slice.iter().all(|&b| b == 0), "secret_key should be zeroed");
}
// Also verify via the struct field
assert!(
record.secret_key.iter().all(|&b| b == 0),
"secret_key field should be zeroed"
);
assert!(record.name.is_empty(), "name should be cleared");
} }
} }