actix-web: add digest verification

This commit is contained in:
Aode (lion) 2021-11-19 17:55:13 -06:00
parent 36255bfbb4
commit 0db515714e
2 changed files with 44 additions and 8 deletions

View file

@ -8,7 +8,7 @@ edition = "2021"
[dependencies] [dependencies]
apub-core = { version = "0.1.0", path = "../apub-core/" } apub-core = { version = "0.1.0", path = "../apub-core/" }
actix-web = { version = "4.0.0-beta.11", default-features = false } actix-web = { version = "4.0.0-beta.11", default-features = false }
http-signature-normalization-actix = { version = "0.5.0-beta.12", default-features = false, features = ["server"] } http-signature-normalization-actix = { version = "0.5.0-beta.12", default-features = false, features = ["server", "digest"] }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
thiserror = "1" thiserror = "1"
url = { version = "2", features = ["serde"] } url = { version = "2", features = ["serde"] }

View file

@ -5,11 +5,16 @@ use actix_web::{
}; };
use apub_core::{ use apub_core::{
deref::{Dereference, Repo}, deref::{Dereference, Repo},
digest::Digest,
ingest::Ingest, ingest::Ingest,
signature::Verify, signature::Verify,
}; };
use http_signature_normalization_actix::prelude::{ use http_signature_normalization_actix::{
Algorithm, DeprecatedAlgorithm, SignatureVerified, SignatureVerify, VerifySignature, digest::DigestName,
prelude::{
Algorithm, DeprecatedAlgorithm, DigestPart, DigestVerify, SignatureVerified,
SignatureVerify, VerifyDigest, VerifySignature,
},
}; };
use std::{future::Future, marker::PhantomData, pin::Pin}; use std::{future::Future, marker::PhantomData, pin::Pin};
use url::Url; use url::Url;
@ -41,6 +46,7 @@ pub trait VerifierFactory<D: Dereference> {
type Error: ResponseError + From<VerifyError> + From<Self::VerifyError> + 'static; type Error: ResponseError + From<VerifyError> + From<Self::VerifyError> + 'static;
type VerifyError: Send + 'static; type VerifyError: Send + 'static;
type Verifier: for<'a> Verifier<'a, D, Error = Self::VerifyError> + 'static; type Verifier: for<'a> Verifier<'a, D, Error = Self::VerifyError> + 'static;
type Digest: Digest + Clone + Send;
fn verifier(&self) -> Self::Verifier; fn verifier(&self) -> Self::Verifier;
} }
@ -93,21 +99,24 @@ where
V: VerifierFactory<ObjectId<PublicKeyType>> + Clone + 'static, V: VerifierFactory<ObjectId<PublicKeyType>> + Clone + 'static,
{ {
move |service_config: &mut ServiceConfig| { move |service_config: &mut ServiceConfig| {
let verifier = VerifySignature::new( let signature = VerifySignature::new(
VerifyMiddleware::<V, ObjectId<PublicKeyType>>::new(verifier_factory), VerifyMiddleware::<V, ObjectId<PublicKeyType>>::new(verifier_factory),
config, config,
); );
let verifier = if require_signature { let digest = VerifyDigest::new(DigestWrapper(V::Digest::build()));
verifier
let (signature, digest) = if require_signature {
(signature, digest)
} else { } else {
verifier.optional() (signature.optional(), digest.optional())
}; };
service_config.service( service_config.service(
web::scope("") web::scope("")
.app_data(web::Data::new(ingest)) .app_data(web::Data::new(ingest))
.wrap(verifier) .wrap(digest)
.wrap(signature)
.route("", web::post().to(inbox_handler::<Activity, Metadata, I>)), .route("", web::post().to(inbox_handler::<Activity, Metadata, I>)),
); );
} }
@ -225,6 +234,33 @@ where
} }
} }
#[derive(Clone)]
struct DigestWrapper<D>(D);
impl<D> DigestName for DigestWrapper<D>
where
D: Digest,
{
const NAME: &'static str = D::NAME;
}
impl<D> DigestVerify for DigestWrapper<D>
where
D: Digest + Clone,
{
fn update(&mut self, part: &[u8]) {
self.0.update(part);
}
fn verify(&mut self, digests: &[DigestPart]) -> bool {
if let Some(part) = digests.iter().find(|part| part.algorithm == D::NAME) {
return self.0.clone().verify(&part.digest);
}
false
}
}
struct ServeInfo<R> { struct ServeInfo<R> {
local_host: String, local_host: String,
repo_factory: R, repo_factory: R,