Crates.io | http-signature-normalization-actix |
lib.rs | http-signature-normalization-actix |
version | 0.11.1 |
source | src |
created_at | 2019-09-21 16:38:03.225553 |
updated_at | 2024-04-15 01:26:20.668309 |
description | An HTTP Signatures library that leaves the signing to you |
homepage | |
repository | https://git.asonix.dog/Aardwolf/http-signature-normalization |
max_upload_size | |
id | 166564 |
size | 157,195 |
An HTTP Signatures library that leaves the signing to you
Http Signature Normalization is a minimal-dependency crate for producing HTTP Signatures with user-provided signing and verification. The API is simple; there's a series of steps for creation and verification with types that ensure reasonable usage.
This crate provides extensions the ClientRequest type from Actix Web, and provides middlewares for verifying HTTP Signatures, and optionally, Digest headers
actix-rt = "2.6.0"
actix-web = "4.0.0"
thiserror = "0.1"
http-signature-normalization-actix = { version = "0.8.0", default-features = false, features = ["sha-2"] }
sha2 = "0.9"
async fn request(config: Config) -> Result<(), Box<dyn std::error::Error>> {
let digest = Sha256::new();
let mut response = Client::default()
.post("http://127.0.0.1:8010/")
.append_header(("User-Agent", "Actix Web"))
.append_header(("Accept", "text/plain"))
.insert_header(actix_web::http::header::Date(SystemTime::now().into()))
.signature_with_digest(config, "my-key-id", digest, "Hewwo-owo", |s| {
info!("Signing String\n{}", s);
Ok(base64::encode(s)) as Result<_, MyError>
})
.await?
.send()
.await
.map_err(|e| {
error!("Error, {}", e);
MyError::SendRequest
})?;
let body = response.body().await.map_err(|e| {
error!("Error, {}", e);
MyError::Body
})?;
info!("{:?}", body);
Ok(())
}
#[derive(Clone, Debug)]
struct MyVerify;
impl SignatureVerify for MyVerify {
type Error = MyError;
type Future = Ready<Result<bool, Self::Error>>;
fn signature_verify(
&mut self,
algorithm: Option<Algorithm>,
key_id: String,
signature: String,
signing_string: String,
) -> Self::Future {
match algorithm {
Some(Algorithm::Hs2019) => (),
_ => return ready(Err(MyError::Algorithm)),
};
if key_id != "my-key-id" {
return ready(Err(MyError::Key));
}
let decoded = match base64::decode(&signature) {
Ok(decoded) => decoded,
Err(_) => return ready(Err(MyError::Decode)),
};
info!("Signing String\n{}", signing_string);
ready(Ok(decoded == signing_string.as_bytes()))
}
}
async fn index(
_: DigestVerified,
sig_verified: SignatureVerified,
req: HttpRequest,
_body: web::Bytes,
) -> &'static str {
info!("Verified request for {}", sig_verified.key_id());
info!("{:?}", req);
"Eyyyyup"
}
#[actix_rt::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
let subscriber = tracing_subscriber::Registry::default()
.with(env_filter)
.with(ErrorLayer::default())
.with(tracing_subscriber::fmt::layer());
tracing::subscriber::set_global_default(subscriber)?;
let config = Config::default().require_header("accept").require_digest();
HttpServer::new(move || {
App::new()
.wrap(VerifyDigest::new(Sha256::new()).optional())
.wrap(VerifySignature::new(MyVerify, config.clone()))
.wrap(TracingLogger::default())
.route("/", web::post().to(index))
})
.bind("127.0.0.1:8010")?
.run()
.await?;
Ok(())
}
#[derive(Debug, thiserror::Error)]
enum MyError {
#[error("Failed to verify, {0}")]
Verify(#[from] PrepareVerifyError),
#[error("Unsupported algorithm")]
Algorithm,
#[error("Couldn't decode signature")]
Decode,
#[error("Invalid key")]
Key,
}
impl ResponseError for MyError {
fn status_code(&self) -> StatusCode {
StatusCode::BAD_REQUEST
}
fn error_response(&self) -> HttpResponse {
HttpResponse::BadRequest().finish()
}
}
Feel free to open issues for anything you find an issue with. Please note that any contributed code will be licensed under the AGPLv3.
Copyright © 2022 Riley Trautman
HTTP Signature Normalization Actix is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
HTTP Signature Normalization Actix is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. This file is part of HTTP Signature Normalization Actix.
You should have received a copy of the GNU General Public License along with HTTP Signature Normalization Actix. If not, see http://www.gnu.org/licenses/.