#[cfg(feature = "server")]
pub mod password;
pub mod kex;
use why2::
{
encrypter,
decrypter,
grid::Grid,
types::EncryptedData,
auth::AuthenticatedData,
};
use zeroize::Zeroizing;
use hkdf::Hkdf;
use sha2::{ Sha256, Digest };
use crate::consts;
pub fn get_correct_key<const W: usize, const H: usize>(key: &Zeroizing<Vec<i64>>) -> Zeroizing<Vec<i64>> {
let mut key_bytes = Vec::with_capacity(key.len() * 8);
for val in key.iter()
{
key_bytes.extend_from_slice(&val.to_be_bytes());
}
let hkdf = Hkdf::<Sha256>::new(None, &key_bytes);
let required_len = W * H * 2;
let needed_bytes = required_len * 8;
let mut output_bytes = vec![0u8; needed_bytes];
hkdf.expand(format!("WHY2-DERIVED-KEY-{W}x{H}").as_bytes(), &mut output_bytes).expect("Key derivation failed");
let mut derived_key = Vec::with_capacity(required_len);
for chunk in output_bytes.chunks_exact(8)
{
let mut buf = [0u8; 8];
buf.copy_from_slice(chunk);
derived_key.push(i64::from_be_bytes(buf));
}
Zeroizing::new(derived_key)
}
pub fn sha256(seed_str: &str) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(seed_str.as_bytes());
hasher.finalize().into()
}
pub fn encrypt_packet<const W: usize, const H: usize>(packet_bytes: Vec<u8>, keys: &consts::SharedKeys) -> Vec<u8>
{
let mut input_i64 = Vec::with_capacity((packet_bytes.len() + 7) / 8);
for chunk in packet_bytes.chunks(8)
{
let mut buf = [0u8; 8];
buf[..chunk.len()].copy_from_slice(chunk);
input_i64.push(i64::from_be_bytes(buf));
}
let key = if keys.0.len() == W * H * 2
{
&keys.0
} else
{
&get_correct_key::<W, H>(&keys.0)
};
let encrypted_data = encrypter::encrypt::<W, H>(&input_i64, Some(key))
.expect("Encrypting packet failed");
AuthenticatedData::authenticate(encrypted_data, keys.1.as_slice().try_into().unwrap()).into()
}
pub fn decrypt_packet<const W: usize, const H: usize>(mut decoded_packet: Vec<u8>, keys: &consts::SharedKeys) -> Option<Vec<u8>>
{
let auth_packet: AuthenticatedData<W, H> = decoded_packet.as_slice().try_into().ok()?;
if !auth_packet.verify(keys.1.as_slice().try_into().ok()?)
{
return None;
}
let key = if keys.0.len() == W * H * 2
{
&keys.0
} else
{
&get_correct_key::<W, H>(&keys.0)
};
let decrypted_packet = decrypter::decrypt(EncryptedData
{
output: auth_packet.encrypted_data.output,
key: Grid::from_key(&key).ok()?,
nonce: auth_packet.encrypted_data.nonce,
}).ok()?;
decoded_packet = Vec::with_capacity(decrypted_packet.output.len() * 8);
for val in decrypted_packet.output.to_vec()
{
decoded_packet.extend_from_slice(&val.to_be_bytes());
}
Some(decoded_packet)
}