jdx/mise · critical

signature does not match any trusted public key

Error message

signature does not match any trusted public key

What it means

verify_detached tried every parsed signature against every trusted public key (fast path for signatures with an issuer subpacket, then the full loop for the rest) and none verified. This means the artifact's signature does not cryptographically match any of the configured trusted keys.

Source

Thrown at src/gpg.rs:63

        bail!("no signature found to verify");
    }

    // Fast path: only try keys whose id/fingerprint matches the signature's issuer, so the signed
    // content is hashed at most once in the common case.
    for sig in &signatures {
        if verify_against_keys(sig, &keys, &open_data, true)? {
            return Ok(());
        }
    }
    // Fallback: try every trusted key, but only for signatures that carried no usable issuer
    // hint. A signature that named an issuer we don't trust is genuinely unverifiable, so skip it
    // rather than re-hashing the (potentially large) content against every key.
    for sig in signatures.iter().filter(|sig| !has_issuer(&sig.signature)) {
        if verify_against_keys(sig, &keys, &open_data, false)? {
            return Ok(());
        }
    }
    bail!("signature does not match any trusted public key");
}

fn verify_against_keys<R, F>(
    sig: &DetachedSignature,
    keys: &[SignedPublicKey],
    open_data: &F,
    require_issuer_match: bool,
) -> Result<bool>
where
    R: Read,
    F: Fn() -> Result<R>,
{
    for key in keys {
        if (!require_issuer_match
            || issuer_matches(&sig.signature, &key.fingerprint(), &key.legacy_key_id()))
            && try_verify(sig, key, open_data)?
        {
            return Ok(true);

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Update the trusted public keys to the project's current official signing keys (fetch new keys from the upstream release/keyserver)
  2. Re-download both the archive and its signature from the official source to rule out a corrupted or mismatched pair
  3. Confirm the archive and signature come from the exact same release/version
  4. If the artifact is trusted and genuinely signed by a new key, add that key to the trusted key list; if not, treat it as tampered
  5. Clear any cached partial downloads/mirrors and retry

Example fix

// before
let keys = read("node-v16-keys.asc")?; // stale: new release signed with rotated key
verify_node(&archive, sig, keys)?;
// after
let keys = fetch_current_keys("node")?; // includes rotated signing key
verify_node(&archive, sig, keys)?;
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure keys include the current upstream signing key fingerprints
let fingerprints: Vec<_> = parse_public_keys(&keys)?.iter().map(|k| hex::encode(k.key_id())).collect();
eprintln!("trusted keys: {:?}", fingerprints);

Try / catch

match verify_node(&archive, sig, keys) {
    Ok(()) => println!("signature verified"),
    Err(e) if e.to_string().contains("does not match any trusted public key") => {
        eprintln!("artifact untrusted: refresh official keys or suspect tampering");
        std::process::exit(1); // fail closed, never proceed unverified
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: verify_node/verify_swift/verify_swift_bytes called with a signature signed by a key not in public_keys_asc, a corrupted/tampered artifact, or mismatched signature/archive pairing.

Common situations: Upstream rotated signing keys (e.g. new Node/Swift release signed with a fresh key) while local trusted key list is stale; MITM or corrupted mirror served a tampered archive; downloaded the .sig from a different release version than the archive; revoked or outdated keys in config.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/99f7ced811fc7a0c. Report an issue: GitHub.