feat(core): flesh out KeyCore
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,42 @@
|
|||||||
|
//! Key: arbitrary key material (Zeroizing), label, public key, algorithm.
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
pub struct KeyCore {}
|
pub struct KeyCore {
|
||||||
|
pub key_material: Zeroizing<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub label: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub public_key: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub algorithm: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user