use crate::{error::MyError, state::State}; use actix_web::client::Client; use http_signature_normalization_actix::prelude::*; use rsa::{hash::Hashes, padding::PaddingScheme, PublicKey, RSAPublicKey}; use rsa_pem::KeyExt; use std::{future::Future, pin::Pin, sync::Arc}; #[derive(Clone)] pub struct MyVerify(pub State, pub Client); impl SignatureVerify for MyVerify { type Error = MyError; type Future = Pin>>>; fn signature_verify( &mut self, algorithm: Option, key_id: &str, signature: &str, signing_string: &str, ) -> Self::Future { let key_id = key_id.to_owned(); let signature = signature.to_owned(); let signing_string = signing_string.to_owned(); let state = Arc::new(self.0.clone()); let client = Arc::new(self.1.clone()); Box::pin(async move { let actor = crate::inbox::fetch_actor(state, client, &key_id.parse()?).await?; let public_key = actor.public_key.ok_or(MyError::MissingKey)?; let public_key = RSAPublicKey::from_pem_pkcs8(&public_key.public_key_pem)?; match algorithm { Some(Algorithm::Hs2019) => (), _ => return Err(MyError::Algorithm), }; let decoded = base64::decode(signature)?; public_key.verify( PaddingScheme::PKCS1v15, Some(&Hashes::SHA2_256), &decoded, signing_string.as_bytes(), )?; Ok(true) }) } }