2019-09-11 23:06:36 +00:00
|
|
|
use actix::System;
|
2019-09-13 22:55:51 +00:00
|
|
|
use actix_web::{web, App, HttpResponse, HttpServer, ResponseError};
|
2019-09-13 01:29:24 +00:00
|
|
|
use failure::Fail;
|
2019-09-11 23:06:36 +00:00
|
|
|
use http_signature_normalization_actix::{prelude::*, verify::Algorithm};
|
2019-09-13 01:12:35 +00:00
|
|
|
use sha2::{Digest, Sha256};
|
2019-09-11 23:06:36 +00:00
|
|
|
|
2019-09-13 22:55:51 +00:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
struct MyVerify;
|
2019-09-11 23:06:36 +00:00
|
|
|
|
2019-09-13 22:55:51 +00:00
|
|
|
impl SignatureVerify for MyVerify {
|
|
|
|
type Error = MyError;
|
|
|
|
type Future = Result<bool, Self::Error>;
|
|
|
|
|
|
|
|
fn signature_verify(
|
|
|
|
&mut self,
|
|
|
|
algorithm: Option<Algorithm>,
|
2019-09-13 23:12:12 +00:00
|
|
|
key_id: &str,
|
2019-09-13 22:55:51 +00:00
|
|
|
signature: &str,
|
|
|
|
signing_string: &str,
|
|
|
|
) -> Self::Future {
|
|
|
|
match algorithm {
|
|
|
|
Some(Algorithm::Hs2019) => (),
|
2019-09-11 23:06:36 +00:00
|
|
|
_ => return Err(MyError::Algorithm),
|
2019-09-13 22:55:51 +00:00
|
|
|
};
|
|
|
|
|
2019-09-13 23:12:12 +00:00
|
|
|
if key_id != "my-key-id" {
|
|
|
|
return Err(MyError::Key);
|
|
|
|
}
|
|
|
|
|
2019-09-13 22:55:51 +00:00
|
|
|
let decoded = base64::decode(signature).map_err(|_| MyError::Decode)?;
|
2019-09-11 23:06:36 +00:00
|
|
|
|
2019-09-13 22:55:51 +00:00
|
|
|
Ok(decoded == signing_string.as_bytes())
|
2019-09-11 23:06:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-13 23:27:04 +00:00
|
|
|
fn index(_: (DigestVerified, SignatureVerified)) -> &'static str {
|
2019-09-13 22:55:51 +00:00
|
|
|
"Eyyyyup"
|
|
|
|
}
|
|
|
|
|
2019-09-11 23:06:36 +00:00
|
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
|
let sys = System::new("server-example");
|
|
|
|
|
2019-09-13 22:55:51 +00:00
|
|
|
let config = Config::default();
|
|
|
|
|
2019-09-11 23:06:36 +00:00
|
|
|
HttpServer::new(move || {
|
|
|
|
App::new()
|
2019-09-13 23:27:04 +00:00
|
|
|
.wrap(VerifyDigest::new(Sha256::new()).optional())
|
|
|
|
.wrap(
|
|
|
|
VerifySignature::new(MyVerify, config.clone())
|
|
|
|
.authorization()
|
|
|
|
.optional(),
|
|
|
|
)
|
2019-09-13 01:12:35 +00:00
|
|
|
.route("/", web::post().to(index))
|
2019-09-11 23:06:36 +00:00
|
|
|
})
|
|
|
|
.bind("127.0.0.1:8010")?
|
|
|
|
.start();
|
|
|
|
|
|
|
|
sys.run()?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2019-09-13 01:29:24 +00:00
|
|
|
#[derive(Debug, Fail)]
|
2019-09-11 23:06:36 +00:00
|
|
|
enum MyError {
|
2019-09-13 01:29:24 +00:00
|
|
|
#[fail(display = "Failed to verify, {}", _0)]
|
2019-09-21 16:26:11 +00:00
|
|
|
Verify(#[cause] PrepareVerifyError),
|
2019-09-11 23:06:36 +00:00
|
|
|
|
2019-09-13 01:29:24 +00:00
|
|
|
#[fail(display = "Unsupported algorithm")]
|
|
|
|
Algorithm,
|
2019-09-13 22:55:51 +00:00
|
|
|
|
|
|
|
#[fail(display = "Couldn't decode signature")]
|
|
|
|
Decode,
|
2019-09-13 23:12:12 +00:00
|
|
|
|
|
|
|
#[fail(display = "Invalid key")]
|
|
|
|
Key,
|
2019-09-11 23:06:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ResponseError for MyError {
|
2019-09-13 22:55:51 +00:00
|
|
|
fn error_response(&self) -> HttpResponse {
|
|
|
|
HttpResponse::BadRequest().finish()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render_response(&self) -> HttpResponse {
|
|
|
|
self.error_response()
|
|
|
|
}
|
2019-09-11 23:06:36 +00:00
|
|
|
}
|
|
|
|
|
2019-09-21 16:26:11 +00:00
|
|
|
impl From<PrepareVerifyError> for MyError {
|
|
|
|
fn from(e: PrepareVerifyError) -> Self {
|
2019-09-11 23:06:36 +00:00
|
|
|
MyError::Verify(e)
|
|
|
|
}
|
|
|
|
}
|