{"record":{"id":"b2cfb52640e9e610","repo":"zeroclaw-labs/zeroclaw","slug":"hmac-accepts-any-key-length-b2cfb5","errorCode":null,"errorMessage":"HMAC accepts any key length","messagePattern":"HMAC accepts any key length","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"info","filePath":"crates/zeroclaw-runtime/src/rpc/tui_identity.rs","lineNumber":99,"sourceCode":"\n    /// Generate a TUI ID that is not currently in the registry.\n    pub fn generate_unique_tui_id(&self) -> String {\n        let connected = self.connected.lock().unwrap_or_else(|e| e.into_inner());\n        loop {\n            let id = Self::generate_tui_id();\n            if !connected.contains_key(&id) {\n                return id;\n            }\n        }\n    }\n\n    // ── HMAC signing ─────────────────────────────────────────────\n\n    /// Sign a TUI ID with HMAC-SHA256. Returns `None` if signing is\n    /// disabled.\n    pub fn sign(&self, tui_id: &str) -> Option<String> {\n        let key = self.signing_key.as_ref()?;\n        let mut mac = HmacSha256::new_from_slice(key).expect(\"HMAC accepts any key length\");\n        mac.update(tui_id.as_bytes());\n        Some(hex::encode(mac.finalize().into_bytes()))\n    }\n\n    /// Verify a TUI ID + signature. Returns `true` if:\n    /// - Signing is disabled (trust all), OR\n    /// - The signature is valid.\n    pub fn verify(&self, tui_id: &str, sig: &str) -> bool {\n        let Some(ref key) = self.signing_key else {\n            return true;\n        };\n        let Ok(sig_bytes) = hex::decode(sig) else {\n            return false;\n        };\n        let mut mac = HmacSha256::new_from_slice(key).expect(\"HMAC accepts any key length\");\n        mac.update(tui_id.as_bytes());\n        mac.verify_slice(&sig_bytes).is_ok()\n    }","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/rpc/tui_identity.rs#L81-L117","documentation":"TuiIdentityRegistry::sign() signs a TUI id with HMAC-SHA256 when a signing key is configured. new_from_slice() is expected to succeed with \"HMAC accepts any key length\"; HMAC imposes no key-length restriction, so this is a static invariant and the expect cannot realistically fire.","triggerScenarios":"Calling sign() while TUI-id signing is enabled (signing_key is Some). No key material can make new_from_slice fail; only a refactor that bypasses HMAC's key contract could trigger it.","commonSituations":"None for users. Maintainers touching the signing_key type (e.g. changing it from Vec<u8>) should re-check the invariant.","solutions":["No action needed at runtime; if seen, inspect local modifications to TuiIdentityRegistry key handling.","Keep the configured signing key a non-empty secret as good practice.","Add a roundtrip unit test (sign_verify_roundtrip exists) when modifying this code."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// At config load, reject empty signing keys before they reach the registry:\nif let Some(key) = &config.tui_signing_key {\n    anyhow::ensure!(!key.is_empty(), \"tui signing key must be a non-empty secret\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Configure a non-empty, high-entropy TUI signing key.","Note sign() returns None when signing is disabled; no panic path exists for callers.","Re-run sign_verify_roundtrip tests when modifying TuiIdentityRegistry."],"tags":["rust","crypto","hmac","tui","invariant"],"backgroundTag":"hmac-key-length-invalid","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}