summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYigit Sever2021-04-14 03:27:27 +0300
committerYigit Sever2021-04-14 19:11:49 +0300
commitedfab6ae2f97a7288ff456265050c01ff397ea8c (patch)
treee98ce8b12c1ef4d61c70944f47d87d74297a8ed3 /src
parenta5d5ab88d3f73d0b6f5fa847df6dace90810313d (diff)
downloadgradecoin-edfab6ae2f97a7288ff456265050c01ff397ea8c.tar.gz
gradecoin-edfab6ae2f97a7288ff456265050c01ff397ea8c.tar.bz2
gradecoin-edfab6ae2f97a7288ff456265050c01ff397ea8c.zip
[WIP] Initial implementation of user auth
There is a dance involved and everything Write down specs for RSA and AES, padding scheme, ugh.
Diffstat (limited to 'src')
-rw-r--r--src/custom_filters.rs8
-rw-r--r--src/handlers.rs34
-rw-r--r--src/lib.rs40
-rw-r--r--src/schema.rs9
4 files changed, 83 insertions, 8 deletions
diff --git a/src/custom_filters.rs b/src/custom_filters.rs
index ae8a56c..299cd8d 100644
--- a/src/custom_filters.rs
+++ b/src/custom_filters.rs
@@ -1,5 +1,5 @@
1/// Functions that extracts Structs to be used in warp routines 1/// Functions that extracts Structs to be used in warp routines
2use crate::schema::{AuthRequest, Block, Db, Transaction}; 2use crate::schema::{Block, Db, InitialAuthRequest, Transaction};
3use std::convert::Infallible; 3use std::convert::Infallible;
4use warp::{Filter, Rejection}; 4use warp::{Filter, Rejection};
5 5
@@ -8,12 +8,12 @@ pub fn with_db(db: Db) -> impl Filter<Extract = (Db,), Error = Infallible> + Clo
8 warp::any().map(move || db.clone()) 8 warp::any().map(move || db.clone())
9} 9}
10 10
11/// Extracts an `AuthRequest` JSON body from the request 11/// Extracts an `InitialAuthRequest` JSON body from the request
12/// Accepts only JSON encoded `AuthRequest` body and rejects big payloads 12/// Accepts only JSON encoded `AuthRequest` body and rejects big payloads
13/// 13///
14// TODO: find a good limit for this, (=e2482057; 8 char String + rsa pem) <11-04-21, yigit> // 14// TODO: find a good limit for this, (=e2482057; 8 char String + rsa pem) <11-04-21, yigit> //
15pub fn auth_request_json_body() -> impl Filter<Extract = (AuthRequest,), Error = Rejection> + Clone 15pub fn auth_request_json_body(
16{ 16) -> impl Filter<Extract = (InitialAuthRequest,), Error = Rejection> + Clone {
17 warp::body::content_length_limit(1024 * 32).and(warp::body::json()) 17 warp::body::content_length_limit(1024 * 32).and(warp::body::json())
18} 18}
19 19
diff --git a/src/handlers.rs b/src/handlers.rs
index b9df931..9d1bb10 100644
--- a/src/handlers.rs
+++ b/src/handlers.rs
@@ -1,3 +1,4 @@
1use base64;
1/// API handlers, the ends of each filter chain 2/// API handlers, the ends of each filter chain
2use blake2::{Blake2s, Digest}; 3use blake2::{Blake2s, Digest};
3use jsonwebtoken::errors::ErrorKind; 4use jsonwebtoken::errors::ErrorKind;
@@ -5,12 +6,16 @@ use jsonwebtoken::{decode, Algorithm, DecodingKey, TokenData, Validation};
5use log::{debug, warn}; 6use log::{debug, warn};
6use md5::Md5; 7use md5::Md5;
7use parking_lot::RwLockUpgradableReadGuard; 8use parking_lot::RwLockUpgradableReadGuard;
9use rsa::{PaddingScheme, RSAPrivateKey};
8use serde::Serialize; 10use serde::Serialize;
9use serde_json; 11use serde_json;
12use sha2;
10use std::convert::Infallible; 13use std::convert::Infallible;
11use std::fs; 14use std::fs;
12use warp::{http::StatusCode, reply}; 15use warp::{http::StatusCode, reply};
13 16
17use crate::PRIVATE_KEY;
18
14#[derive(Serialize, Debug)] 19#[derive(Serialize, Debug)]
15struct GradeCoinResponse { 20struct GradeCoinResponse {
16 res: ResponseType, 21 res: ResponseType,
@@ -23,7 +28,9 @@ enum ResponseType {
23 Error, 28 Error,
24} 29}
25 30
26use crate::schema::{AuthRequest, Block, Claims, Db, MetuId, NakedBlock, Transaction, User}; 31use crate::schema::{
32 AuthRequest, Block, Claims, Db, InitialAuthRequest, MetuId, NakedBlock, Transaction, User,
33};
27 34
28const BEARER: &str = "Bearer "; 35const BEARER: &str = "Bearer ";
29 36
@@ -32,11 +39,34 @@ const BEARER: &str = "Bearer ";
32/// Lets a [`User`] (=student) to authenticate themselves to the system 39/// Lets a [`User`] (=student) to authenticate themselves to the system
33/// This `request` can be rejected if the payload is malformed (= not authenticated properly) or if 40/// This `request` can be rejected if the payload is malformed (= not authenticated properly) or if
34/// the [`AuthRequest.user_id`] of the `request` is not in the list of users that can hold a Gradecoin account 41/// the [`AuthRequest.user_id`] of the `request` is not in the list of users that can hold a Gradecoin account
42/// The request first comes in encrypted
35pub async fn authenticate_user( 43pub async fn authenticate_user(
36 request: AuthRequest, 44 request: InitialAuthRequest,
37 db: Db, 45 db: Db,
38) -> Result<impl warp::Reply, warp::Rejection> { 46) -> Result<impl warp::Reply, warp::Rejection> {
39 debug!("POST request to /register, authenticate_user"); 47 debug!("POST request to /register, authenticate_user");
48
49 // TODO: lazyload or something <14-04-21, yigit> //
50 let der_encoded = PRIVATE_KEY
51 .lines()
52 .filter(|line| !line.starts_with("-"))
53 .fold(String::new(), |mut data, line| {
54 data.push_str(&line);
55 data
56 });
57 let der_bytes = base64::decode(&der_encoded).expect("failed to decode base64 content");
58 let private_key = RSAPrivateKey::from_pkcs1(&der_bytes).expect("failed to parse key");
59
60 let padding = PaddingScheme::new_oaep::<sha2::Sha256>();
61 let dec_key = private_key
62 .decrypt(padding, &request.key.as_bytes())
63 .expect("failed to decrypt");
64
65 // then decrypt c using key dec_key
66
67 // let request: AuthRequest = serde_json::from_str(&String::from_utf8(dec_data).unwrap()).unwrap();
68 let request;
69
40 let provided_id = request.student_id.clone(); 70 let provided_id = request.student_id.clone();
41 71
42 let priv_student_id = match MetuId::new(request.student_id, request.passwd) { 72 let priv_student_id = match MetuId::new(request.student_id, request.passwd) {
diff --git a/src/lib.rs b/src/lib.rs
index 42def0f..7a24f9f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -22,7 +22,45 @@
22//! `Authorization`: The request header should have Bearer JWT.Token signed with Student Public Key 22//! `Authorization`: The request header should have Bearer JWT.Token signed with Student Public Key
23 23
24pub mod custom_filters; 24pub mod custom_filters;
25pub mod error;
25pub mod handlers; 26pub mod handlers;
26pub mod routes; 27pub mod routes;
27pub mod schema; 28pub mod schema;
28pub mod error; 29
30pub const PRIVATE_KEY: &'static str = "-----BEGIN RSA PRIVATE KEY-----
31MIIEogIBAAKCAQEAyGuqiCPGcguy+Y9TH7Bl7XlEsalyqb9bYlzpbV0dnqZ3lPkE
32PkuOhkN+GcuiV6iXtSwyh7nB+xTRXKJFRUBO/jbN8jfcxVwBu0JxjF3v1YRBxbOH
33hz2A295mbKD9xHQCKxkfYBNkUXxj8gd+GaDvQiSW5NdrX/lEkvqfGtdEX1m2+Hdc
34G0+3YW24Xg0znhCwLr+sorLuJaDy9Xa0Uo+DPWGC5s001U/BxkCIWJ+eJQCb7Bv+
359vXb8BGRK/ecMb/fb6h5O+8fgB64RCHMgcc2v+Q/dPt8kHX1OJdMuYUrUJGACppM
36QY3W6e1HdlRIBcZKL2LMZ2CrIB/2D5LiJhPThQIDAQABAoIBABbHrg1lS5QA4mnd
37MYyDh0JTq0wqP18t4dwvRVTp5Yj30NW87A+MlPmLyFR0QdKG1h+Ak4m7wmGgfx9x
38TkBNy+y3G/dxBAXmrEe1iKR0tOLm8nbfLgNgKTpUb/3e2pkuumRdqaRI7/kXE2Ea
39Guoc0bUJ5aDDH3A8K+As3lK1rw7LNxwxZdmqmpO+EAldP6NaLnXNP5BegjLK50xP
40NXTDNx6pw+I2ZHHwC/A6+QVksSA6zPipI1poANaO0frHffwKhcEZ/VucuXlJGGq/
41aqXT/cc7IkKUVq8EZUwUqHi4SrnyDDq/mtuikSD0MazxumbeC6fBKRP98Kavy2rT
42JItHSYECgYEA8H/yC9GDrR1bwBesD0pKdKBy18UMFQF3BrB04OjqdGzugdVafF4e
437azYQQTQ0ZddLDvgYl0QYvQaZfv26L7o4VrN5XEg8WjUWKuww8XUYOCfPn4gOFL1
44ar8nQ0w3P65gYf/rw0rFMo3eB78rJMROYnG8nZ/3OdgQjVaYPJxFKmECgYEA1VZy
45EQz8dHK3+F0EfQIFeXOSlYGUegmPZ9iYmh+yvW/zWKLYdXBEHNhAIRlBmfe7Yhj6
461FNluNGjFqZYuRnP0RuiBxt2RCd+AL90Lqq+O6jem4XNgr3cOKoaV0FbaU49sI4s
47/B6iiYBFdVuPBiknz+Wf1KEF9lQ+w2VYSLucY6UCgYAWPe73ste3sehjWo0aGOfL
48427bj6ivZKRKZRVaG5BbVhu0vDOTHu1DU+HoGXbqe1ItnhgBYNP8ItEyL1xFaCqH
49dOtn1c+TI/vHe5FseaZLk1qG4AlAzENQLP+HlMvjQtA9H/sA47BbHY20L7TgwJrz
50NcuY1Et7+QSG3cRUjqtC4QKBgGuP+VUVehfwW0dzBrdMlJwGpGqS+dyKA271awOS
51ZdlTn5saCA82OnFcqwDFLilGGYk9VQJGxivoLtVVq7gwBnLE/u2ccAWu773KyfZZ
52ii6kVxCM5vA7b9R2F2/U+RTgKQRiutWnUIYJUXv5XORbTcJpYSugwFPRaA+2gkux
53pAktAoGABRyVs5LOhQ/oeXe2H2kvuaUq9c7f/dTtnyMNdNxK0uZcQn4jcB2eK9kB
54PDYHM9dfQ8xn51U0fTeaXjy/8Km8fyX2Jtxntlm6puyhSTJ8AX+FEgJkC4ajNEvA
55mJ1Gsy2fXKUyyZdI2b74MLqOpzr9cvS60tmTIScuiHFzg/SJgiA=
56-----END RSA PRIVATE KEY-----";
57
58pub const PUB_KEY: &'static str = "-----BEGIN PUBLIC KEY-----
59MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyGuqiCPGcguy+Y9TH7Bl
607XlEsalyqb9bYlzpbV0dnqZ3lPkEPkuOhkN+GcuiV6iXtSwyh7nB+xTRXKJFRUBO
61/jbN8jfcxVwBu0JxjF3v1YRBxbOHhz2A295mbKD9xHQCKxkfYBNkUXxj8gd+GaDv
62QiSW5NdrX/lEkvqfGtdEX1m2+HdcG0+3YW24Xg0znhCwLr+sorLuJaDy9Xa0Uo+D
63PWGC5s001U/BxkCIWJ+eJQCb7Bv+9vXb8BGRK/ecMb/fb6h5O+8fgB64RCHMgcc2
64v+Q/dPt8kHX1OJdMuYUrUJGACppMQY3W6e1HdlRIBcZKL2LMZ2CrIB/2D5LiJhPT
65hQIDAQAB
66-----END PUBLIC KEY-----";
diff --git a/src/schema.rs b/src/schema.rs
index 9e157c7..f159d83 100644
--- a/src/schema.rs
+++ b/src/schema.rs
@@ -178,7 +178,7 @@ pub struct MetuId {
178 passwd: String, 178 passwd: String,
179} 179}
180 180
181// TODO: this will arrive encrypted <13-04-21, yigit> // 181/// The plaintext of the initial user authentication request
182#[derive(Serialize, Deserialize, Debug, PartialEq)] 182#[derive(Serialize, Deserialize, Debug, PartialEq)]
183pub struct AuthRequest { 183pub struct AuthRequest {
184 pub student_id: String, 184 pub student_id: String,
@@ -186,6 +186,13 @@ pub struct AuthRequest {
186 pub public_key: String, 186 pub public_key: String,
187} 187}
188 188
189/// Ciphertext of the initial authentication request, or what we will receive
190#[derive(Serialize, Deserialize, Debug)]
191pub struct InitialAuthRequest {
192 pub c: String,
193 pub key: String,
194}
195
189lazy_static! { 196lazy_static! {
190 static ref OUR_STUDENTS: HashSet<(&'static str, &'static str)> = { 197 static ref OUR_STUDENTS: HashSet<(&'static str, &'static str)> = {
191 [ 198 [