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

ambee/giterated

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

Major connection refactor base

Type: Refactor

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨8dcc111

⁨src/messages/mod.rs⁩ - ⁨8191⁩ bytes
Raw
1 use anyhow::Error;
2 use jsonwebtoken::{decode, Algorithm, DecodingKey, TokenData, Validation};
3 use rsa::{
4 pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey},
5 pss::{Signature, SigningKey, VerifyingKey},
6 sha2::Sha256,
7 signature::{RandomizedSigner, SignatureEncoding, Verifier},
8 RsaPrivateKey, RsaPublicKey,
9 };
10 use serde::{Deserialize, Serialize};
11 use std::fmt::Debug;
12
13 use crate::{
14 authentication::UserTokenMetadata,
15 handshake::HandshakeMessage,
16 model::{instance::Instance, user::User},
17 };
18
19 use self::{
20 authentication::AuthenticationMessage, discovery::DiscoveryMessage,
21 repository::RepositoryMessage, user::UserMessage,
22 };
23
24 pub mod authentication;
25 pub mod discovery;
26 pub mod issues;
27 pub mod repository;
28 pub mod user;
29
30 #[derive(Clone, Serialize, Deserialize)]
31 pub enum MessageKind {
32 Handshake(HandshakeMessage),
33 Repository(RepositoryMessage),
34 Authentication(AuthenticationMessage),
35 Discovery(DiscoveryMessage),
36 User(UserMessage),
37 Error(ErrorMessage),
38 }
39
40 #[derive(Clone, Debug, Serialize, Deserialize, thiserror::Error)]
41 pub enum ErrorMessage {
42 #[error("user {0} doesn't exist or isn't valid in this context")]
43 InvalidUser(User),
44 #[error("internal error: shutdown")]
45 Shutdown,
46 }
47
48 /// An authenticated message, where the instance is authenticating
49 /// a request it is making for itself.
50 #[derive(Serialize, Deserialize)]
51 pub struct InstanceAuthenticated<T: Serialize> {
52 message: T,
53 pub instance: Instance,
54 signature: Vec<u8>,
55 }
56
57 impl<T> PartialEq for InstanceAuthenticated<T>
58 where
59 T: PartialEq + Serialize,
60 {
61 fn eq(&self, other: &Self) -> bool {
62 self.message == other.message
63 && self.instance == other.instance
64 && self.signature == other.signature
65 }
66 }
67
68 impl<T> Eq for InstanceAuthenticated<T> where T: Eq + Serialize {}
69
70 impl<T> std::hash::Hash for InstanceAuthenticated<T>
71 where
72 T: std::hash::Hash + Serialize,
73 {
74 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
75 self.message.hash(state);
76 self.instance.hash(state);
77 self.signature.hash(state);
78 }
79 }
80
81 impl<T> Clone for InstanceAuthenticated<T>
82 where
83 T: Clone + Serialize,
84 {
85 fn clone(&self) -> Self {
86 Self {
87 message: self.message.clone(),
88 instance: self.instance.clone(),
89 signature: self.signature.clone(),
90 }
91 }
92 }
93
94 impl<T> Debug for InstanceAuthenticated<T>
95 where
96 T: Debug + Serialize,
97 {
98 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99 f.debug_struct("Authenticated")
100 .field("message", &self.message)
101 .field("instance", &self.instance)
102 .field("signature", &self.signature)
103 .finish()
104 }
105 }
106
107 impl<T: Serialize> InstanceAuthenticated<T> {
108 pub fn new(message: T, instance: Instance, private_key: String) -> Result<Self, Error> {
109 let mut rng = rand::thread_rng();
110
111 let private_key = RsaPrivateKey::from_pkcs1_pem(&private_key)?;
112 let signing_key = SigningKey::<Sha256>::new(private_key);
113
114 let message_json = serde_json::to_vec(&message)?;
115
116 let signature = signing_key.sign_with_rng(&mut rng, &message_json);
117
118 Ok(Self {
119 message,
120 instance,
121 signature: signature.to_vec(),
122 })
123 }
124
125 pub async fn inner(&self) -> &T {
126 &self.message
127 }
128
129 pub async fn validate(&self, instance: &Instance) -> Result<(), Error> {
130 let public_key = public_key(instance).await?;
131 let public_key = RsaPublicKey::from_pkcs1_pem(&public_key).unwrap();
132
133 let verifying_key: VerifyingKey<Sha256> = VerifyingKey::new(public_key);
134
135 let message_json = serde_json::to_vec(&self.message).unwrap();
136
137 verifying_key
138 .verify(
139 &message_json,
140 &Signature::try_from(self.signature.as_ref()).unwrap(),
141 )
142 .unwrap();
143
144 Ok(())
145 }
146 }
147
148 /// An authenticated message.
149 ///
150 /// Includes the message, with a digest generated with
151 /// our private key.
152 #[derive(Serialize, Deserialize)]
153 pub struct ValidatedUserAuthenticated<T: Serialize> {
154 #[serde(flatten)]
155 message: T,
156 pub(crate) user: User,
157 }
158
159 impl<T> Clone for ValidatedUserAuthenticated<T>
160 where
161 T: Clone + Serialize,
162 {
163 fn clone(&self) -> Self {
164 Self {
165 message: self.message.clone(),
166 user: self.user.clone(),
167 }
168 }
169 }
170
171 impl<T> Debug for ValidatedUserAuthenticated<T>
172 where
173 T: Debug + Serialize,
174 {
175 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
176 f.debug_struct("Authenticated")
177 .field("message", &self.message)
178 .field("user", &self.user)
179 .finish()
180 }
181 }
182
183 impl<T: Serialize> ValidatedUserAuthenticated<T> {
184 pub async fn inner(&self) -> &T {
185 &self.message
186 }
187
188 pub async fn user(&self) -> &User {
189 &self.user
190 }
191 }
192
193 /// An unvalidated authenticated message.
194 ///
195 /// Includes the message, with a digest generated with
196 /// our private key.
197 #[derive(Serialize, Deserialize)]
198 pub struct UnvalidatedUserAuthenticated<T: Serialize> {
199 #[serde(flatten)]
200 message: T,
201 token: String,
202 digest: Vec<u8>,
203 }
204
205 impl<T> Clone for UnvalidatedUserAuthenticated<T>
206 where
207 T: Clone + Serialize,
208 {
209 fn clone(&self) -> Self {
210 Self {
211 message: self.message.clone(),
212 token: self.token.clone(),
213 digest: self.digest.clone(),
214 }
215 }
216 }
217
218 impl<T> Debug for UnvalidatedUserAuthenticated<T>
219 where
220 T: Debug + Serialize,
221 {
222 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
223 f.debug_struct("Authenticated")
224 .field("message", &self.message)
225 .field("token", &self.token)
226 .field("digest", &self.digest)
227 .finish()
228 }
229 }
230
231 impl<T: Serialize> UnvalidatedUserAuthenticated<T> {
232 pub fn new(message: T, token: String, private_key: String) -> Result<Self, Error> {
233 let mut rng = rand::thread_rng();
234
235 let private_key = RsaPrivateKey::from_pkcs1_pem(&private_key)?;
236 let signing_key = SigningKey::<Sha256>::new(private_key);
237
238 let message_json = serde_json::to_vec(&message)?;
239
240 let signature = signing_key.sign_with_rng(&mut rng, &message_json);
241
242 Ok(Self {
243 message,
244 token,
245 digest: signature.to_vec(),
246 })
247 }
248
249 pub async fn inner(&self) -> &T {
250 &self.message
251 }
252
253 pub async fn validate(self) -> Result<ValidatedUserAuthenticated<T>, Error> {
254 let instance = {
255 let mut validation = Validation::new(Algorithm::RS256);
256 validation.insecure_disable_signature_validation();
257
258 info!("Value: {:?}", self.token);
259
260 let value: TokenData<UserTokenMetadata> =
261 decode(&self.token, &DecodingKey::from_secret(b"test"), &validation).unwrap();
262
263 value.claims.generated_for.clone()
264 };
265
266 let public_key_raw = public_key(&instance).await?;
267 let public_key = RsaPublicKey::from_pkcs1_pem(&public_key_raw).unwrap();
268
269 let verifying_key: VerifyingKey<Sha256> = VerifyingKey::new(public_key);
270
271 let message_json = serde_json::to_vec(&self.message).unwrap();
272
273 verifying_key
274 .verify(
275 &message_json,
276 &Signature::try_from(self.digest.as_ref()).unwrap(),
277 )
278 .unwrap();
279
280 let verification_key = DecodingKey::from_rsa_pem(public_key_raw.as_bytes()).unwrap();
281
282 let data: TokenData<UserTokenMetadata> = decode(
283 &self.token,
284 &verification_key,
285 &Validation::new(Algorithm::RS256),
286 )
287 .unwrap();
288
289 assert_eq!(data.claims.generated_for, instance);
290
291 Ok(ValidatedUserAuthenticated {
292 message: self.message,
293 user: data.claims.user,
294 })
295 }
296 }
297
298 async fn public_key(instance: &Instance) -> Result<String, Error> {
299 let key = reqwest::get(format!("https://{}/.giterated/pubkey.pem", instance.url))
300 .await?
301 .text()
302 .await?;
303
304 Ok(key)
305 }
306