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

ambee/giterated

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

Fixes

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨25c3410

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