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

ambee/giterated

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

Update GitBackend to use new models

Type: Fix

emilia - ⁨2⁩ years ago

parent: tbd commit: ⁨f657cbe

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