The main steps involved in Digest authentication are as follows:
Lots of little nuances: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization#digest
Quite untested:
use ring::digest; fn calculate_digest(username: &str, realm: &str, password: &str, method: &str, uri: &str, nonce: &str, cnonce: &str) -> String { let ha1 = format!("{}:{}:{}", username, realm, password); let ha1_digest = digest::digest(&digest::MD5, ha1.as_bytes()); let ha2 = format!("{}:{}", method, uri); let ha2_digest = digest::digest(&digest::MD5, ha2.as_bytes()); let response = format!("{:x}:{nonce}:{nc}:{cnonce}:{qop}:{ha2}", ha1_digest, nonce, "00000001", cnonce, "auth", ha2_digest); let response_digest = digest::digest(&digest::MD5, response.as_bytes()); format!("{:x}", response_digest) } fn main() { let username = "alice"; let realm = "realm"; let password = "password"; let method = "GET"; let uri = "/path"; let nonce = "1234567890"; let cnonce = "0987654321"; let digest = calculate_digest(username, realm, password, method, uri, nonce, cnonce); println!("Digest: {}", digest); }The main pain point is the extra request to get the
WWW-Authenticate
header with the realm and stuff. I wonder if this can be done in a separate step or something (e.g. have the value ready before sync).