SHARAG256 0.1.0

A custom hashing algorithm with complex random number generation based on SHA-256 principles
Documentation
//! A custom hashing algorithm with complex random number generation.
//!
//! This library provides a modified SHA-256-like hashing algorithm with additional
//! processing steps including byte flipping and shifting operations.
//!
//! # Examples
//!
//! ```
//! use SHARAG256::patentmethod;
//!
//! let message = "Hello, world!";
//! let hash = patentmethod(message);
//! println!("Hash: {}", hash);
//! ```

use std::f64;

const K: [u32; 64] = [
    0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
    0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
    0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
    0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
    0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
    0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
    0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
    0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
];

/// Generates a complex random number based on input data.
///
/// # Arguments
///
/// * `input_data` - Input bytes, byte array, or string
///
/// # Returns
///
/// An integer between 0 and 999,999
fn generate_complex_random_number3(input_data: &[u8]) -> u64 {
    let input_string = String::from_utf8_lossy(input_data);
    
    // Fix: Use char-based truncation instead of byte slicing
    let input_string = if input_string.chars().count() > 15 {
        input_string.chars().take(15).collect::<String>()
    } else {
        input_string.to_string()
    };

    let ascii_values: Vec<u32> = input_string.chars().map(|c| c as u32).collect();

    // Handle empty input
    if ascii_values.is_empty() {
        return 123456; // Fixed seed for empty string
    }

    let length_of_string = input_string.chars().count() as f64;
    let sum_ascii: f64 = ascii_values.iter().map(|&x| x as f64).sum();
    let max_ascii = *ascii_values.iter().max().unwrap() as f64;
    let min_ascii = *ascii_values.iter().min().unwrap() as f64;

    // Calculate factorial (limited to 10)
    let factorial_limit = length_of_string.min(10.0) as u64;
    let mut factorial = 1u64;
    for i in 1..=factorial_limit {
        factorial = factorial.saturating_mul(i); // Prevent overflow
    }

    // Calculate sum of squares
    let sum_of_squares: f64 = ascii_values.iter().map(|&x| (x as f64).powi(2)).sum();

    let result = sum_ascii.sin()
        + length_of_string.exp()
        + max_ascii.tan()
        + (length_of_string + 1e-10).ln()
        + min_ascii.abs().sqrt()
        + factorial as f64
        + sum_of_squares
        - f64::atan2(length_of_string, max_ascii)
        + length_of_string.cosh()
        + gamma(length_of_string + 1.0);

    (result.abs() as u64) % 1_000_000
}
/// Approximation of the gamma function using Stirling's formula
fn gamma(x: f64) -> f64 {
    if x < 0.5 {
        std::f64::consts::PI / ((std::f64::consts::PI * x).sin() * gamma(1.0 - x))
    } else {
        let x = x - 1.0;
        let p = [
            0.99999999999980993,
            676.5203681218851,
            -1259.1392167224028,
            771.32342877765313,
            -176.61502916214059,
            12.507343278686905,
            -0.13857109526572012,
            9.9843695780195716e-6,
            1.5056327351493116e-7,
        ];
        let mut y = p[0];
        for (i, &pi) in p.iter().enumerate().skip(1) {
            y += pi / (x + i as f64);
        }
        let t = x + 7.5;
        (2.0 * std::f64::consts::PI).sqrt() * t.powf(x + 0.5) * (-t).exp() * y
    }
}

/// Right rotate a 32-bit value
#[inline(always)]
fn right_rotate(x: u32, amount: u32) -> u32 {
    (x >> amount) | (x << (32 - amount))
}

/// Process a single 64-byte chunk
fn process_chunk(mut chunk: Vec<u8>, h_values: &mut [u32; 8]) {
    // Flip bytes at even positions
    for (i, byte) in chunk.iter_mut().enumerate() {
        if i % 2 == 0 {
            *byte ^= 0xFF;
        }
    }

    // Shift each byte 5 bits to the right (with wraparound)
    for byte in chunk.iter_mut() {
        *byte = (*byte >> 5) | ((*byte << 3) & 0xFF);
    }

    // Prepare message schedule
    let mut w = [0u32; 64];
    for i in 0..16 {
        w[i] = u32::from_be_bytes([
            chunk[i * 4],
            chunk[i * 4 + 1],
            chunk[i * 4 + 2],
            chunk[i * 4 + 3],
        ]);
    }

    for i in 16..64 {
        let s0 = right_rotate(w[i - 15], 7) ^ right_rotate(w[i - 15], 18) ^ (w[i - 15] >> 3);
        let s1 = right_rotate(w[i - 2], 17) ^ right_rotate(w[i - 2], 19) ^ (w[i - 2] >> 10);
        w[i] = w[i - 16]
            .wrapping_add(s0)
            .wrapping_add(w[i - 7])
            .wrapping_add(s1);
    }

    // Initialize working variables
    let mut a = h_values[0];
    let mut b = h_values[1];
    let mut c = h_values[2];
    let mut d = h_values[3];
    let mut e = h_values[4];
    let mut f = h_values[5];
    let mut g = h_values[6];
    let mut h = h_values[7];

    // Main compression loop
    for i in 0..64 {
        let s1 = right_rotate(e, 6) ^ right_rotate(e, 11) ^ right_rotate(e, 25);
        let ch = (e & f) ^ ((!e) & g);
        let temp1 = h
            .wrapping_add(s1)
            .wrapping_add(ch)
            .wrapping_add(K[i])
            .wrapping_add(w[i]);
        let s0 = right_rotate(a, 2) ^ right_rotate(a, 13) ^ right_rotate(a, 22);
        let maj = (a & b) ^ (a & c) ^ (b & c);
        let temp2 = s0.wrapping_add(maj);

        h = g;
        g = f;
        f = e;
        e = d.wrapping_add(temp1);
        d = c;
        c = b;
        b = a;
        a = temp1.wrapping_add(temp2);
    }

    // Update hash values
    h_values[0] = h_values[0].wrapping_add(a);
    h_values[1] = h_values[1].wrapping_add(b);
    h_values[2] = h_values[2].wrapping_add(c);
    h_values[3] = h_values[3].wrapping_add(d);
    h_values[4] = h_values[4].wrapping_add(e);
    h_values[5] = h_values[5].wrapping_add(f);
    h_values[6] = h_values[6].wrapping_add(g);
    h_values[7] = h_values[7].wrapping_add(h);
}

/// Main hashing function implementing the patent method.
///
/// # Arguments
///
/// * `message` - The input message to hash (can be String, &str, or bytes)
///
/// # Returns
///
/// A 64-character hexadecimal hash string
///
/// # Examples
///
/// ```
/// use SHARAG256::patentmethod;
///
/// let hash = patentmethod("Hello, world!");
/// assert_eq!(hash.len(), 64);
/// ```
pub fn patentmethod(message: &str) -> String {
    // Initial hash values (SHA-256 standard)
    let mut h_values = [
        0x6A09E667u32,
        0xBB67AE85,
        0x3C6EF372,
        0xA54FF53A,
        0x510E527F,
        0x9B05688C,
        0x1F83D9AB,
        0x5BE0CD19,
    ];

    let mut message_bytes = message.as_bytes().to_vec();
    let original_length = (message_bytes.len() * 8) as u64;

    // Add padding bit
    message_bytes.push(0x80);

    // Handle empty message edge case
    if message_bytes.len() == 1 {
        message_bytes.extend_from_slice(&[0u8; 55]);
    }

    // Add random value (6 bytes)
    let random_value = generate_complex_random_number3(&message_bytes);
    message_bytes.extend_from_slice(&random_value.to_be_bytes()[2..8]); // Last 6 bytes

    // Pad to 56 bytes mod 64
    while message_bytes.len() % 64 != 56 {
        message_bytes.push(0);
    }

    // Append original length (8 bytes, big-endian)
    message_bytes.extend_from_slice(&original_length.to_be_bytes());

    // Process chunks
    for chunk_start in (0..message_bytes.len()).step_by(64) {
        let chunk = message_bytes[chunk_start..chunk_start + 64].to_vec();
        process_chunk(chunk, &mut h_values);
    }

    // Produce final hash
    format!(
        "{:08x}{:08x}{:08x}{:08x}{:08x}{:08x}{:08x}{:08x}",
        h_values[0],
        h_values[1],
        h_values[2],
        h_values[3],
        h_values[4],
        h_values[5],
        h_values[6],
        h_values[7]
    )
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_hash() {
        let message = "Hello, world!";
        let hash = patentmethod(message);
        assert_eq!(hash.len(), 64);
        // Verify it produces consistent output
        let hash2 = patentmethod(message);
        assert_eq!(hash, hash2);
    }

    #[test]
    fn test_empty_string() {
        let hash = patentmethod("");
        assert_eq!(hash.len(), 64);
    }

    #[test]
    fn test_long_message() {
        let message = "anantehucnjldsnciejur380480-2=@#459mo-dlsanantehucnjldsnciejur380480-2=@#459mo-dlsgauranshi003003lavyabirthdayllllllllllanantehucnjldsnciejur380480-2=@#459mo-dlsanantehucnjldsnciejur380480-2=@#459mo-dlsgauranshi003003lavyabirthdayllllllllll";
        let hash = patentmethod(message);
        assert_eq!(hash.len(), 64);
    }

    #[test]
    fn test_complex_random_number() {
        let input = b"test";
        let num = generate_complex_random_number3(input);
        assert!(num < 1_000_000);
    }

    #[test]
    fn test_different_inputs_different_hashes() {
        let hash1 = patentmethod("test1");
        let hash2 = patentmethod("test2");
        assert_ne!(hash1, hash2);
    }
}