mirror of
https://github.com/logos-messaging/libchat.git
synced 2026-03-26 22:23:14 +00:00
fix: zeroize identity record
This commit is contained in:
parent
fdacfae108
commit
0e62c44b7e
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -505,6 +505,7 @@ dependencies = [
|
|||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"x25519-dalek",
|
"x25519-dalek",
|
||||||
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user