{"record":{"id":"ec4da2b52940ad23","repo":"rustdesk/rustdesk-server","slug":"invalid-secret-key","errorCode":null,"errorMessage":"Invalid secret key","messagePattern":"Invalid secret key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/utils.rs","lineNumber":38,"sourceCode":"}\n\nfn error_then_help(msg: &str) {\n    println!(\"ERROR: {msg}\\n\");\n    print_help();\n}\n\nfn gen_keypair() {\n    let (pk, sk) = sign::gen_keypair();\n    let public_key = base64::encode(pk);\n    let secret_key = base64::encode(sk);\n    println!(\"Public Key:  {public_key}\");\n    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\");","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/rustdesk/rustdesk-server/blob/a7736be5e40f85bfc141120dce587e836e5d4b80/src/utils.rs#L20-L56","documentation":"validate_keypair (src/utils.rs, called from the `--doctor`/keypair validation path in main) first base64-decodes the supplied secret key; if `base64::decode(sk)` fails, it bails with \"Invalid secret key\". This means the -k/--key argument is not valid base64 at all, before any cryptographic check happens.","triggerScenarios":"Passing a secret key string to the keypair validator that contains characters outside the base64 alphabet, has wrong padding, or is empty/whitespace so base64::decode returns Err.","commonSituations":"Copy-paste truncation or extra whitespace/newlines in the key; confusing the base64 public key with the raw secret key; shell quoting mangling '+' or '/' characters; editing key files by hand.","solutions":["Re-copy the secret key exactly as printed by the key-generation step ('Secret Key: ...'), with no truncation or whitespace.","Quote the argument in the shell (single quotes) so '+' and '/' are not mangled.","Verify the string decodes: `echo '<sk>' | base64 -d > /dev/null` must succeed.","Regenerate the keypair with the built-in key generation if the original key file is lost."],"exampleFix":"// before\nhbbs --doctor -k 0Sfx!invalid\n// after (single-quoted, full base64 string)\nhbbs --doctor -k '0SfxB0b+BASE64SECRETKEY=='","handlingStrategy":"validation","validationCode":"fn is_base64(s: &str) -> bool { base64::decode(s.trim()).is_ok() }\n// pre-check: assert!(is_base64(&sk), \"secret key must be valid base64\");","typeGuard":"fn valid_sk_base64(s: &str) -> Option<Vec<u8>> { base64::decode(s.trim()).ok().filter(|b| b.len() == 64) }","tryCatchPattern":"match validate_keypair(&pk, &sk) {\n    Err(e) if e.to_string().contains(\"secret key\") => eprintln!(\"Re-copy the secret key from key-gen output\"),\n    Err(e) => eprintln!(\"keypair check failed: {e}\"),\n    Ok(()) => println!(\"keypair OK\"),\n}","preventionTips":["Copy keys programmatically (files/clipboard tools), never retyped.","Single-quote key arguments in shells to protect +, /, =.","Strip whitespace/newlines before validating."],"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"}