why2_chat/crypto/
mod.rs

1/*
2This is part of WHY2
3Copyright (C) 2022-2026 Václav Šmejkal
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 3 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program.  If not, see <https://www.gnu.org/licenses/>.
17*/
18
19//MODULES
20#[cfg(feature = "server")]
21pub mod password;
22pub mod kex;
23
24use why2::
25{
26    Grid,
27    encrypter,
28    decrypter,
29    options as core_options,
30    auth::AuthenticatedData,
31};
32
33use sha2::{ Sha256, Digest };
34
35use crate::options;
36
37//CONSTS
38const GRID_W: usize = options::GRID_DIMENSIONS.0;
39const GRID_H: usize = options::GRID_DIMENSIONS.1;
40
41//FUNCTIONS
42pub fn sha256(seed_str: &str) -> [u8; 32] //GET HASH SEED; USED FOR PADDING
43{
44    //SHA256
45    let mut hasher = Sha256::new();
46    hasher.update(seed_str.as_bytes());
47
48    //FINALIZE
49    hasher.finalize().into()
50}
51
52pub fn encrypt_packet(packet_bytes: Vec<u8>, keys: &options::SharedKeys) -> Vec<u8>
53{
54    //CONVERT packet_bytes to BINARY
55    let mut input_i64 = Vec::with_capacity((packet_bytes.len() + 7) / 8);
56    for chunk in packet_bytes.chunks(8)
57    {
58        let mut buf = [0u8; 8];
59        buf[..chunk.len()].copy_from_slice(chunk);
60        input_i64.push(i64::from_be_bytes(buf));
61    }
62
63    //ENCRYPT
64    let encrypted_data = encrypter::encrypt::<GRID_W, GRID_H>(&input_i64, Some(&keys.0)).expect("Encrypting packet failed");
65
66    //AUTHENTICATE
67    AuthenticatedData::authenticate(encrypted_data, keys.1.as_slice().try_into().unwrap()).into()
68}
69
70pub fn decrypt_packet(mut decoded_packet: Vec<u8>, keys: &options::SharedKeys) -> Option<Vec<u8>>
71{
72    //DESERIALIZE
73    let auth_packet: AuthenticatedData<GRID_W, GRID_H> = decoded_packet.as_slice().try_into().ok()?;
74
75    //VERIFY HMAC
76    if !auth_packet.verify(keys.1.as_slice().try_into().ok()?)
77    {
78        return None;
79    }
80
81    //DECRYPT
82    let decrypted_packet = decrypter::decrypt(core_options::EncryptedData
83    {
84        output: auth_packet.encrypted_data.output,
85        key: Grid::from_key(&keys.0).ok()?,
86        nonce: auth_packet.encrypted_data.nonce,
87    }).ok()?;
88
89    //OVERWRITE decoded_packet
90    decoded_packet = Vec::with_capacity(decrypted_packet.output.len() * 8);
91    for val in decrypted_packet.output.to_vec()
92    {
93        decoded_packet.extend_from_slice(&val.to_be_bytes());
94    }
95
96    Some(decoded_packet)
97}