kkv 1.2.1

A Peer-to-Peer Decentralized, Temporary and Anonymous Message System.
Documentation
/**************************************************************************
 *   src/types.rs  --  This file is part of kkv.                          *
 *                                                                        *
 *   Copyright (C) 2025 Mateo Lafalce                                     *
 *                                                                        *
 *   kkv is free software: you can redistribute it and/or modify          *
 *   it under the terms of the GNU General Public License as published    *
 *   by the Free Software Foundation, either version 3 of the License,    *
 *   or (at your option) any later version.                               *
 *                                                                        *
 *   kkv is distributed in the hope that it will be useful,               *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty          *
 *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.              *
 *   See the GNU General Public License for more details.                 *
 *                                                                        *
 *   You should have received a copy of the GNU General Public License    *
 *   along with this program.  If not, see http://www.gnu.org/licenses/.  *
 *                                                                        *
 **************************************************************************/

use crate::message::Message;
use chacha20poly1305::Nonce;
use ed25519_dalek::PUBLIC_KEY_LENGTH;
use paste::paste;
use serde::{Deserialize, Serialize};
use validator::Validate;
use x25519_dalek::{PublicKey, ReusableSecret};

pub type OnionPubkey = [u8; PUBLIC_KEY_LENGTH];
pub type Ed25519Pubkey = [u8; 32];
pub type Ed25519Singature = [u8; 64];

pub type OnionUrl = String;
pub type Body = String;
pub type HexPubkey = String;
pub type HexDomain = String;
pub type HexSignature = String;
pub type HexMessage = String;
pub type HexCipher = String;
pub type HexNonce = String;
pub type HexPoW = String;
pub type HexDiffieHellman = String;

macro_rules! generate_getters {
    ($struct_name:ident, $( $field:ident : $field_type:ty ),* ) => {
        impl $struct_name {
            $(
                paste! {
                    pub fn [<get_ $field>](&self) -> $field_type {
                        self.$field.clone()
                    }
                }
            )*
        }
    };
}

#[derive(Debug, Deserialize, serde::Serialize, Validate)]
pub struct RequestPubkey {
    #[validate(length(equal = 64, message = "bytes length should be 64"))]
    bytes: HexPubkey,
}

impl RequestPubkey {
    pub fn new(bytes: HexPubkey) -> Self {
        RequestPubkey { bytes }
    }
}

generate_getters!(
    RequestPubkey,
    bytes: HexPubkey
);

#[derive(Debug, Deserialize, Serialize, Validate)]
pub struct PoW {
    /// [bytes_to_search]32bytes + [difficult]4bytes + [client_pk]32bytes + [duration_limit]8bytes
    #[validate(length(equal = 152, message = "bytes_to_verify length should be 64"))]
    bytes: HexMessage,
    #[validate(length(equal = 128, message = "signature length should be 128"))]
    signature: HexSignature,
}

impl PoW {
    pub fn new(bytes: HexMessage, signature: HexSignature) -> Self {
        PoW { bytes, signature }
    }
}

generate_getters!(
    PoW,
    bytes: HexMessage,
    signature: HexSignature
);

impl Default for PoW {
    fn default() -> Self {
        PoW::new(hex::encode([0; 80]), hex::encode([0; 64]))
    }
}

#[derive(Debug, Deserialize, Serialize, Validate)]
pub struct SolvedPoW {
    #[validate(length(equal = 64, message = "pubkey length should be 64"))]
    pubkey: HexPubkey,
    #[validate(length(equal = 64, message = "nonce length should be 64"))]
    nonce: HexNonce,
    #[validate(length(equal = 128, message = "signature length should be 128"))]
    signature: HexSignature,
}

impl SolvedPoW {
    pub fn new(pubkey: HexPubkey, nonce: HexNonce, signature: HexSignature) -> Self {
        SolvedPoW {
            pubkey,
            nonce,
            signature,
        }
    }
}

generate_getters!(
    SolvedPoW,
    pubkey: HexPubkey,
    nonce: HexNonce,
    signature: HexSignature
);

#[derive(Debug, Deserialize, Serialize, Validate)]
pub struct SentMessage {
    #[validate(length(equal = 64, message = "pubkey length should be 64"))]
    pubkey: HexPubkey,
    #[validate(length(max = 6000, message = "chiphertext length should be max 6000"))]
    chiphertext: HexCipher,
    #[validate(length(equal = 128, message = "signature length should be 128"))]
    signature: HexSignature,
}

impl SentMessage {
    pub fn new(pubkey: HexPubkey, chiphertext: HexCipher, signature: HexSignature) -> Self {
        SentMessage {
            pubkey,
            chiphertext,
            signature,
        }
    }
}

generate_getters!(
    SentMessage,
    pubkey: HexPubkey,
    chiphertext: HexCipher,
    signature: HexSignature
);

#[derive(Debug, Serialize, Deserialize)]
pub struct DataCollection {
    size: usize,
    items: Vec<Message>,
}

impl Default for DataCollection {
    fn default() -> Self {
        DataCollection::new(0, vec![])
    }
}

impl DataCollection {
    pub fn new(size: usize, items: Vec<Message>) -> Self {
        DataCollection { size, items }
    }
}

generate_getters!(
    DataCollection,
    size: usize,
    items: Vec<Message>
);

#[derive(Serialize, Deserialize, Debug)]
pub struct ServerIndex {
    index: usize,
}

impl ServerIndex {
    pub fn new(index: usize) -> Self {
        ServerIndex { index }
    }
}

generate_getters!(
    ServerIndex,
    index: usize
);

impl Default for ServerIndex {
    fn default() -> Self {
        ServerIndex::new(0)
    }
}

#[derive(Debug, Deserialize, Serialize, Validate)]
pub struct IndexMsg {
    index: usize,
}

impl IndexMsg {
    pub fn new(index: usize) -> Self {
        IndexMsg { index }
    }
}

generate_getters!(
    IndexMsg,
    index: usize
);

#[derive(Debug, Deserialize, Serialize, Validate)]
pub struct KeyExchange {
    #[validate(length(equal = 64, message = "pubkey length should be 64"))]
    ed25519_pubkey: HexPubkey,
    #[validate(length(equal = 64, message = "nonce length should be 64"))]
    nonce: HexNonce,
    #[validate(length(equal = 152, message = "pow length should be 152"))]
    pow: HexPoW,
    #[validate(length(equal = 128, message = "pow_sig length should be 128"))]
    pow_sig: HexPoW,
    #[validate(length(equal = 64, message = "diffie_hellman length should be 64"))]
    diffie_hellman: HexDiffieHellman,
    #[validate(length(equal = 128, message = "diffie_hellman_sig length should be 128"))]
    diffie_hellman_sig: HexSignature,
}

impl KeyExchange {
    pub fn new(
        ed25519_pubkey: HexPubkey,
        nonce: HexNonce,
        pow: HexPoW,
        pow_sig: HexPoW,
        diffie_hellman: HexDiffieHellman,
        diffie_hellman_sig: HexSignature,
    ) -> Self {
        KeyExchange {
            ed25519_pubkey,
            nonce,
            pow,
            pow_sig,
            diffie_hellman,
            diffie_hellman_sig,
        }
    }
}

impl Default for KeyExchange {
    fn default() -> Self {
        KeyExchange::new(
            String::default(),
            String::default(),
            String::default(),
            String::default(),
            String::default(),
            String::default(),
        )
    }
}

generate_getters!(
    KeyExchange,
    ed25519_pubkey: HexPubkey,
    nonce: HexNonce,
    pow: HexPoW,
    pow_sig: HexPoW,
    diffie_hellman: HexDiffieHellman,
    diffie_hellman_sig: HexSignature
);

/// This struct is exclusive store in the server side
/// Give us the keypairs for decrypt the ciphertext
pub struct Keypair {
    bob_diffie_hellman_sk: ReusableSecret,
    alice_diffie_hellman_pk: PublicKey,
    shared_nonce: Nonce,
    nonce_from_pow: HexNonce,
    unix_timestamp_seconds: u64,
}

impl Keypair {
    pub fn new(
        bob_diffie_hellman_sk: ReusableSecret,
        alice_diffie_hellman_pk: PublicKey,
        shared_nonce: Nonce,
        nonce_from_pow: HexNonce,
        unix_timestamp_seconds: u64,
    ) -> Self {
        Keypair {
            bob_diffie_hellman_sk,
            alice_diffie_hellman_pk,
            shared_nonce,
            nonce_from_pow,
            unix_timestamp_seconds,
        }
    }
}

generate_getters!(
    Keypair,
    bob_diffie_hellman_sk: ReusableSecret,
    alice_diffie_hellman_pk: PublicKey,
    shared_nonce: Nonce,
    nonce_from_pow: HexNonce,
    unix_timestamp_seconds: u64
);