1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use super::*;
use crate::error::SigningErr;

use hmac::{Hmac, Mac};
use sha2::{Sha512, Sha256};
use crate::{cryptography::*, error::*};

/// Represents a cryptographic signing operation, including data, passphrase, operational status,
/// hash type, signature length, and verification status.
impl Sign {
    /// Constructs a new `Sign` instance with specified data, passphrase, operation status, and hash type.
    ///
    /// # Parameters
    /// - `data`: The data to be signed or verified.
    /// - `passphrase`: The passphrase used for HMAC generation.
    /// - `status`: The operation status (signing or verifying).
    /// - `hash_type`: The hash algorithm to use for signing.
    ///
    /// # Returns
    /// A new `Sign` instance.
    pub fn new(data: Vec<u8>, passphrase: Vec<u8>, status: Operation, hash_type: SignType) -> Self {
        let data = SignatureData {
            data, passphrase, hmac: Vec::new(), concat_data: Vec::new()
        };
        match hash_type {
            SignType::Sha512 => Sign { data, status, hash_type, length: 64, veryfied: false},
            SignType::Sha256 => Sign { data, status, hash_type, length: 32, veryfied: false},
            _ => Sign { data, status, hash_type, length: 64, veryfied: false},
         } 
    }

    /// Performs the HMAC operation based on the operation status: generates HMAC for signing
    /// or verifies HMAC for verification.
    ///
    /// # Returns
    /// HMAC as a `Vec<u8>` for signing or the verified data for verification.
    pub fn hmac(&mut self) -> Vec<u8> {
        match &self.status {
            Operation::Sign => {
                let data = self.generate_hmac();
                data
            },
            Operation::Verify => {
                let data = self.verify_hmac();
                data.unwrap()
            },
            _ => vec![],
        }
    }

    /// Generates HMAC for the data using the specified hash type and passphrase.
    ///
    /// # Returns
    /// Concatenated original data and its HMAC as a `Vec<u8>`.
    pub fn generate_hmac(&self) -> Vec<u8> {
        let mut data = &self.data.data;
        match &self.hash_type {
            SignType::Sha512 => {
                let mut mac = <Hmac<Sha512> as Mac>::new_from_slice(&self.data.passphrase)
                    .expect("HMAC can take key of any size");
                mac.update(&data);
                let hmac = mac.finalize().into_bytes().to_vec();
                //println!("HMAC: {:?}", hmac);
                let concat_data = [&self.data.data, hmac.as_slice()].concat();
                //println!("Concated data: {:?}", concat_data);
                concat_data
            },
            SignType::Sha256 => {
                let mut mac = <Hmac<Sha256> as Mac>::new_from_slice(&self.data.passphrase)
                    .expect("HMAC can take key of any size");
                mac.update(&data);
                let hmac = mac.finalize().into_bytes().to_vec();
                println!("HMAC: {:?}", hmac);
                let concat_data = [&self.data.data, hmac.as_slice()].concat();
                println!("Concated data: {:?}", concat_data);
                concat_data
            },
            _ => vec![],
        }
    }

    /// Verifies HMAC using SHA-512.
    ///
    /// # Parameters
    /// - `data`: The data part of the message.
    /// - `hmac`: The HMAC to verify against.
    /// - `passphrase`: The passphrase used for HMAC generation.
    ///
    /// # Returns
    /// `true` if verification is successful, `false` otherwise.
    fn verify_hmac_sha512(data: &[u8], hmac: &[u8], passphrase: &[u8]) -> bool {
        let mut mac = <Hmac<Sha512> as Mac>::new_from_slice(passphrase)
            .expect("HMAC can take key of any size");
        mac.update(data);
        mac.verify_slice(hmac).is_ok()
    }

    /// Verifies HMAC using SHA-256.
    ///
    /// # Parameters
    /// - `data`: The data part of the message.
    /// - `hmac`: The HMAC to verify against.
    /// - `passphrase`: The passphrase used for HMAC generation.
    ///
    /// # Returns
    /// `true` if verification is successful, `false` otherwise.
    fn verify_hmac_sha256(data: &[u8], hmac: &[u8], passphrase: &[u8]) -> bool {
        let mut mac = <Hmac<Sha256> as Mac>::new_from_slice(passphrase)
            .expect("HMAC can take key of any size");
        mac.update(data);
        mac.verify_slice(hmac).is_ok()
    }

    /// Verifies HMAC based on the hash type. Splits the provided data into the original data
    /// and HMAC, then verifies the HMAC.
    ///
    /// # Returns
    /// `Ok(Vec<u8>)` containing the original data if verification is successful, `Err(&'static str)` otherwise.
    pub fn verify_hmac(&self) -> Result<Vec<u8>, &'static str> {
        if self.data.data.len() < self.length {
            return Err("Data is too short for HMAC verification");
        }

        let (data, hmac) = self.data.data.split_at(self.data.data.len() - self.length);

        let verification_success = match &self.hash_type {
            SignType::Sha512 => Self::verify_hmac_sha512(data, hmac, &self.data.passphrase),
            SignType::Sha256 => Self::verify_hmac_sha256(data, hmac, &self.data.passphrase),
            _ => return Err("Unsupported HMAC hash type"),
        };

        if verification_success {
            println!("splittet data: {:?}", data);
            Ok(data.to_owned())
        } else {
            Err("HMAC verification failed")
        }
    }
}