Actix-web middleware to sign and verify detached jws (Detached JWS)
```rust use std::{io::Read, sync::Arc};
use actixweb::{ dev::ServiceRequest, error::{ErrorForbidden, ErrorInternalServerError}, web::{self}, App, Error, HttpServer, Responder, }; use actixwebdetachedjwsmiddleware::{ DetachedJwsSign, DetachedJwsSignConfig, DetachedJwsVerify, DetachedJwsVerifyConfig, VerifyErrorType, }; use detachedjws::JwsHeader; use futures::future::{ready, Ready}; use openssl::{ hash::MessageDigest, pkcs12::{ParsedPkcs12, Pkcs12}, rsa::Padding, sign::{Signer, Verifier}, };
async fn index() -> impl Responder { "thisisresponse_body" }
async fn main() -> std::io::Result<()> { let config = Arc::new(Config::new());
HttpServer::new(move || {
App::new()
.service(
web::resource("/protected")
.wrap(DetachedJwsVerify::new(config.clone()))
.wrap(DetachedJwsSign::new(config.clone()))
.route(web::post().to(index)),
)
.service(web::resource("/simple").route(web::post().to(index)))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
struct Config { certrs256: ParsedPkcs12, certps256: ParsedPkcs12, }
impl Config { fn new() -> Self { let loadpkcs12 = |path, pass| { let mut file = std::fs::File::open(path).unwrap(); let mut pkcs12 = vec![]; file.readto_end(&mut pkcs12).unwrap();
let pkcs12 = Pkcs12::from_der(&pkcs12).unwrap();
pkcs12.parse(pass).unwrap()
};
Self {
cert_rs256: load_pkcs12("examples/cert_for_rs256.pfx", "123456"),
cert_ps256: load_pkcs12("examples/cert_for_ps256.pfx", "123456"),
}
}
}
impl<'a> DetachedJwsVerifyConfig<'a> for Config {
type Verifier = Verifier<'a>;
type ErrorHandler = Ready
fn get_verifier(&'a self, h: &JwsHeader) -> Option<Self::Verifier> {
match h.get("alg")?.as_str()? {
"RS256" => {
let mut verifier =
Verifier::new(MessageDigest::sha256(), &self.cert_rs256.pkey).unwrap();
verifier.set_rsa_padding(Padding::PKCS1).unwrap();
Some(verifier)
}
"PS256" => {
let mut verifier =
Verifier::new(MessageDigest::sha256(), &self.cert_ps256.pkey).unwrap();
verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
Some(verifier)
}
_ => None,
}
}
fn error_handler(
&'a self,
_: &'a mut ServiceRequest,
error: VerifyErrorType,
) -> Self::ErrorHandler {
ready(match error {
VerifyErrorType::HeaderNotFound => ErrorForbidden("Header Not Found"),
VerifyErrorType::IncorrectSignature => ErrorForbidden("Incorrect Signature"),
VerifyErrorType::Other(e) => ErrorInternalServerError(e),
})
}
}
impl<'a> DetachedJwsSignConfig<'a> for Config { type Signer = Signer<'a>;
fn get_signer(&'a self) -> (Self::Signer, String, JwsHeader) {
let mut signer = Signer::new(MessageDigest::sha256(), &self.cert_ps256.pkey).unwrap();
signer.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
(signer, "PS256".into(), JwsHeader::new())
}
}
```