PaperTrader/src/libtrader/client/network/cmd/req_server_salt.rs

71 lines
2.1 KiB
Rust

use std::io;
use argon2::password_hash::SaltString;
use crate::common::message::*;
use tokio::net::TcpStream;
use tokio_rustls::client::TlsStream;
/// Issues a command to the connected TLS server to obtain a stored salt for either email or
/// password.
///
/// All salts returned are of size ```digest::SHA512_OUTPUT_LEN``` or 64 bytes.
/// Should be used in contexts that return ```io::Result```.
/// Should be used in Async contexts.
///
/// Arguments:
/// socket - The TLS client to use for the salt.
/// username - The username to obtain the salt.
/// salt_type - The CommmandInst, either GetEmailSalt, or GetPasswordSalt.
///
/// Returns: a ```io::Result<[u8; 64]>```.
/// Example:
/// ```rust
/// let server_salt: [u8; digest::SHA512_OUTPUT_LEN/2] = req_server_salt(tls_client, "n1ckn8me",
/// CommandInst::GetEmailSalt)?;
/// ```
pub async fn req_server_salt(
socket: &mut TlsStream<TcpStream>,
username: &str,
salt_type: Command,
) -> std::io::Result<SaltString> {
/* enforce salt_type to be either email or password */
assert_eq!(
(salt_type == Command::GetEmailSalt) || (salt_type == Command::GetPasswordSalt),
true
);
/* generate message to send */
Message::new()
.command(salt_type)
.data(username)
.send(socket)
.await?;
let ret_msg = Message::receive(socket).await?;
/* assert received message */
if !ret_msg.assert_command(Command::Success) || !ret_msg.assert_data() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Recieved invalid Salt from server.",
));
}
let salt_raw: String = ret_msg.get_data().map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidData,
"Could not get server salt, received invalid data.",
)
})?;
/* verify that the salt is actually valid */
SaltString::new(salt_raw.as_str()).map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidData,
format!("Could not get server salt, received invalid salt length."),
)
})
}