{"record":{"id":"f25ec4fc069274d9","repo":"sigoden/dufs","slug":"invalid-nonce","errorCode":null,"errorMessage":"invalid nonce","messagePattern":"invalid nonce","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/auth.rs","lineNumber":527,"sourceCode":"        }\n        None\n    } else {\n        None\n    }\n}\n\nfn derive_secret_key(user: &str, pass: &str) -> SigningKey {\n    let mut hasher = Sha256::new();\n    hasher.update(format!(\"{user}:{pass}\").as_bytes());\n    let hash = hasher.finalize();\n    SigningKey::from_bytes(&hash.into())\n}\n\n/// Check if a nonce is still valid.\n/// Return an error if it was never valid\nfn validate_nonce(nonce: &[u8]) -> Result<bool> {\n    if nonce.len() != 34 {\n        bail!(\"invalid nonce\");\n    }\n    //parse hex\n    if let Ok(n) = std::str::from_utf8(nonce) {\n        //get time\n        if let Ok(secs_nonce) = u32::from_str_radix(&n[..8], 16) {\n            //check time\n            let now = unix_now();\n            let secs_now = now.as_secs() as u32;\n\n            if let Some(dur) = secs_now.checked_sub(secs_nonce) {\n                //check hash\n                let mut h = NONCESTARTHASH.clone();\n                h.consume(secs_nonce.to_be_bytes());\n                let h = format!(\"{:x}\", h.finalize());\n                if h[..26] == n[8..34] {\n                    return Ok(dur < DIGEST_AUTH_TIMEOUT);\n                }\n            }","sourceCodeStart":509,"sourceCodeEnd":545,"githubUrl":"https://github.com/sigoden/dufs/blob/fe7fd564f80dfbac361c8e0589c3845638149d38/src/auth.rs#L509-L545","documentation":"HTTP Digest auth nonces must be exactly 34 bytes: 8 hex chars encoding a Unix-seconds timestamp followed by 26 hex chars of digest. `validate_nonce` rejects any nonce with the wrong length as 'invalid nonce' before further parsing.","triggerScenarios":"A client sends a WWW-Authenticate Digest response whose nonce is not 34 bytes long — e.g. empty, server-generated nonce from a different implementation, or truncated.","commonSituations":"Custom HTTP clients hand-building Digest headers; replaying nonces from another server; corrupted or cut-off Authorization headers.","solutions":["Use the nonce exactly as issued by this server in its WWW-Authenticate challenge.","Check the client's Digest implementation generates/passes the full nonce string.","Inspect the raw Authorization header for truncation or whitespace mangling.","Fall back to Basic auth if the client cannot do Digest correctly."],"exampleFix":"// before\nAuthorization: Digest username=\"u\", nonce=\"abc123\"  (too short)\n// after\nAuthorization: Digest username=\"u\", nonce=\"<34-char nonce from server challenge>\"","handlingStrategy":"validation","validationCode":"fn nonce_wellformed(n: &str) -> bool { n.len() == 34 && n.chars().all(|c| c.is_ascii_hexdigit()) }\nif !nonce_wellformed(nonce) { request_new_challenge(); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Echo the server's nonce verbatim, no trimming/altering","Use a maintained Digest auth library instead of hand-rolling","Log the raw Authorization header when debugging","Never reuse nonces from a different server"],"tags":["rust","authentication","http-digest","nonce"],"backgroundTag":"invalid-argument-format","analyzedSha":"fe7fd564f80dfbac361c8e0589c3845638149d38","analyzedAt":"2026-09-09T13:01:22.843Z","contentChangedAt":"2026-09-09T13:01:22.843Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}