aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/handlers.rs136
-rw-r--r--src/schema.rs2
2 files changed, 123 insertions, 15 deletions
diff --git a/src/handlers.rs b/src/handlers.rs
index 848cb75..515caa5 100644
--- a/src/handlers.rs
+++ b/src/handlers.rs
@@ -60,9 +60,9 @@ const BEARER: &str = "Bearer ";
60/// public_key: "---BEGIN PUBLIC KEY..." 60/// public_key: "---BEGIN PUBLIC KEY..."
61/// } 61/// }
62/// 62///
63/// - Encrypts the serialized string of `auth_plaintext` with 128 bit block AES in CBC mode with Pkcs7 padding using the temporary key (`k_temp`), the result is `auth_ciphertext` TODO should this be base64'd? 63/// - Encrypts the serialized string of `auth_plaintext` with 128 bit block AES in CBC mode with Pkcs7 padding using the temporary key (`k_temp`), the result is `auth_ciphertext`
64/// - The temporary key student has picked `k_temp` is encrypted using RSA with OAEP padding scheme 64/// - The temporary key student has picked `k_temp` is encrypted using RSA with OAEP padding scheme
65/// using sha256 with `gradecoin_public_key` (TODO base64? same as above), giving us `key_ciphertext` 65/// using sha256 with `gradecoin_public_key`, giving us `key_ciphertext`
66/// - The payload JSON object (`auth_request`) can be JSON serialized now: 66/// - The payload JSON object (`auth_request`) can be JSON serialized now:
67/// { 67/// {
68/// c: "auth_ciphertext" 68/// c: "auth_ciphertext"
@@ -103,18 +103,126 @@ pub async fn authenticate_user(
103 let gradecoin_private_key = RSAPrivateKey::from_pkcs1(&der_bytes).expect("failed to parse key"); 103 let gradecoin_private_key = RSAPrivateKey::from_pkcs1(&der_bytes).expect("failed to parse key");
104 104
105 let padding = PaddingScheme::new_oaep::<sha2::Sha256>(); 105 let padding = PaddingScheme::new_oaep::<sha2::Sha256>();
106 let temp_key = gradecoin_private_key 106
107 .decrypt(padding, &request.key.as_bytes()) 107 let key_ciphertext = match base64::decode(&request.key) {
108 .expect("failed to decrypt"); 108 Ok(c) => c,
109 109 Err(err) => {
110 // decrypt c using key dec_key 110 debug!(
111 let cipher = Aes128Cbc::new_var(&temp_key, &request.iv.as_bytes()).unwrap(); 111 "The ciphertext of the key was not base64 encoded {}, {}",
112 let auth_plaintext = cipher 112 &request.key, err
113 .decrypt_vec(&base64::decode(request.c).unwrap()) 113 );
114 .unwrap(); 114
115 115 let res_json = warp::reply::json(&GradeCoinResponse {
116 let request: AuthRequest = 116 res: ResponseType::Error,
117 serde_json::from_str(&String::from_utf8(auth_plaintext).unwrap()).unwrap(); 117 message: "The ciphertext of the key was not base64 encoded {}, {}".to_owned(),
118 });
119
120 return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST));
121 }
122 };
123
124 let temp_key = match gradecoin_private_key.decrypt(padding, &key_ciphertext) {
125 Ok(k) => k,
126 Err(err) => {
127 debug!(
128 "Failed to decrypt ciphertext {:?}, {}",
129 &key_ciphertext, err
130 );
131
132 let res_json = warp::reply::json(&GradeCoinResponse {
133 res: ResponseType::Error,
134 message: "Failed to decrypt the ciphertext of the temporary key".to_owned(),
135 });
136
137 return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST));
138 }
139 };
140
141 let cipher = match Aes128Cbc::new_var(&temp_key, &request.iv.as_bytes()) {
142 Ok(c) => c,
143 Err(err) => {
144 debug!(
145 "Could not create a cipher from temp_key and request.iv {:?}, {}, {}",
146 &temp_key, &request.iv, err
147 );
148
149 let res_json = warp::reply::json(&GradeCoinResponse {
150 res: ResponseType::Error,
151 message: "Given IV has invalid length".to_owned(),
152 });
153
154 return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST));
155 }
156 };
157
158 let auth_packet = match base64::decode(&request.c) {
159 Ok(a) => a,
160
161 Err(err) => {
162 debug!(
163 "The auth_packet (c field) did not base64 decode {} {}",
164 &request.c, err
165 );
166
167 let res_json = warp::reply::json(&GradeCoinResponse {
168 res: ResponseType::Error,
169 message: "The c field was not correctly base64 encoded".to_owned(),
170 });
171
172 return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST));
173 }
174 };
175
176 let auth_plaintext = match cipher.decrypt_vec(&auth_packet) {
177 Ok(p) => p,
178 Err(err) => {
179 debug!(
180 "Base64 decoded auth request did not decrypt correctly {:?} {}",
181 &auth_packet, err
182 );
183
184 let res_json = warp::reply::json(&GradeCoinResponse {
185 res: ResponseType::Error,
186 message: "The Bas64 decoded auth request did not decrypt correctly".to_owned(),
187 });
188
189 return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST));
190 }
191 };
192
193 let utf8_auth_plaintext = match String::from_utf8(auth_plaintext.clone()) {
194 Ok(text) => text,
195 Err(err) => {
196 debug!(
197 "Auth plaintext did not convert into utf8 {:?} {}",
198 &auth_plaintext, err
199 );
200
201 let res_json = warp::reply::json(&GradeCoinResponse {
202 res: ResponseType::Error,
203 message: "Auth plaintext couldn't get converted to UTF-8".to_owned(),
204 });
205
206 return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST));
207 }
208 };
209
210 let request: AuthRequest = match serde_json::from_str(&utf8_auth_plaintext) {
211 Ok(req) => req,
212 Err(err) => {
213 debug!(
214 "Auth plaintext did not serialize correctly {:?} {}",
215 &utf8_auth_plaintext, err
216 );
217
218 let res_json = warp::reply::json(&GradeCoinResponse {
219 res: ResponseType::Error,
220 message: "The auth request JSON did not serialize correctly".to_owned(),
221 });
222
223 return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST));
224 }
225 };
118 226
119 let provided_id = request.student_id.clone(); 227 let provided_id = request.student_id.clone();
120 228
diff --git a/src/schema.rs b/src/schema.rs
index 6f2f1f3..dca0eef 100644
--- a/src/schema.rs
+++ b/src/schema.rs
@@ -163,7 +163,7 @@ impl Block {
163 Block { 163 Block {
164 transaction_list: vec!["gradecoin_bank".to_owned()], 164 transaction_list: vec!["gradecoin_bank".to_owned()],
165 nonce: 0, 165 nonce: 0,
166 timestamp: NaiveDate::from_ymd(2021, 04, 11).and_hms(20, 45, 00), 166 timestamp: NaiveDate::from_ymd(2021, 4, 11).and_hms(20, 45, 00),
167 hash: String::from("not_actually_mined"), 167 hash: String::from("not_actually_mined"),
168 } 168 }
169 } 169 }