Skip to main content

tequel/hash/
mod.rs

1/*
2 * Tequel-rs: High-Density 384-bit Cryptographic Hash Engine
3 * Copyright (C) 2026 Gabriel Xavier (dotxav)
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU Affero General Public License for more details.
14 */
15
16#[cfg(target_arch = "x86_64")]
17use std::arch::x86_64::*;
18use crate::avx2_inline::{ add, loadu, or, rota_lf, rota_rg, setone_i32, setzero, xor, horiz_add_avx2 };
19
20
21macro_rules! teq_direct {
22    ($ss:ident, $ss1:expr, $lv:expr, $lr:expr, $ymm_a1:ident) => {
23        $ss = add($ss, $ymm_a1);
24        $ss = or(rota_lf::<$lv>($ss), rota_rg::<$lr>($ss));
25        $ss = xor($ss1, $ss);
26    };
27}
28
29use zeroize::{Zeroize, ZeroizeOnDrop};
30
31#[cfg(feature = "serde")]
32use serde::{Serialize, Deserialize};
33
34
35/// ```TequelHash``` provides hash functions, custom iterations and salt. <br><br>
36#[derive(Debug, Zeroize, ZeroizeOnDrop, Clone, PartialEq, Eq)]
37#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
38pub struct TequelHash {
39    pub states: [u32; 12],
40    pub salt: String,
41    pub iterations: u32
42}
43
44impl TequelHash {
45
46    pub fn new() -> Self { 
47        Self {
48            states: [
49                0x1A2B3C4D, 0x5E6F7A8B, 0x9C0D1E2F, 0x31415926,
50                0x27182818, 0xDEADBEEF, 0xCAFEBABE, 0x80808080,
51                0xABCDEF01, 0x456789AB, 0xFEDCBA98, 0x01234567
52            ],
53            salt: "".to_string(),
54            iterations: 30
55        } 
56    }
57
58
59
60    pub fn with_salt(mut self, salt: &str) -> Self {
61        self.salt = salt.to_string();
62        self
63    }
64
65    pub fn with_iteration(mut self, value: u32) -> Self{
66        self.iterations = value;
67        self
68    }
69
70    /// Generates a unique 384-bit hexadecimal hash from the input data.
71    ///
72    /// This function is the core of the Tequel engine, utilizing **SIMD/AVX2** /// instructions to process data in 256-bit blocks. It is designed for 
73    /// high-speed performance and maximum bit diffusion.
74    ///
75    /// # Performance
76    /// By leveraging hardware acceleration, `tqlhash` achieves significantly lower 
77    /// latency compared to scalar implementations, making it ideal for 
78    /// large-scale data integrity checks and real-time obfuscation.
79    ///
80    /// # Determinism
81    /// The algorithm is strictly deterministic. Providing the same input bytes 
82    /// will always yield the exact same hexadecimal string.
83    ///
84    /// # Arguments
85    /// * `input` - The raw data bytes (`&[u8]`) to be hashed.
86    ///
87    /// # Returns
88    /// A 96-character hexadecimal `String` (12 x 32-bit internal states).
89    ///
90    /// # Example
91    /// ```rust
92    /// use tequel::hash::TequelHash;
93    /// 
94    /// let mut tequel = TequelHash::new();
95    /// let data = b"secret_data";
96    /// 
97    /// let hash_a = tequel.tqlhash(data);
98    /// let hash_b = tequel.tqlhash(data);
99    /// 
100    /// assert_eq!(hash_a, hash_b);
101    /// println!("Hash: {}", hash_a);
102    /// ```
103    pub fn tqlhash(&mut self, input: &[u8]) -> String {
104
105        self.states = [
106            0x107912FA, 0x220952EA, 0x3320212A, 0x4324312F, 
107            0x5320212A, 0x9E3779B1, 0x85EBCA6B, 0xAD35744D,
108            0xCC2912FA, 0xEE0952EA, 0x1120212A, 0x2224312F,
109        ];
110
111        const HEX_CHARS: &[u8; 16] = b"0123456789abcdef";
112
113        let mut s0  = unsafe { setzero() };
114        let mut s1  = unsafe { setzero() };
115        let mut s2  = unsafe { setzero() };
116        let mut s3  = unsafe { setzero() };
117        let mut s4  = unsafe { setzero() };
118        let mut s5  = unsafe { setzero() };
119        let mut s6  = unsafe { setzero() };
120        let mut s7  = unsafe { setzero() };
121        let mut s8  = unsafe { setzero() };
122        let mut s9  = unsafe { setzero() };
123        let mut s10 = unsafe { setzero() };
124        let mut s11 = unsafe { setzero() };
125
126        let mut chunks = input.chunks_exact(128);
127
128        for chunk in chunks.by_ref() {
129
130            unsafe {
131
132                let bl_a = &chunk[..64];
133                let bl_b = &chunk[64..];
134
135                let ymm_a1 = loadu(bl_a.as_ptr() as *const __m256i);
136                let ymm_a2 = xor(loadu(bl_a.as_ptr().add(32) as *const __m256i), setone_i32(0x517CC1B7));
137
138                teq_direct!(s0,  s1,  7,  25,   ymm_a1);
139                teq_direct!(s1,  s2,  31, 28,   ymm_a2);
140                teq_direct!(s2,  s3,  25, 7,    ymm_a1);
141                teq_direct!(s3,  s4,  23, 9,    ymm_a2);
142                teq_direct!(s4,  s5,  13, 19,   ymm_a1);
143                teq_direct!(s5,  s6,  29, 3,    ymm_a2);
144                teq_direct!(s6,  s7,  19, 13,   ymm_a1);
145                teq_direct!(s7,  s8,  17, 15,   ymm_a2);
146                teq_direct!(s8,  s9,  11, 21,   ymm_a1);
147                teq_direct!(s9,  s10, 5,  27,   ymm_a2);
148                teq_direct!(s10, s11, 3,  29,   ymm_a1);
149                teq_direct!(s11, s0,  2,  30,   ymm_a2);
150
151                let ymm_b1 = loadu(bl_b.as_ptr() as *const __m256i);
152                let ymm_b2 = xor(loadu(bl_b.as_ptr().add(32) as *const __m256i), setone_i32(0x517CC1B7));
153
154                teq_direct!(s0,  s1,  7,  25,   ymm_b1);
155                teq_direct!(s1,  s2,  31, 28,   ymm_b2);
156                teq_direct!(s2,  s3,  25, 7,    ymm_b1);
157                teq_direct!(s3,  s4,  23, 9,    ymm_b2);
158                teq_direct!(s4,  s5,  13, 19,   ymm_b1);
159                teq_direct!(s5,  s6,  29, 3,    ymm_b2);
160                teq_direct!(s6,  s7,  19, 13,   ymm_b1);
161                teq_direct!(s7,  s8,  17, 15,   ymm_b2);
162                teq_direct!(s8,  s9,  11, 21,   ymm_b1);
163                teq_direct!(s9,  s10, 5,  27,   ymm_b2);
164                teq_direct!(s10, s11, 3,  29,   ymm_b1);
165                teq_direct!(s11, s0,  2,  30,   ymm_b2);
166
167                s0 = xor(s0, s11);
168
169            }
170
171        }
172
173
174        unsafe {
175            self.states[0]  = self.states[0] .wrapping_add(horiz_add_avx2(s0));
176            self.states[1]  = self.states[1] .wrapping_add(horiz_add_avx2(s1));
177            self.states[2]  = self.states[2] .wrapping_add(horiz_add_avx2(s2));
178            self.states[3]  = self.states[3] .wrapping_add(horiz_add_avx2(s3));
179            self.states[4]  = self.states[4] .wrapping_add(horiz_add_avx2(s4));
180            self.states[5]  = self.states[5] .wrapping_add(horiz_add_avx2(s5));
181            self.states[6]  = self.states[6] .wrapping_add(horiz_add_avx2(s6));
182            self.states[7]  = self.states[7] .wrapping_add(horiz_add_avx2(s7));
183            self.states[8]  = self.states[8] .wrapping_add(horiz_add_avx2(s8));
184            self.states[9]  = self.states[9] .wrapping_add(horiz_add_avx2(s9));
185            self.states[10] = self.states[10].wrapping_add(horiz_add_avx2(s10));
186            self.states[11] = self.states[11].wrapping_add(horiz_add_avx2(s11));
187        }
188
189
190        let remainder_128 = chunks.remainder();
191        let mut chunks_64 = remainder_128.chunks_exact(64);
192
193        for chunk in chunks_64.by_ref() {
194            unsafe {
195
196                let ymm_a1 = loadu(chunk.as_ptr() as *const __m256i);
197                let ymm_a2 = xor(loadu(chunk.as_ptr().add(32) as *const __m256i), setone_i32(0x517CC1B7));
198
199                teq_direct!(s0,  s1,  7,  25,   ymm_a1);
200                teq_direct!(s1,  s2,  31, 28,   ymm_a2);
201                teq_direct!(s2,  s3,  25, 7,    ymm_a1);
202                teq_direct!(s3,  s4,  23, 9,    ymm_a2);
203                teq_direct!(s4,  s5,  13, 19,   ymm_a1);
204                teq_direct!(s5,  s6,  29, 3,    ymm_a2);
205                teq_direct!(s6,  s7,  19, 13,   ymm_a1);
206                teq_direct!(s7,  s8,  17, 15,   ymm_a2);
207                teq_direct!(s8,  s9,  11, 21,   ymm_a1);
208                teq_direct!(s9,  s10, 5,  27,   ymm_a2);
209                teq_direct!(s10, s11, 3,  29,   ymm_a1);
210                teq_direct!(s11, s0,  2,  30,   ymm_a2);                
211
212            }
213        }
214
215
216        let final_remainder = chunks_64.remainder();
217
218        for (idx, &byte) in final_remainder.iter().enumerate() {
219            let pos = idx % 12;
220            self.states[pos] = self.states[pos].wrapping_add((byte as u32) ^ 0x9E3779B1);
221        }
222
223        self.apply_final_mixer_64();
224
225        let mut hex_buffer = vec![0u8; 96];
226
227        for (i, &s) in self.states.iter().enumerate() {
228            let bytes = s.to_be_bytes();
229            for (j, &byte) in bytes.iter().enumerate() {
230                let offset = (i * 8) + (j * 2);
231                hex_buffer[offset] = HEX_CHARS[(byte >> 4) as usize];
232                hex_buffer[offset + 1] = HEX_CHARS[(byte & 0x0f) as usize];
233            }
234        }
235        
236        unsafe { String::from_utf8_unchecked(hex_buffer) }
237
238    }
239
240
241    /// Generates a unique 384-bit hexadecimal hash from the input data.
242    ///
243    /// This function is the core of the Tequel engine, utilizing **SIMD/AVX2** /// instructions to process data in 256-bit blocks. It is designed for 
244    /// high-speed performance and maximum bit diffusion.
245    ///
246    /// # Performance
247    /// By leveraging hardware acceleration, `tqlhash_raw` achieves significantly lower 
248    /// latency compared to scalar implementations, making it ideal for 
249    /// large-scale data integrity checks and real-time obfuscation.
250    ///
251    /// # Determinism
252    /// The algorithm is strictly deterministic. Providing the same input bytes 
253    /// will always yield the exact same hexadecimal string.
254    ///
255    /// # Arguments
256    /// * `input` - The raw data bytes (`&[u8]`).
257    ///
258    /// # Returns
259    /// A 32-bit list `[u8; 32]` 
260    ///
261    /// # Example
262    /// ```rust
263    /// use tequel::hash::TequelHash;
264    /// 
265    /// let mut tequel = TequelHash::new();
266    /// let data = b"secret_data";
267    /// 
268    /// let bytes_a = tequel.tqlhash_raw(data);
269    /// let bytes_b = tequel.tqlhash_raw(data);
270    /// 
271    /// assert_eq!(bytes_a, bytes_b);
272    /// println!("bytes: {:?}", bytes_a);
273    /// ```
274    pub fn tqlhash_raw(&mut self, input: &[u8]) -> [u8; 48] {
275
276        self.states = [
277            0x107912FA, 0x220952EA, 0x3320212A, 0x4324312F, 
278            0x5320212A, 0x9E3779B1, 0x85EBCA6B, 0xAD35744D,
279            0xCC2912FA, 0xEE0952EA, 0x1120212A, 0x2224312F,
280        ];
281
282        const HEX_CHARS: &[u8; 16] = b"0123456789abcdef";
283
284        let mut s0  = unsafe { setzero() };
285        let mut s1  = unsafe { setzero() };
286        let mut s2  = unsafe { setzero() };
287        let mut s3  = unsafe { setzero() };
288        let mut s4  = unsafe { setzero() };
289        let mut s5  = unsafe { setzero() };
290        let mut s6  = unsafe { setzero() };
291        let mut s7  = unsafe { setzero() };
292        let mut s8  = unsafe { setzero() };
293        let mut s9  = unsafe { setzero() };
294        let mut s10 = unsafe { setzero() };
295        let mut s11 = unsafe { setzero() };
296
297        let mut chunks = input.chunks_exact(128);
298
299        for chunk in chunks.by_ref() {
300
301            unsafe {
302
303                let bl_a = &chunk[..64];
304                let bl_b = &chunk[64..];
305
306                let ymm_a1 = loadu(bl_a.as_ptr() as *const __m256i);
307                let ymm_a2 = xor(loadu(bl_a.as_ptr().add(32) as *const __m256i), setone_i32(0x517CC1B7));
308
309                teq_direct!(s0, s1, 7, 25,   ymm_a1);
310                teq_direct!(s1, s2, 31, 28,  ymm_a2);
311                teq_direct!(s2, s3, 25, 7,   ymm_a1);
312                teq_direct!(s3, s4, 23, 9,   ymm_a2);
313                teq_direct!(s4, s5, 13, 19,  ymm_a1);
314                teq_direct!(s5, s6, 29, 3,   ymm_a2);
315                teq_direct!(s6, s7, 19, 13,  ymm_a1);
316                teq_direct!(s7, s8, 17, 15,  ymm_a2);
317                teq_direct!(s8, s9, 11, 21,  ymm_a1);
318                teq_direct!(s9, s10, 5, 27,  ymm_a2);
319                teq_direct!(s10, s11, 3, 29, ymm_a1);
320                teq_direct!(s11, s0, 2, 30,  ymm_a2);
321
322                let ymm_b1 = loadu(bl_b.as_ptr() as *const __m256i);
323                let ymm_b2 = xor(loadu(bl_b.as_ptr().add(32) as *const __m256i), setone_i32(0x517CC1B7));
324
325                teq_direct!(s0, s1, 7, 25,   ymm_b1);
326                teq_direct!(s1, s2, 31, 28,  ymm_b2);
327                teq_direct!(s2, s3, 25, 7,   ymm_b1);
328                teq_direct!(s3, s4, 23, 9,   ymm_b2);
329                teq_direct!(s4, s5, 13, 19,  ymm_b1);
330                teq_direct!(s5, s6, 29, 3,   ymm_b2);
331                teq_direct!(s6, s7, 19, 13,  ymm_b1);
332                teq_direct!(s7, s8, 17, 15,  ymm_b2);
333                teq_direct!(s8, s9, 11, 21,  ymm_b1);
334                teq_direct!(s9, s10, 5, 27,  ymm_b2);
335                teq_direct!(s10, s11, 3, 29, ymm_b1);
336                teq_direct!(s11, s0, 2, 30,  ymm_b2);
337
338                s0 = xor(s0, s11);
339
340            }
341
342        }
343
344
345        unsafe {
346            self.states[0]  = self.states[0] .wrapping_add(horiz_add_avx2(s0));
347            self.states[1]  = self.states[1] .wrapping_add(horiz_add_avx2(s1));
348            self.states[2]  = self.states[2] .wrapping_add(horiz_add_avx2(s2));
349            self.states[3]  = self.states[3] .wrapping_add(horiz_add_avx2(s3));
350            self.states[4]  = self.states[4] .wrapping_add(horiz_add_avx2(s4));
351            self.states[5]  = self.states[5] .wrapping_add(horiz_add_avx2(s5));
352            self.states[6]  = self.states[6] .wrapping_add(horiz_add_avx2(s6));
353            self.states[7]  = self.states[7] .wrapping_add(horiz_add_avx2(s7));
354            self.states[8]  = self.states[8] .wrapping_add(horiz_add_avx2(s8));
355            self.states[9]  = self.states[9] .wrapping_add(horiz_add_avx2(s9));
356            self.states[10] = self.states[10].wrapping_add(horiz_add_avx2(s10));
357            self.states[11] = self.states[11].wrapping_add(horiz_add_avx2(s11));
358        }
359
360
361        let remainder = chunks.remainder();
362        
363        for (idx, &byte) in remainder.iter().enumerate() {
364            let pos = idx % 12;
365            self.states[pos] = self.states[pos].wrapping_add((byte as u32) ^ 0x9E3779B1);
366        }
367
368        self.apply_final_mixer_64();
369        
370        let mut bytes = [0u8; 48];
371
372        for (i, &val) in self.states.iter().enumerate() {
373            let b = val.to_be_bytes();
374            bytes[i*4 .. i*4+4].copy_from_slice(&b);
375        }
376
377        bytes
378    }
379
380
381
382    /// Verifies if a given hash matches the original input data.
383    ///
384    /// This is a convenience function that re-hashes the provided `input` 
385    /// and performs a comparison against the existing `hash` string.
386    ///
387    /// # Security
388    /// The verification process leverages the TQL-11 SIMD engine to ensure 
389    /// high-speed integrity checks. It is ideal for verifying file integrity 
390    /// or checking stored credentials.
391    ///
392    /// # Arguments
393    /// * `hash` - The pre-computed hexadecimal hash string to be verified.
394    /// * `input` - The raw bytes (`&[u8]`) of the data to check.
395    ///
396    /// # Returns
397    /// Returns `true` if the re-computed hash matches the provided one, `false` otherwise.
398    ///
399    /// # Example
400    /// ```rust
401    /// use tequel::hash::TequelHash;
402    /// 
403    /// let mut tequel = TequelHash::new();
404    /// let data = b"secret_message";
405    /// let hash = tequel.tqlhash(data);
406    ///
407    /// if tequel.isv_tqlhash(&hash, data) {
408    ///     println!("Integrity verified: VALID!");
409    /// } else {
410    ///     println!("Integrity compromised: NOT VALID!");
411    /// }
412    /// ```
413    pub fn isv_tqlhash(&mut self, hash: &String, input: &[u8]) -> bool {
414        
415        let mut prop_tequel = TequelHash::new()
416            .with_salt(&self.salt)
417            .with_iteration(self.iterations);
418
419        let new_hash = prop_tequel.tqlhash(input);
420
421        let a = new_hash.as_bytes();
422        let b = hash.as_bytes();
423
424        if a.len() != b.len() {
425            return false;
426        }
427
428        let mut result = 0u8;
429        for i in 0..a.len() {
430            result |= a[i] ^ b[i];
431        }
432
433        result == 0
434
435    }
436
437
438
439    /// Derives a high-entropy cryptographic key from a password and a salt.
440    ///
441    /// This function implements a **Key Derivation Function (KDF)** powered by the TQL-11 engine.
442    /// It utilizes a "Key Stretching" mechanism to make brute-force and dictionary attacks 
443    /// computationally expensive.
444    ///
445    /// # Architecture
446    /// The process is **SIMD-accelerated (AVX2)**, ensuring that the computational cost 
447    /// remains high for attackers (who must replicate the intensive TQL-11 rounds) while 
448    /// staying efficient for legitimate local use. Every iteration triggers a non-linear 
449    /// mutation with a validated 51% avalanche diffusion.
450    ///
451    /// # Arguments
452    /// * `password` - The raw bytes of the master password (e.g., from user input).
453    /// * `salt` - A unique, random value used to prevent Rainbow Table attacks.
454    /// * `iterations` - The number of hashing rounds. Higher values increase resistance 
455    ///   against GPU-accelerated cracking (Recommended: >1000).
456    ///
457    /// # Returns
458    /// A 384-bit hexadecimal `String` representing the derived cryptographic key.
459    ///
460    /// # Example
461    /// ```rust
462    /// use tequel::hash::TequelHash;
463    /// 
464    /// fn main() {
465    ///     let mut teq = TequelHash::new();
466    ///     let key = teq.derive_key("master_password_123", 2048);
467    ///     println!("Derived Key: {:?}", key);
468    /// }
469    /// ```
470    pub fn derive_key(&mut self, password: &str, iterations: u32) -> [u8; 32] {
471
472        self.iterations = if iterations > 0 { iterations } else { 30 };
473
474        let mut derived = format!("{}{}{}", self.salt, password, self.salt);
475
476        for i in 0..self.iterations {
477            let hash_hex = self.tqlhash(derived.as_bytes());
478            derived = format!("{}{}{}", i, hash_hex, self.salt);
479        }
480
481        let final_hash = self.tqlhash(derived.as_bytes());
482        let bytes = hex::decode(&final_hash).expect("Error in key closing");
483
484        let mut key = [0u8; 32];
485        key.copy_from_slice(&bytes[0..32]);
486        key
487    }
488
489
490
491    fn apply_final_mixer_64(&mut self) {
492        for r in 0..64 {
493            for i in 0..12 {
494                let prev = if i == 0 { 11 } else { i - 1 };
495                let next = (i + 1) % 12;
496
497                self.states[i] = self.states[i]
498                    .wrapping_add(self.states[prev])
499                    .rotate_left(((r % 31) as u32) + 1);
500                self.states[next] ^= self.states[i].wrapping_mul(0xAD35744D);
501            }
502        }
503    }
504
505}