From 3cf683609589e0816bed5e7441572569d1f22167 Mon Sep 17 00:00:00 2001 From: Bat Date: Fri, 4 May 2018 16:18:00 +0100 Subject: [PATCH] HTTP signature when sending activites --- Cargo.lock | 1 + Cargo.toml | 4 +++- src/activity_pub/actor.rs | 5 ++++ src/activity_pub/mod.rs | 1 + src/activity_pub/request.rs | 48 +++++++++++++++++++++++++++++++++++++ src/main.rs | 2 ++ 6 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/activity_pub/request.rs diff --git a/Cargo.lock b/Cargo.lock index 5d642fe9..4fdfe0d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -808,6 +808,7 @@ dependencies = [ "dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.25 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index f1ae7acc..1267f0ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,11 +3,12 @@ authors = ["Bat' "] name = "plume" version = "0.1.0" [dependencies] -base64 = "0.9.1" +base64 = "0.9" bcrypt = "0.2" dotenv = "*" heck = "0.3.0" hex = "0.3" +hyper = "*" lazy_static = "*" openssl = "0.10.6" reqwest = "0.8" @@ -29,3 +30,4 @@ version = "*" [dependencies.rocket_contrib] features = ["tera_templates", "json"] version = "*" +" diff --git a/src/activity_pub/actor.rs b/src/activity_pub/actor.rs index 45fb42fd..06c0fde6 100644 --- a/src/activity_pub/actor.rs +++ b/src/activity_pub/actor.rs @@ -5,6 +5,7 @@ use serde_json; use BASE_URL; use activity_pub::{activity_pub, ActivityPub, context, ap_url}; use activity_pub::activity::Activity; +use activity_pub::request; use activity_pub::sign::*; use models::instance::Instance; @@ -85,8 +86,12 @@ pub trait Actor: Sized { let mut act = act.serialize(); act["@context"] = context(); let signed = act.sign(sender, conn); + let res = Client::new() .post(&self.compute_inbox(conn)[..]) + .headers(request::headers()) + .header(request::signature(sender, request::headers, conn)) + .header(request::digest(signed.to_string())) .body(signed.to_string()) .send(); match res { diff --git a/src/activity_pub/mod.rs b/src/activity_pub/mod.rs index 2e68c021..928dddd1 100644 --- a/src/activity_pub/mod.rs +++ b/src/activity_pub/mod.rs @@ -8,6 +8,7 @@ pub mod actor; pub mod inbox; pub mod object; pub mod outbox; +pub mod request; pub mod sign; pub mod webfinger; diff --git a/src/activity_pub/request.rs b/src/activity_pub/request.rs new file mode 100644 index 00000000..08305373 --- /dev/null +++ b/src/activity_pub/request.rs @@ -0,0 +1,48 @@ +use base64; +use diesel::PgConnection; +use hex; +use openssl::hash::{Hasher, MessageDigest}; +use openssl::sha::sha256; +use reqwest::header::{Date, Headers, UserAgent}; +use std::time::SystemTime; + +use activity_pub::sign::Signer; + +const USER_AGENT: &'static str = "Plume/0.1.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 +} + +pub fn signature(signer: S, headers: Headers, conn: &PgConnection) -> 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 = hex::encode(sha256(&data[..])); + + Signature(format!( + "keyId=\"{key_id}\",algorithm=\"rsa-sha256\",headers=\"#{signed_headers}\",signature=\"#{signature}\"", + key_id = signer.get_key_id(conn), + 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()[..]); + let res = base64::encode(&hasher.finish().unwrap()); + Digest(format!("SHA-256={}", res)) +} diff --git a/src/main.rs b/src/main.rs index 107437f1..737a3fbd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,8 @@ extern crate chrono; extern crate heck; extern crate hex; #[macro_use] +extern crate hyper; +#[macro_use] extern crate diesel; extern crate dotenv; #[macro_use]