// flotte-user-management server for managing users, roles and permissions // Copyright (C) 2020 trivernis // See LICENSE for more information use std::panic; use bcrypt::DEFAULT_COST; use byteorder::{BigEndian, ByteOrder}; use rand::Rng; use sha2::Digest; pub mod error; pub const TOKEN_LENGTH: usize = 32; const SALT_LENGTH: usize = 16; /// Creates a new random salt pub fn create_salt() -> [u8; SALT_LENGTH] { let mut rng = rand::thread_rng(); let mut salt = [0u8; SALT_LENGTH]; rng.fill(&mut salt); salt } /// Creates a new random user token where the first 4 bytes represent /// the userId pub fn create_user_token(user_id: i32) -> [u8; TOKEN_LENGTH] { let mut rng = rand::thread_rng(); let mut value = [0u8; TOKEN_LENGTH]; rng.fill(&mut value); BigEndian::write_i32(&mut value, user_id); value } /// Extracts the userId from a request token pub fn get_user_id_from_token(token: &String) -> Option { let token = base64::decode(&token).ok()?; if token.len() > 4 { Some(BigEndian::read_i32(token.as_slice())) } else { None } } /// Hashes a password with a salt by using BCrypt pub fn hash_password(password: &[u8], salt: &[u8]) -> Result<[u8; 24], String> { panic::catch_unwind(|| { let mut pw_hash = [0u8; 24]; let password = sha2::Sha256::digest(password); bcrypt::bcrypt(DEFAULT_COST, salt, password.as_slice(), &mut pw_hash); Ok(pw_hash) }) .map_err(|_| "Hashing failed".to_string())? }