From e7e958478388c0c8c01db684bdcee3a7321c500a Mon Sep 17 00:00:00 2001 From: alemi Date: Fri, 31 May 2024 21:31:09 +0200 Subject: [PATCH] chore(httpsign): moved httpsign into standalone crate --- upub/core/src/server/mod.rs | 1 - utils/httpsign/Cargo.toml | 26 +++++++++++++++++ utils/httpsign/README.md | 0 .../httpsign.rs => utils/httpsign/lib.rs | 28 ++++++++++++++++--- 4 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 utils/httpsign/Cargo.toml create mode 100644 utils/httpsign/README.md rename upub/core/src/server/httpsign.rs => utils/httpsign/lib.rs (85%) diff --git a/upub/core/src/server/mod.rs b/upub/core/src/server/mod.rs index 4df3856..8fcefff 100644 --- a/upub/core/src/server/mod.rs +++ b/upub/core/src/server/mod.rs @@ -7,7 +7,6 @@ pub mod inbox; pub mod init; pub mod outbox; pub mod auth; -pub mod httpsign; pub mod normalizer; pub mod side_effects; diff --git a/utils/httpsign/Cargo.toml b/utils/httpsign/Cargo.toml new file mode 100644 index 0000000..dddd9f7 --- /dev/null +++ b/utils/httpsign/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "httpsign" +version = "0.1.0" +edition = "2021" +authors = [ "alemi " ] +description = "fediverse-friendly implementation of http signaures in rust" +license = "MIT" +#keywords = ["html", "markdown", "parser"] +repository = "https://git.alemi.dev/upub.git" +readme = "README.md" + +[lib] +path = "lib.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +thiserror = "1" +tracing = "0.1" +base64 = "0.22" +openssl = "0.10" # TODO handle pubkeys with a smaller crate +axum = { version = "0.7", optional = true } + +[features] +default = [] +axum = ["dep:axum"] diff --git a/utils/httpsign/README.md b/utils/httpsign/README.md new file mode 100644 index 0000000..e69de29 diff --git a/upub/core/src/server/httpsign.rs b/utils/httpsign/lib.rs similarity index 85% rename from upub/core/src/server/httpsign.rs rename to utils/httpsign/lib.rs index 47a4678..849849a 100644 --- a/upub/core/src/server/httpsign.rs +++ b/utils/httpsign/lib.rs @@ -1,9 +1,25 @@ use std::collections::BTreeMap; -use axum::http::request::Parts; use base64::Engine; use openssl::{hash::MessageDigest, pkey::PKey, sign::Verifier}; +#[derive(Debug, thiserror::Error)] +pub enum HttpSignatureError { + #[error("openssl error: {0:?}")] + OpenSSL(#[from] openssl::error::ErrorStack), + + #[error("invalid UTF8 in key: {0:?}")] + UTF8(#[from] std::str::Utf8Error), + + #[error("os I/O error: {0}")] + IO(#[from] std::io::Error), + + #[error("invalid base64: {0}")] + Base64(#[from] base64::DecodeError), +} + +type Result = std::result::Result; + #[derive(Debug, Clone, Default)] pub struct HttpSignature { pub key_id: String, @@ -60,7 +76,8 @@ impl HttpSignature { self } - pub fn build_from_parts(&mut self, parts: &Parts) -> &mut Self { + #[cfg(feature = "axum")] + pub fn build_from_parts(&mut self, parts: &axum::http::request::Parts) -> &mut Self { let mut out = Vec::new(); for header in self.headers.iter() { match header.as_str() { @@ -82,14 +99,14 @@ impl HttpSignature { self } - pub fn verify(&self, key: &str) -> crate::Result { + pub fn verify(&self, key: &str) -> Result { let pubkey = PKey::public_key_from_pem(key.as_bytes())?; let mut verifier = Verifier::new(MessageDigest::sha256(), &pubkey)?; let signature = base64::prelude::BASE64_STANDARD.decode(&self.signature)?; Ok(verifier.verify_oneshot(&signature, self.control.as_bytes())?) } - pub fn sign(&mut self, key: &str) -> crate::Result<&str> { + pub fn sign(&mut self, key: &str) -> Result<&str> { let privkey = PKey::private_key_from_pem(key.as_bytes())?; let mut signer = openssl::sign::Signer::new(MessageDigest::sha256(), &privkey)?; signer.update(self.control.as_bytes())?; @@ -100,6 +117,9 @@ impl HttpSignature { #[cfg(test)] mod test { + + // TODO more tests!!! + #[test] fn http_signature_signs_and_verifies() { let key = openssl::rsa::Rsa::generate(2048).unwrap();