rustdesk/rustdesk-server · error

Key pair is INVALID

Error message

Key pair is INVALID

What it means

After both keys construct successfully, validate_keypair signs a fixed test string and verifies it; if `sign::verify` returns Err, the keys do not form a usable Ed25519 signing pair and the code bails with "Key pair is INVALID". Both inputs are individually well-formed but the pair fails the sign/verify round-trip.

Solutions

  1. Use the secret key and public key from the SAME generated keypair; regenerate the pair together if unsure.
  2. Compare fingerprints of both keys to confirm they belong together before running validation.
  3. Replace the deployed key pair on clients with the freshly generated pair after regenerating.

Example fix

// before: mixed pair
hbbs --doctor -k '<sk from pair A>' -K '<pk from pair B>'
// after: matched pair
hbbs --doctor -k '<sk from pair A>' -K '<pk from pair A>'
Defensive patterns

Strategy: validation

Validate before calling

// confirm the pair matches before calling the validator
let sig = sign::sign(b"probe", &secret_key);
assert!(sign::verify(&sig, &public_key).is_ok(), "secret/public keys do not match");

Try / catch

match validate_keypair(&pk, &sk) {
    Err(e) if e.to_string().contains("INVALID") => eprintln!("Keys are not a matched pair - regenerate"),
    Err(e) => eprintln!("keypair check failed: {e}"),
    Ok(()) => println!("keypair OK"),
}

Prevention

When it happens

Trigger: Signing with secret key A and verifying with an unrelated public key B (mismatched pair), or a corrupted key that decodes to the right length but is cryptographically unusable.

Common situations: Mixing id_ed25519 and id_ed25519.pub from different generations; keys regenerated on the server while old ones are checked; wrong file passed from a directory holding several keypairs.

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 rustdesk/rustdesk-server@a7736be5e4 (2026-09-09). Data as JSON: /api/errors/7096bf43fce8235d. Report an issue: GitHub.

Appendix: source

Thrown at src/utils.rs:64

    let secret_key = secret_key.unwrap();

    let pk1 = base64::decode(pk);
    if pk1.is_err() {
        bail!("Invalid public key");
    }
    let pk1 = pk1.unwrap();

    let public_key = sign::PublicKey::from_slice(pk1.as_slice());
    if public_key.is_none() {
        bail!("Invalid Public key");
    }
    let public_key = public_key.unwrap();

    let random_data_to_test = b"This is meh.";
    let signed_data = sign::sign(random_data_to_test, &secret_key);
    let verified_data = sign::verify(&signed_data, &public_key);
    if verified_data.is_err() {
        bail!("Key pair is INVALID");
    }
    let verified_data = verified_data.unwrap();

    if random_data_to_test != &verified_data[..] {
        bail!("Key pair is INVALID");
    }

    Ok(())
}

fn doctor_tcp(address: std::net::IpAddr, port: &str, desc: &str) {
    let start = std::time::Instant::now();
    let conn = format!("{address}:{port}");
    if let Ok(_stream) = TcpStream::connect(conn.as_str()) {
        let elapsed = std::time::Instant::now().duration_since(start);
        println!(
            "TCP Port {} ({}): OK in {} ms",
            port,

View on GitHub (pinned to a7736be5e4)