{"record":{"id":"44c7a9a23fe0cb95","repo":"rustdesk/rustdesk-server","slug":"invalid-public-key","errorCode":null,"errorMessage":"Invalid public key","messagePattern":"Invalid public key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/utils.rs","lineNumber":50,"sourceCode":"    println!(\"Secret Key:  {secret_key}\");\n}\n\nfn validate_keypair(pk: &str, sk: &str) -> ResultType<()> {\n    let sk1 = base64::decode(sk);\n    if sk1.is_err() {\n        bail!(\"Invalid secret key\");\n    }\n    let sk1 = sk1.unwrap();\n\n    let secret_key = sign::SecretKey::from_slice(sk1.as_slice());\n    if secret_key.is_none() {\n        bail!(\"Invalid Secret key\");\n    }\n    let secret_key = secret_key.unwrap();\n\n    let pk1 = base64::decode(pk);\n    if pk1.is_err() {\n        bail!(\"Invalid public key\");\n    }\n    let pk1 = pk1.unwrap();\n\n    let public_key = sign::PublicKey::from_slice(pk1.as_slice());\n    if public_key.is_none() {\n        bail!(\"Invalid Public key\");\n    }\n    let public_key = public_key.unwrap();\n\n    let random_data_to_test = b\"This is meh.\";\n    let signed_data = sign::sign(random_data_to_test, &secret_key);\n    let verified_data = sign::verify(&signed_data, &public_key);\n    if verified_data.is_err() {\n        bail!(\"Key pair is INVALID\");\n    }\n    let verified_data = verified_data.unwrap();\n\n    if random_data_to_test != &verified_data[..] {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/rustdesk/rustdesk-server/blob/a7736be5e40f85bfc141120dce587e836e5d4b80/src/utils.rs#L32-L68","documentation":"validate_keypair base64-decodes the supplied public key; if `base64::decode(pk)` returns Err, it bails with \"Invalid public key\". As with the secret-key check, this fires before any crypto: the -p/public-key argument is not valid base64.","triggerScenarios":"Passing a public key argument containing invalid base64 characters, bad padding, whitespace/newlines, or an empty string so base64::decode fails.","commonSituations":"Copy-paste errors from the id_ed25519.pub output; shell interpolation inserting extra characters; confusing the server's public key file with an HTML/PEM wrapper around it.","solutions":["Re-copy the public key exactly as printed by the key generator (single line of base64).","Single-quote the argument in the shell to protect '+', '/' and '=' characters.","Verify decodability: `echo '<pk>' | base64 -d > /dev/null` must succeed.","If the .pub file contains extra headers/wrappers, extract only the base64 payload."],"exampleFix":"// before (newline-broken paste)\n-K 'abcCdef\n+ghi='\n// after (single-quoted, one line)\n-K 'abcCdef+ghi='","handlingStrategy":"validation","validationCode":"fn is_base64(s: &str) -> bool { base64::decode(s.trim()).is_ok() }\n// pre-check: assert!(is_base64(&pk), \"public key must be valid base64\");","typeGuard":"fn valid_pk_base64(s: &str) -> Option<Vec<u8>> { base64::decode(s.trim()).ok().filter(|b| b.len() == 32) }","tryCatchPattern":"match validate_keypair(&pk, &sk) {\n    Err(e) if e.to_string().contains(\"public key\") => eprintln!(\"Public key must be one line of base64\"),\n    Err(e) => eprintln!(\"keypair check failed: {e}\"),\n    Ok(()) => println!(\"keypair OK\"),\n}","preventionTips":["Extract only the base64 payload if the .pub file has wrappers.","Strip trailing newlines when reading keys from files (e.g. tr -d '\\n').","Single-quote key arguments in the shell."],"tags":["base64","key-validation","cli","cryptography"],"backgroundTag":"invalid-argument-format","analyzedSha":"a7736be5e40f85bfc141120dce587e836e5d4b80","analyzedAt":"2026-09-09T21:56:29.933Z","contentChangedAt":"2026-09-09T21:56:29.933Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}