diff --git a/src/connection/authentication.rs b/src/connection/authentication.rs index 6675291..e505bdc 100644 --- a/src/connection/authentication.rs +++ b/src/connection/authentication.rs @@ -9,7 +9,6 @@ use crate::model::authenticated::{Message, MessageHandler}; use super::wrapper::ConnectionState; - pub async fn authentication_handle( message_type: &str, message: &NetworkMessage, diff --git a/src/connection/repository.rs b/src/connection/repository.rs index c9a6f2c..87d13ae 100644 --- a/src/connection/repository.rs +++ b/src/connection/repository.rs @@ -9,7 +9,7 @@ use crate::{ model::authenticated::{AuthenticatedUser, Message, MessageHandler, NetworkMessage, State}, }; -use super::{wrapper::ConnectionState}; +use super::wrapper::ConnectionState; pub async fn repository_handle( message_type: &str, diff --git a/src/connection/user.rs b/src/connection/user.rs index 7133bc8..fa2fa9e 100644 --- a/src/connection/user.rs +++ b/src/connection/user.rs @@ -1,6 +1,5 @@ use anyhow::Error; - use crate::model::authenticated::AuthenticatedUser; use crate::model::user::User; use crate::{ @@ -11,7 +10,7 @@ use crate::{ model::authenticated::{Message, MessageHandler, NetworkMessage, State}, }; -use super::{wrapper::ConnectionState}; +use super::wrapper::ConnectionState; pub async fn user_handle( message_type: &str, diff --git a/src/model/authenticated.rs b/src/model/authenticated.rs index b865cc3..6248463 100644 --- a/src/model/authenticated.rs +++ b/src/model/authenticated.rs @@ -3,6 +3,13 @@ use std::{any::type_name, collections::HashMap, ops::Deref}; use anyhow::Error; use futures_util::Future; use jsonwebtoken::{decode, Algorithm, DecodingKey, TokenData, Validation}; +use rsa::{ + pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey}, + pss::{Signature, SigningKey, VerifyingKey}, + sha2::Sha256, + signature::{RandomizedSigner, SignatureEncoding, Verifier}, + RsaPrivateKey, RsaPublicKey, +}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_json::Value; @@ -102,11 +109,17 @@ pub struct InstanceAuthenticator<'a> { } impl AuthenticationSourceProvider for InstanceAuthenticator<'_> { - fn authenticate(self, _payload: &Vec) -> AuthenticationSource { + fn authenticate(self, payload: &Vec) -> AuthenticationSource { + let mut rng = rand::thread_rng(); + + let private_key = RsaPrivateKey::from_pkcs1_pem(self.private_key).unwrap(); + let signing_key = SigningKey::::new(private_key); + let signature = signing_key.sign_with_rng(&mut rng, &payload); + AuthenticationSource::Instance { instance: self.instance, // TODO: Actually parse signature from private key - signature: InstanceSignature(self.private_key.as_bytes().to_vec()), + signature: InstanceSignature(signature.to_bytes().into_vec()), } } } @@ -136,6 +149,12 @@ impl AsRef for UserAuthenticationToken { #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] pub struct InstanceSignature(Vec); +impl AsRef<[u8]> for InstanceSignature { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] pub enum AuthenticationSource { User { @@ -234,12 +253,12 @@ impl FromMessage for AuthenticatedUser { impl FromMessage for AuthenticatedInstance { async fn from_message( network_message: &NetworkMessage, - _state: &ConnectionState, + state: &ConnectionState, ) -> Result { - let message: Authenticated> = + let message: Authenticated = serde_json::from_slice(&network_message).map_err(|e| Error::from(e))?; - let (instance, _signature) = message + let (instance, signature) = message .source .iter() .filter_map(|auth| { @@ -257,9 +276,21 @@ impl FromMessage for AuthenticatedInstance { // TODO: Instance authentication error .ok_or_else(|| UserAuthenticationError::Missing)?; - // TODO: Actually validate + let public_key = public_key(instance).await?; + let public_key = RsaPublicKey::from_pkcs1_pem(&public_key).unwrap(); + + let verifying_key: VerifyingKey = VerifyingKey::new(public_key); + + let message_json = serde_json::to_vec(&message.message).unwrap(); + + verifying_key + .verify( + &message_json, + &Signature::try_from(signature.as_ref()).unwrap(), + ) + .unwrap(); - Ok(Self(instance.clone())) + Ok(AuthenticatedInstance(instance.clone())) } }