JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Change forwarding

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨2556801

⁨giterated-models/src/model/authenticated.rs⁩ - ⁨5669⁩ bytes
Raw
1 use std::{any::type_name, fmt::Debug};
2
3 use rsa::{
4 pkcs1::DecodeRsaPrivateKey,
5 pss::SigningKey,
6 sha2::Sha256,
7 signature::{RandomizedSigner, SignatureEncoding},
8 RsaPrivateKey,
9 };
10 use serde::{Deserialize, Serialize};
11 use tracing::info;
12
13 use super::{instance::Instance, user::User};
14
15 #[derive(Debug, Serialize, Deserialize)]
16 pub struct UserTokenMetadata {
17 pub user: User,
18 pub generated_for: Instance,
19 pub exp: u64,
20 }
21
22 #[derive(Debug)]
23 pub struct Authenticated<T: Serialize> {
24 pub target_instance: Option<Instance>,
25 pub source: Vec<Box<dyn AuthenticationSourceProvider + Send + Sync>>,
26 pub message_type: String,
27 pub message: T,
28 }
29
30 #[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
31 pub struct AuthenticatedPayload {
32 pub target_instance: Option<Instance>,
33 pub source: Vec<AuthenticationSource>,
34 pub message_type: String,
35 pub payload: Vec<u8>,
36 }
37
38 impl<T: Serialize> From<Authenticated<T>> for AuthenticatedPayload {
39 fn from(mut value: Authenticated<T>) -> Self {
40 let payload = bincode::serialize(&value.message).unwrap();
41
42 AuthenticatedPayload {
43 target_instance: value.target_instance,
44 source: value
45 .source
46 .drain(..)
47 .map(|provider| provider.as_ref().authenticate(&payload))
48 .collect::<Vec<_>>(),
49 message_type: value.message_type,
50 payload,
51 }
52 }
53 }
54
55 pub trait AuthenticationSourceProvider: Debug {
56 fn authenticate(&self, payload: &Vec<u8>) -> AuthenticationSource;
57 }
58
59 pub trait AuthenticationSourceProviders: Debug {
60 fn authenticate_all(&self, payload: &Vec<u8>) -> Vec<AuthenticationSource>;
61 }
62
63 impl<A> AuthenticationSourceProviders for A
64 where
65 A: AuthenticationSourceProvider,
66 {
67 fn authenticate_all(&self, payload: &Vec<u8>) -> Vec<AuthenticationSource> {
68 vec![self.authenticate(payload)]
69 }
70 }
71
72 impl<A, B> AuthenticationSourceProviders for (A, B)
73 where
74 A: AuthenticationSourceProvider,
75 B: AuthenticationSourceProvider,
76 {
77 fn authenticate_all(&self, payload: &Vec<u8>) -> Vec<AuthenticationSource> {
78 let (first, second) = self;
79
80 vec![first.authenticate(payload), second.authenticate(payload)]
81 }
82 }
83
84 impl<T: Serialize + Debug> Authenticated<T> {
85 pub fn new(message: T) -> Self {
86 Self {
87 source: vec![],
88 message_type: type_name::<T>().to_string(),
89 message,
90 target_instance: None,
91 }
92 }
93
94 pub fn new_for(instance: impl ToOwned<Owned = Instance>, message: T) -> Self {
95 Self {
96 source: vec![],
97 message_type: type_name::<T>().to_string(),
98 message,
99 target_instance: Some(instance.to_owned()),
100 }
101 }
102
103 pub fn new_empty(message: T) -> Self {
104 Self {
105 source: vec![],
106 message_type: type_name::<T>().to_string(),
107 message,
108 target_instance: None,
109 }
110 }
111
112 pub fn append_authentication<P: AuthenticationSourceProvider + 'static + Send + Sync>(
113 &mut self,
114 authentication: P,
115 ) {
116 let message_payload = serde_json::to_vec(&self.message).unwrap();
117
118 info!(
119 "Verifying payload: {}",
120 std::str::from_utf8(&message_payload).unwrap()
121 );
122
123 self.source
124 .push(Box::new(authentication) as Box<dyn AuthenticationSourceProvider + Send + Sync>);
125 }
126
127 pub fn into_payload(self) -> AuthenticatedPayload {
128 self.into()
129 }
130 }
131
132 mod verified {}
133
134 #[derive(Clone, Debug)]
135 pub struct UserAuthenticator {
136 pub user: User,
137 pub token: UserAuthenticationToken,
138 }
139
140 impl AuthenticationSourceProvider for UserAuthenticator {
141 fn authenticate(&self, _payload: &Vec<u8>) -> AuthenticationSource {
142 AuthenticationSource::User {
143 user: self.user.clone(),
144 token: self.token.clone(),
145 }
146 }
147 }
148
149 #[derive(Debug, Clone)]
150 pub struct InstanceAuthenticator {
151 pub instance: Instance,
152 pub private_key: String,
153 }
154
155 impl AuthenticationSourceProvider for InstanceAuthenticator {
156 fn authenticate(&self, payload: &Vec<u8>) -> AuthenticationSource {
157 let mut rng = rand::thread_rng();
158
159 let private_key = RsaPrivateKey::from_pkcs1_pem(&self.private_key).unwrap();
160 let signing_key = SigningKey::<Sha256>::new(private_key);
161 let signature = signing_key.sign_with_rng(&mut rng, &payload);
162
163 AuthenticationSource::Instance {
164 instance: self.instance.clone(),
165 // TODO: Actually parse signature from private key
166 signature: InstanceSignature(signature.to_bytes().into_vec()),
167 }
168 }
169 }
170
171 #[repr(transparent)]
172 #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
173 pub struct UserAuthenticationToken(String);
174
175 impl From<String> for UserAuthenticationToken {
176 fn from(value: String) -> Self {
177 Self(value)
178 }
179 }
180
181 impl ToString for UserAuthenticationToken {
182 fn to_string(&self) -> String {
183 self.0.clone()
184 }
185 }
186
187 impl AsRef<str> for UserAuthenticationToken {
188 fn as_ref(&self) -> &str {
189 &self.0
190 }
191 }
192
193 #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
194 pub struct InstanceSignature(Vec<u8>);
195
196 impl AsRef<[u8]> for InstanceSignature {
197 fn as_ref(&self) -> &[u8] {
198 &self.0
199 }
200 }
201
202 #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
203 pub enum AuthenticationSource {
204 User {
205 user: User,
206 token: UserAuthenticationToken,
207 },
208 Instance {
209 instance: Instance,
210 signature: InstanceSignature,
211 },
212 }
213