use std::{error::Error, fmt::Debug}; use rsa::{ pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey}, pkcs8::{DecodePrivateKey, DecodePublicKey}, pss::{Signature, SigningKey, VerifyingKey}, sha2::Sha256, signature::{RandomizedSigner, SignatureEncoding, Verifier}, RsaPrivateKey, RsaPublicKey, }; use serde::{Deserialize, Serialize}; use crate::{handshake::HandshakeMessage, model::instance::Instance}; use self::{authentication::AuthenticationMessage, repository::RepositoryMessage}; pub mod authentication; pub mod issues; pub mod repository; pub mod user; #[derive(Clone, Serialize, Deserialize)] pub enum MessageKind { Handshake(HandshakeMessage), Repository(RepositoryMessage), Authentication(AuthenticationMessage), } /// An authenticated message, where the instance is authenticating /// a request it is making for itself. #[derive(Serialize, Deserialize)] pub struct InstanceAuthenticated { message: T, instance: Instance, signature: Vec, } impl Clone for InstanceAuthenticated where T: Clone + Serialize, { fn clone(&self) -> Self { Self { message: self.message.clone(), instance: self.instance.clone(), signature: self.signature.clone(), } } } impl Debug for InstanceAuthenticated where T: Debug + Serialize, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Authenticated") .field("message", &self.message) .field("instance", &self.instance) .field("signature", &self.signature) .finish() } } impl InstanceAuthenticated { pub fn new( message: T, instance: Instance, private_key: String, ) -> Result> { let mut rng = rand::thread_rng(); let private_key = RsaPrivateKey::from_pkcs1_pem(&private_key)?; let signing_key = SigningKey::::new(private_key); let message_json = serde_json::to_vec(&message)?; let signature = signing_key.sign_with_rng(&mut rng, &message_json); Ok(Self { message, instance, signature: signature.to_vec(), }) } pub async fn inner(&self) -> &T { &self.message } pub async fn validate(&self, key: String) -> Result<(), Box> { let public_key = RsaPublicKey::from_pkcs1_pem(&key).unwrap(); let verifying_key: VerifyingKey = VerifyingKey::new(public_key); let message_json = serde_json::to_vec(&self.message).unwrap(); verifying_key .verify( &message_json, &Signature::try_from(self.signature.as_ref()).unwrap(), ) .unwrap(); Ok(()) } } /// An authenticated message. /// /// Includes the message, with a digest generated with /// our private key. #[derive(Serialize, Deserialize)] pub struct UserAuthenticated { #[serde(flatten)] message: T, token: String, digest: Vec, } impl Clone for UserAuthenticated where T: Clone + Serialize, { fn clone(&self) -> Self { Self { message: self.message.clone(), token: self.token.clone(), digest: self.digest.clone(), } } } impl Debug for UserAuthenticated where T: Debug + Serialize, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Authenticated") .field("message", &self.message) .field("token", &self.token) .field("digest", &self.digest) .finish() } } impl UserAuthenticated { pub fn new(message: T, token: String, private_key: String) -> Result> { let mut rng = rand::thread_rng(); let private_key = RsaPrivateKey::from_pkcs1_pem(&private_key)?; let signing_key = SigningKey::::new(private_key); let message_json = serde_json::to_vec(&message)?; let signature = signing_key.sign_with_rng(&mut rng, &message_json); Ok(Self { message, token, digest: signature.to_vec(), }) } pub async fn inner(&self) -> &T { &self.message } pub async fn validate(&self, key: String) -> Result<(), Box> { let public_key = RsaPublicKey::from_pkcs1_pem(&key).unwrap(); let verifying_key: VerifyingKey = VerifyingKey::new(public_key); let message_json = serde_json::to_vec(&self.message).unwrap(); verifying_key .verify( &message_json, &Signature::try_from(self.digest.as_ref()).unwrap(), ) .unwrap(); Ok(()) } }