Skip to main content

patent_hash/
lib.rs

1//! A custom hashing algorithm with complex random number generation.
2//!
3//! This library provides a modified SHA-256-like hashing algorithm with additional
4//! processing steps including byte flipping and shifting operations.
5//!
6//! # Examples
7//!
8//! ```
9//! use patent_hash::patentmethod;
10//!
11//! let message = "Hello, world!";
12//! let hash = patentmethod(message);
13//! println!("Hash: {}", hash);
14//! ```
15
16use std::f64;
17
18const K: [u32; 64] = [
19    0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
20    0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
21    0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
22    0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
23    0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
24    0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
25    0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
26    0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
27];
28
29/// Generates a complex random number based on input data.
30///
31/// # Arguments
32///
33/// * `input_data` - Input bytes, byte array, or string
34///
35/// # Returns
36///
37/// An integer between 0 and 999,999
38fn generate_complex_random_number3(input_data: &[u8]) -> u64 {
39    let input_string = String::from_utf8_lossy(input_data);
40    
41    // Fix: Use char-based truncation instead of byte slicing
42    let input_string = if input_string.chars().count() > 15 {
43        input_string.chars().take(15).collect::<String>()
44    } else {
45        input_string.to_string()
46    };
47
48    let ascii_values: Vec<u32> = input_string.chars().map(|c| c as u32).collect();
49
50    // Handle empty input
51    if ascii_values.is_empty() {
52        return 123456; // Fixed seed for empty string
53    }
54
55    let length_of_string = input_string.chars().count() as f64;
56    let sum_ascii: f64 = ascii_values.iter().map(|&x| x as f64).sum();
57    let max_ascii = *ascii_values.iter().max().unwrap() as f64;
58    let min_ascii = *ascii_values.iter().min().unwrap() as f64;
59
60    // Calculate factorial (limited to 10)
61    let factorial_limit = length_of_string.min(10.0) as u64;
62    let mut factorial = 1u64;
63    for i in 1..=factorial_limit {
64        factorial = factorial.saturating_mul(i); // Prevent overflow
65    }
66
67    // Calculate sum of squares
68    let sum_of_squares: f64 = ascii_values.iter().map(|&x| (x as f64).powi(2)).sum();
69
70    let result = sum_ascii.sin()
71        + length_of_string.exp()
72        + max_ascii.tan()
73        + (length_of_string + 1e-10).ln()
74        + min_ascii.abs().sqrt()
75        + factorial as f64
76        + sum_of_squares
77        - f64::atan2(length_of_string, max_ascii)
78        + length_of_string.cosh()
79        + gamma(length_of_string + 1.0);
80
81    (result.abs() as u64) % 1_000_000
82}
83/// Approximation of the gamma function using Stirling's formula
84fn gamma(x: f64) -> f64 {
85    if x < 0.5 {
86        std::f64::consts::PI / ((std::f64::consts::PI * x).sin() * gamma(1.0 - x))
87    } else {
88        let x = x - 1.0;
89        let p = [
90            0.99999999999980993,
91            676.5203681218851,
92            -1259.1392167224028,
93            771.32342877765313,
94            -176.61502916214059,
95            12.507343278686905,
96            -0.13857109526572012,
97            9.9843695780195716e-6,
98            1.5056327351493116e-7,
99        ];
100        let mut y = p[0];
101        for (i, &pi) in p.iter().enumerate().skip(1) {
102            y += pi / (x + i as f64);
103        }
104        let t = x + 7.5;
105        (2.0 * std::f64::consts::PI).sqrt() * t.powf(x + 0.5) * (-t).exp() * y
106    }
107}
108
109/// Right rotate a 32-bit value
110#[inline(always)]
111fn right_rotate(x: u32, amount: u32) -> u32 {
112    (x >> amount) | (x << (32 - amount))
113}
114
115/// Process a single 64-byte chunk
116fn process_chunk(mut chunk: Vec<u8>, h_values: &mut [u32; 8]) {
117    // Flip bytes at even positions
118    for (i, byte) in chunk.iter_mut().enumerate() {
119        if i % 2 == 0 {
120            *byte ^= 0xFF;
121        }
122    }
123
124    // Shift each byte 5 bits to the right (with wraparound)
125    for byte in chunk.iter_mut() {
126        *byte = (*byte >> 5) | ((*byte << 3) & 0xFF);
127    }
128
129    // Prepare message schedule
130    let mut w = [0u32; 64];
131    for i in 0..16 {
132        w[i] = u32::from_be_bytes([
133            chunk[i * 4],
134            chunk[i * 4 + 1],
135            chunk[i * 4 + 2],
136            chunk[i * 4 + 3],
137        ]);
138    }
139
140    for i in 16..64 {
141        let s0 = right_rotate(w[i - 15], 7) ^ right_rotate(w[i - 15], 18) ^ (w[i - 15] >> 3);
142        let s1 = right_rotate(w[i - 2], 17) ^ right_rotate(w[i - 2], 19) ^ (w[i - 2] >> 10);
143        w[i] = w[i - 16]
144            .wrapping_add(s0)
145            .wrapping_add(w[i - 7])
146            .wrapping_add(s1);
147    }
148
149    // Initialize working variables
150    let mut a = h_values[0];
151    let mut b = h_values[1];
152    let mut c = h_values[2];
153    let mut d = h_values[3];
154    let mut e = h_values[4];
155    let mut f = h_values[5];
156    let mut g = h_values[6];
157    let mut h = h_values[7];
158
159    // Main compression loop
160    for i in 0..64 {
161        let s1 = right_rotate(e, 6) ^ right_rotate(e, 11) ^ right_rotate(e, 25);
162        let ch = (e & f) ^ ((!e) & g);
163        let temp1 = h
164            .wrapping_add(s1)
165            .wrapping_add(ch)
166            .wrapping_add(K[i])
167            .wrapping_add(w[i]);
168        let s0 = right_rotate(a, 2) ^ right_rotate(a, 13) ^ right_rotate(a, 22);
169        let maj = (a & b) ^ (a & c) ^ (b & c);
170        let temp2 = s0.wrapping_add(maj);
171
172        h = g;
173        g = f;
174        f = e;
175        e = d.wrapping_add(temp1);
176        d = c;
177        c = b;
178        b = a;
179        a = temp1.wrapping_add(temp2);
180    }
181
182    // Update hash values
183    h_values[0] = h_values[0].wrapping_add(a);
184    h_values[1] = h_values[1].wrapping_add(b);
185    h_values[2] = h_values[2].wrapping_add(c);
186    h_values[3] = h_values[3].wrapping_add(d);
187    h_values[4] = h_values[4].wrapping_add(e);
188    h_values[5] = h_values[5].wrapping_add(f);
189    h_values[6] = h_values[6].wrapping_add(g);
190    h_values[7] = h_values[7].wrapping_add(h);
191}
192
193/// Main hashing function implementing the patent method.
194///
195/// # Arguments
196///
197/// * `message` - The input message to hash (can be String, &str, or bytes)
198///
199/// # Returns
200///
201/// A 64-character hexadecimal hash string
202///
203/// # Examples
204///
205/// ```
206/// use patent_hash::patentmethod;
207///
208/// let hash = patentmethod("Hello, world!");
209/// assert_eq!(hash.len(), 64);
210/// ```
211pub fn patentmethod(message: &str) -> String {
212    // Initial hash values (SHA-256 standard)
213    let mut h_values = [
214        0x6A09E667u32,
215        0xBB67AE85,
216        0x3C6EF372,
217        0xA54FF53A,
218        0x510E527F,
219        0x9B05688C,
220        0x1F83D9AB,
221        0x5BE0CD19,
222    ];
223
224    let mut message_bytes = message.as_bytes().to_vec();
225    let original_length = (message_bytes.len() * 8) as u64;
226
227    // Add padding bit
228    message_bytes.push(0x80);
229
230    // Handle empty message edge case
231    if message_bytes.len() == 1 {
232        message_bytes.extend_from_slice(&[0u8; 55]);
233    }
234
235    // Add random value (6 bytes)
236    let random_value = generate_complex_random_number3(&message_bytes);
237    message_bytes.extend_from_slice(&random_value.to_be_bytes()[2..8]); // Last 6 bytes
238
239    // Pad to 56 bytes mod 64
240    while message_bytes.len() % 64 != 56 {
241        message_bytes.push(0);
242    }
243
244    // Append original length (8 bytes, big-endian)
245    message_bytes.extend_from_slice(&original_length.to_be_bytes());
246
247    // Process chunks
248    for chunk_start in (0..message_bytes.len()).step_by(64) {
249        let chunk = message_bytes[chunk_start..chunk_start + 64].to_vec();
250        process_chunk(chunk, &mut h_values);
251    }
252
253    // Produce final hash
254    format!(
255        "{:08x}{:08x}{:08x}{:08x}{:08x}{:08x}{:08x}{:08x}",
256        h_values[0],
257        h_values[1],
258        h_values[2],
259        h_values[3],
260        h_values[4],
261        h_values[5],
262        h_values[6],
263        h_values[7]
264    )
265}
266
267#[cfg(test)]
268mod tests {
269    use super::*;
270
271    #[test]
272    fn test_basic_hash() {
273        let message = "Hello, world!";
274        let hash = patentmethod(message);
275        assert_eq!(hash.len(), 64);
276        // Verify it produces consistent output
277        let hash2 = patentmethod(message);
278        assert_eq!(hash, hash2);
279    }
280
281    #[test]
282    fn test_empty_string() {
283        let hash = patentmethod("");
284        assert_eq!(hash.len(), 64);
285    }
286
287    #[test]
288    fn test_long_message() {
289        let message = "anantehucnjldsnciejur380480-2=@#459mo-dlsanantehucnjldsnciejur380480-2=@#459mo-dlsgauranshi003003lavyabirthdayllllllllllanantehucnjldsnciejur380480-2=@#459mo-dlsanantehucnjldsnciejur380480-2=@#459mo-dlsgauranshi003003lavyabirthdayllllllllll";
290        let hash = patentmethod(message);
291        assert_eq!(hash.len(), 64);
292    }
293
294    #[test]
295    fn test_complex_random_number() {
296        let input = b"test";
297        let num = generate_complex_random_number3(input);
298        assert!(num < 1_000_000);
299    }
300
301    #[test]
302    fn test_different_inputs_different_hashes() {
303        let hash1 = patentmethod("test1");
304        let hash2 = patentmethod("test2");
305        assert_ne!(hash1, hash2);
306    }
307}