104 lines
4.0 KiB
Rust
104 lines
4.0 KiB
Rust
use ring::rand::SecureRandom;
|
|
use ring::{digest, rand};
|
|
use data_encoding::HEXUPPER;
|
|
use std::io::Write;
|
|
|
|
use crate::common::account::hash::hash;
|
|
|
|
use crate::common::message::message::Message;
|
|
use crate::common::message::message_type::MessageType;
|
|
use crate::common::message::inst::CommandInst;
|
|
use crate::common::message::message_builder::message_builder;
|
|
|
|
use crate::client::network::cmd::wait_and_read_branched::wait_and_read_branched;
|
|
use crate::client::network::cmd::get_server_salt::get_server_salt;
|
|
use crate::client::network::tls_client::TlsClient;
|
|
|
|
/// Requests a TLS server to create an account.
|
|
///
|
|
/// Gets three server salts, generates three new salts, cancatenates both salts, and use the
|
|
/// concatenated salt to hash the username, email, and password. Generates a message containing the
|
|
/// hashes and sends it to the server. Waits for a response and returns.
|
|
///
|
|
/// Arguments:
|
|
/// tls_client - The TLS client to use.
|
|
/// poll - The mio::Poll to get the events from.
|
|
/// username - The username to send to the server.
|
|
/// email - The email to send to the server.
|
|
/// password - The password to send to the server.
|
|
///
|
|
/// Returns: nothing on success, a string on error containing the reason of failure.
|
|
///
|
|
/// Example:
|
|
/// ```rust
|
|
/// match acc_create(&mut tlsclient, &mut poll, "test", "test", "test") {
|
|
/// Ok(()) => println!("server returned yes"),
|
|
/// Err(err) => panic!("panik {}", err),
|
|
/// }
|
|
/// ```
|
|
pub fn acc_create(tls_client: &mut TlsClient, poll: &mut mio::Poll,
|
|
username: &str, email: &str, password: &str) -> Result<(), String> {
|
|
/*
|
|
* get three server salts for email, and password
|
|
* */
|
|
let email_server_salt: [u8; digest::SHA512_OUTPUT_LEN/2] = match get_server_salt(tls_client, poll) {
|
|
Ok(salt) => salt,
|
|
Err(err) => return Err(format!("ACC_CREATE_RETRIEVE_SALTS_FAILED: {}", err))
|
|
};
|
|
let password_server_salt: [u8; digest::SHA512_OUTPUT_LEN/2] = match get_server_salt(tls_client, poll) {
|
|
Ok(salt) => salt,
|
|
Err(err) => return Err(format!("ACC_CREATE_RETRIEVE_SALTS_FAILED: {}", err))
|
|
};
|
|
|
|
/*
|
|
* generate client salts for email, password
|
|
* */
|
|
let rng = rand::SystemRandom::new();
|
|
let mut email_client_salt = [0u8; digest::SHA512_OUTPUT_LEN/2];
|
|
rng.fill(&mut email_client_salt).unwrap();
|
|
let mut password_client_salt = [0u8; digest::SHA512_OUTPUT_LEN/2];
|
|
rng.fill(&mut password_client_salt).unwrap();
|
|
|
|
/*
|
|
* generate final salts for email, password
|
|
* */
|
|
let email_salt = [email_server_salt, email_client_salt].concat();
|
|
let password_salt = [password_server_salt, password_client_salt].concat();
|
|
|
|
/*
|
|
* generate hashes for email, password
|
|
* */
|
|
let email_hash = hash(email, email_salt, 175_000);
|
|
let password_hash = hash(password, password_salt, 250_000);
|
|
|
|
/* generate message to be sent to the server */
|
|
let data = object!{
|
|
email_hash: HEXUPPER.encode(&email_hash),
|
|
email_client_salt: HEXUPPER.encode(&email_client_salt),
|
|
password_hash: HEXUPPER.encode(&password_hash),
|
|
password_client_salt: HEXUPPER.encode(&password_client_salt),
|
|
username: username
|
|
};
|
|
match message_builder(MessageType::Command, CommandInst::Register as i64, 5, 0, 0, data.dump().as_bytes().to_vec()) {
|
|
Ok(message) => {
|
|
tls_client.write(bincode::serialize(&message).unwrap().as_slice()).unwrap();
|
|
},
|
|
Err(_) => return Err("ACC_CREATE_MESSAGE_BUILD_FAILED".to_string())
|
|
};
|
|
|
|
/* wait for response */
|
|
wait_and_read_branched(tls_client, poll, Some(15), Some(500))?;
|
|
|
|
/* decode response */
|
|
let response: Message = bincode::deserialize(&tls_client.read_plaintext).unwrap();
|
|
tls_client.read_plaintext.clear();
|
|
|
|
if response.msgtype == MessageType::ServerReturn && response.instruction == 1 {
|
|
/* created successfully */
|
|
return Ok(());
|
|
} else {
|
|
/* server rejected account creation */
|
|
return Err("ACC_CREATE_FAILED_SERVER_REJECTED".to_string());
|
|
}
|
|
}
|