use base64; use openssl::hash::{Hasher, MessageDigest}; use reqwest::{ mime::Mime, header::{Accept, Date, Headers, UserAgent, qitem} }; use std::time::SystemTime; use activity_pub::ap_accept_header; use activity_pub::sign::Signer; const USER_AGENT: &'static str = "Plume/0.2.0"; header! { (Signature, "Signature") => [String] } header! { (Digest, "Digest") => [String] } pub fn headers() -> Headers { let mut headers = Headers::new(); headers.set(UserAgent::new(USER_AGENT)); headers.set(Date(SystemTime::now().into())); headers.set(Accept(ap_accept_header().into_iter().map(|h| qitem(h.parse::().expect("Invalid Content-Type"))).collect())); headers } pub fn signature(signer: &S, headers: Headers) -> Signature { let signed_string = headers.iter().map(|h| format!("{}: {}", h.name().to_lowercase(), h.value_string())).collect::>().join("\n"); let signed_headers = headers.iter().map(|h| h.name().to_string()).collect::>().join(" ").to_lowercase(); let data = signer.sign(signed_string); let sign = base64::encode(&data[..]); Signature(format!( "keyId=\"{key_id}\",algorithm=\"rsa-sha256\",headers=\"{signed_headers}\",signature=\"{signature}\"", key_id = signer.get_key_id(), signed_headers = signed_headers, signature = sign )) } pub fn digest(body: String) -> Digest { let mut hasher = Hasher::new(MessageDigest::sha256()).unwrap(); hasher.update(&body.into_bytes()[..]).unwrap(); let res = base64::encode(&hasher.finish().unwrap()); Digest(format!("SHA-256={}", res)) }