dyolo-kya 1.0.0

Know Your Agent (KYA): cryptographic chain-of-custody for recursive AI delegation with provable scope narrowing
use ed25519_dalek::{Signature, Signer, SigningKey, VerifyingKey};
use rand::rngs::OsRng;
use zeroize::ZeroizeOnDrop;

/// A cryptographic identity for any participant — human principal or AI agent.
///
/// Key material is zeroized from memory on drop. In production systems, wrap
/// this in hardware-backed storage such as an HSM, TPM, or a secrets manager
/// and load from there at runtime rather than persisting raw bytes.
#[derive(ZeroizeOnDrop)]
pub struct DyoloIdentity {
    signing_key: SigningKey,
}

impl DyoloIdentity {
    /// Generate a new identity using the OS entropy source.
    pub fn generate() -> Self {
        Self { signing_key: SigningKey::generate(&mut OsRng) }
    }

    /// Restore an identity from a 32-byte signing key.
    ///
    /// # Security
    ///
    /// The caller is responsible for sourcing these bytes from secure storage.
    /// Zero the input bytes after calling this function.
    pub fn from_signing_bytes(bytes: &[u8; 32]) -> Self {
        Self { signing_key: SigningKey::from_bytes(bytes) }
    }

    /// Export the raw signing key bytes.
    ///
    /// # Security
    ///
    /// Handle the returned bytes as a secret. Zeroize them after use.
    pub fn to_signing_bytes(&self) -> [u8; 32] {
        self.signing_key.to_bytes()
    }

    /// The public verification key for this identity.
    pub fn verifying_key(&self) -> VerifyingKey {
        self.signing_key.verifying_key()
    }

    pub(crate) fn sign(&self, message: &[u8]) -> Signature {
        self.signing_key.sign(message)
    }
}

impl std::fmt::Debug for DyoloIdentity {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let vk = self.verifying_key();
        let bytes = vk.as_bytes();
        // Show first 8 bytes as a fingerprint prefix — never the full signing key.
        write!(
            f,
            "DyoloIdentity(vk:{:02x}{:02x}{:02x}{:02x}…)",
            bytes[0], bytes[1], bytes[2], bytes[3]
        )
    }
}