zeroclaw-labs/zeroclaw · error · anyhow::Error
Unsupported COSE key format (expected uncompressed P-256, go
Error message
Unsupported COSE key format (expected uncompressed P-256, got {} bytes starting with 0x{:02x}) What it means
extract_p256_from_cose accepts only a 65-byte uncompressed EC2 P-256 point starting with 0x04 (webauthn.rs:661-671); anything else — compressed points, P-384/Ed25519/RSA COSE keys, or short buffers — is rejected. The message includes length and first byte so you can identify the actual key type.
Source
Thrown at crates/zeroclaw-runtime/src/security/webauthn.rs:669
)
}
/// Simplified attestation object for the enrollment UI.
#[derive(Deserialize)]
struct AttestationObject {
/// Base64url-encoded public key (uncompressed P-256 or DER SPKI).
public_key: String,
/// Initial sign counter.
sign_count: Option<u32>,
}
fn extract_p256_from_cose(cose: &[u8]) -> Result<Vec<u8>> {
// If it starts with 0x04 and is 65 bytes, it's already uncompressed P-256
if cose.len() >= 65 && cose[0] == 0x04 {
return Ok(cose[..65].to_vec());
}
anyhow::bail!(
"Unsupported COSE key format (expected uncompressed P-256, got {} bytes starting with 0x{:02x})",
cose.len(),
cose.first().copied().unwrap_or(0)
)
}
// ── Signature verification ──────────────────────────────────────
fn verify_es256_signature(public_key: &[u8], message: &[u8], sig: &[u8]) -> Result<()> {
// ring's UnparsedPublicKey expects the raw uncompressed point for P-256
// (not wrapped in SPKI). If we have SPKI, we'd need to extract the point.
// For our use case the stored key is always the raw uncompressed point.
let pk = signature::UnparsedPublicKey::new(&signature::ECDSA_P256_SHA256_ASN1, public_key);
pk.verify(message, sig).map_err(|_| {
::zeroclaw_log::record!(
WARN,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Reject)View on GitHub (pinned to 88bb9c8533)
Solutions
- Request only ES256 (alg -7, EC2, P-256) in your WebAuthn creation options
- Read the reported length and first byte: 33 bytes starting 0x02/0x03 means compressed; 97 bytes starting 0x04 suggests P-384
- If you must support other key types, extend the extractor — current code intentionally supports only uncompressed P-256
Example fix
// before: broad algorithm set
const creationOptions = {
pubKeyCredParams: [
{ type: "public-key", alg: -7 },
{ type: "public-key", alg: -8 }, // EdDSA
{ type: "public-key", alg: -257 }, // RS256
],
};
// after: only ES256 / uncompressed P-256, which the server can extract
const creationOptions = {
pubKeyCredParams: [{ type: "public-key", alg: -7 }],
}; Defensive patterns
Strategy: validation
Validate before calling
// Browser side: restrict creation options so non-ES256 credentials are never made
const creationOptions = {
pubKeyCredParams: [{ type: "public-key", alg: -7 }], // ES256 only
authenticatorSelection: { userVerification: "preferred" },
}; Try / catch
Catch around finish_registration, read the reported byte length/first byte to classify the key type, and tell the user to enroll a credential with a standard passkey (ES256); log the key shape for support triage.
Prevention
- Request only alg -7 (ES256) in navigator.credentials.create options
- Reject non-ES256 credentials at enrollment with a clear message
- Track which authenticator models emit unsupported COSE keys and steer users away from them
When it happens
Trigger: finish_registration with an authenticator that used ES384 or EdDSA, or a COSE key serialized as separate x/y coordinates instead of the 0x04||x||y form.
Common situations: The WebAuthn creation options allow broader algorithms than ES256 (alg -7); some platform authenticators default to other curves; a custom client builds the COSE structure by hand.
Related errors
- No credentials found for user '{user_id}'
- Unable to extract public key from attestation object ({} byt
- Expected type 'webauthn.create', got '{cd_type}'
- Challenge mismatch in registration response
- Origin mismatch: expected '{}', got '{cd_origin}'
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/1c3fa8687ff45a76.
Report an issue: GitHub.