From 0b0f1cea7377e9988a7fe66d557c822b17cec566 Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Sun, 19 Apr 2026 13:06:50 -0400 Subject: [PATCH] feat(core): flesh out KeyCore Co-Authored-By: Claude Opus 4.7 (1M context) --- crates/idfoto-core/src/item_types/key.rs | 41 +++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/crates/idfoto-core/src/item_types/key.rs b/crates/idfoto-core/src/item_types/key.rs index 011d1b9..2a5c52a 100644 --- a/crates/idfoto-core/src/item_types/key.rs +++ b/crates/idfoto-core/src/item_types/key.rs @@ -1,3 +1,42 @@ +//! Key: arbitrary key material (Zeroizing), label, public key, algorithm. + use serde::{Deserialize, Serialize}; +use zeroize::Zeroizing; + #[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct KeyCore {} +pub struct KeyCore { + pub key_material: Zeroizing, + #[serde(skip_serializing_if = "Option::is_none")] + pub label: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub public_key: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub algorithm: Option, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn key_round_trip() { + let k = KeyCore { + key_material: Zeroizing::new("-----BEGIN OPENSSH PRIVATE KEY-----\n...".into()), + label: Some("yubikey-backup".into()), + public_key: Some("ssh-ed25519 AAAAC3...".into()), + algorithm: Some("ed25519".into()), + }; + let json = serde_json::to_string(&k).unwrap(); + let parsed: KeyCore = serde_json::from_str(&json).unwrap(); + assert!(parsed.key_material.starts_with("-----BEGIN")); + assert_eq!(parsed.algorithm.as_deref(), Some("ed25519")); + } + + #[test] + fn empty_key_material_round_trips() { + let k = KeyCore::default(); + let json = serde_json::to_string(&k).unwrap(); + let parsed: KeyCore = serde_json::from_str(&json).unwrap(); + assert!(parsed.key_material.is_empty()); + } +}