The first construct for Cryptix Messenger encryption already exists. The encryption will also be used for future modules, wherever data protection and security are relevant. Please note that this is a simple, basic version so developers can work on it. The SHA256 usage is also just a placeholder; this will be replaced later with a custom version of our Cryptix OX8 hash.




// main.rs @Cryptis
/*
* This code deliberately uses a 64-bit key length to comply with legal regulations
* and reporting requirements for strong cryptography (128-bit symmetric security and above).
@ TODO:
- Use the midstate as part of a real secret key, not just derived from a publicly known string.
- Logging not sufficient
- Exchange Sha3 with Cryptix OX8 Light
- Prepare conversation_id and message_id for dynamic unkown input
- Shor resistance
@V.1.0
-Template created
@V.1.1
- Quantum Security Explanation
This encryption scheme leverages the SHA-256 midstate — the internal hash state after half of the compression rounds — as a secret, fixed “password” derived from the conversation_id. By combining this midstate with a random nonce and a message_id, the key derivation function creates a large, high-entropy key space.
Traditional PoW systems or symmetric keys typically rely on 32- or 64-bit nonces, limiting the search space. Here, the effective search space expands to roughly 2^160 due to the 128-bit midstate entropy plus the 32-bit nonce.
Against quantum attacks using Grover’s algorithm (which offers a quadratic speedup), the complexity becomes approximately 2^80 operations — far beyond the reach of foreseeable quantum computers.
Thus, the design inherently increases resistance to quantum brute-force attacks without sacrificing performance or requiring new cryptographic primitives, making your implementation effectively quantum-resistant.
@V.1.1.1
- Protection features and AI interface for DDOS attacks, payloads and other attacks.
@V.1.2
- Added protection against Timing Attacks
- Added protection against side-channel attacks (not complete)
- High-entropy 16-byte nonce from random, timestamp, and device ID
- Addet Timing Attack Test
V.1.3
- Replay Functions
- ASVS Level 3 compliant - ASVS 3.8.1–3.9.1
- ASVS Level 3 Error handling
V.1.4
- X25519 Key Exchange
- Shared Secret
- Ephemeral Keys Forward Secrecy
V1.5
- Adds dynamic low level noise padding before and after ciphertext
*/
// main.rs
extern crate hmac;
extern crate sha2;
extern crate base64;
extern crate rand;
extern crate bitcoin_hashes;
extern crate hkdf;
extern crate tracing;
extern crate tracing_subscriber;
extern crate subtle;
extern crate x25519_dalek;
extern crate rand_core;
use hmac::{Hmac, Mac};
use sha2::{Sha256, Digest};
use base64::engine::general_purpose::STANDARD;
use base64::Engine;
use rand::Rng;
use std::time::Instant;
use std::time::{SystemTime, UNIX_EPOCH};
mod replay_guard;
use replay_guard::is_replay;
use subtle::ConstantTimeEq;
mod ai_guard;
use ai_guard::protected_decrypt;
use bitcoin_hashes::sha256::{HashEngine as Sha256Engine, Midstate};
use bitcoin_hashes::HashEngine;
use hkdf::Hkdf;
use tracing::{info, error};
use hex;
use x25519_dalek::{EphemeralSecret, PublicKey};
use rand::rngs::OsRng;
type HmacSha256 = Hmac;
#[derive(Debug)]
enum DecryptError {
ReplayDetected,
InvalidBase64,
CiphertextTooShort,
HmacVerificationFailed,
InvalidUtf8,
}
// Generate an ephemeral X25519 keypair
fn generate_keypair() -> (EphemeralSecret, PublicKey) {
let secret = EphemeralSecret::random_from_rng(OsRng);
let public = PublicKey::from(&secret);
(secret, public)
}
// Compute a shared secret using private key and peer's public key
fn compute_shared_secret(secret: EphemeralSecret, peer_public: &PublicKey) -> [u8; 32] {
secret.diffie_hellman(peer_public).to_bytes()
}
// Generate midstate hash from input (used as salt)
fn generate_midstate(data: &[u8]) -> Midstate {
let mut engine = Sha256Engine::default();
engine.input(data);
engine.midstate()
}
// Create 16-byte nonce using random data, timestamp, and device ID
fn generate_nonce() -> [u8; 16] {
let mut rng = rand::thread_rng();
let mut random_bytes = [0u8; 16];
rng.fill(&mut random_bytes);
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_nanos()
.to_be_bytes();
let device_id = b"CryptixDevice42";
let mut entropy_source = Vec::with_capacity(16 + 16 + 16);
entropy_source.extend_from_slice(&random_bytes);
entropy_source.extend_from_slice(×tamp[..16.min(timestamp.len())]);
entropy_source.extend_from_slice(device_id);
let mut hasher = Sha256::new();
hasher.update(&entropy_source);
let hash = hasher.finalize();
let mut nonce = [0u8; 16];
nonce.copy_from_slice(&hash[..16]);
nonce
}
// Derive an 8-byte encryption key using HKDF
fn derive_key(message_id: &str, midstate: &Midstate, nonce: &[u8], secret: &[u8]) -> [u8; 8] {
let salt = midstate.into_inner();
let info = [message_id.as_bytes(), nonce].concat();
let hk = Hkdf::::new(Some(&salt), secret);
let mut key = [0u8; 8];
hk.expand(&info, &mut key).expect("HKDF expand failed");
key
}
// Stream cipher based on SHA256 as keystream generator
pub fn stream_cipher(data: &[u8], mut key: [u8; 8], nonce: &[u8]) -> Vec {
let mut result = Vec::with_capacity(data.len());
let mut counter: u64 = 0;
let mut prev_keystream = [0u8; 32];
for chunk in data.chunks(32) {
if counter > 0 && counter % 1024 == 0 {
let mut rekey_hasher = Sha256::new();
rekey_hasher.update(&key);
rekey_hasher.update(nonce);
rekey_hasher.update(counter.to_be_bytes());
let new_key = rekey_hasher.finalize();
key.copy_from_slice(&new_key[..8]);
}
let mut hasher = Sha256::new();
hasher.update(&key);
hasher.update(nonce);
hasher.update(counter.to_be_bytes());
hasher.update(&prev_keystream);
let keystream = hasher.finalize();
let mut output_block = Vec::with_capacity(chunk.len());
for (i, &b) in chunk.iter().enumerate() {
output_block.push(b ^ keystream[i]);
}
result.extend_from_slice(&output_block);
prev_keystream.copy_from_slice(&keystream);
counter += 1;
}
result
}
// Generate HMAC-SHA256 authentication tag
fn hmac_auth(data: &[u8], key: &[u8]) -> Vec {
let mut hmac = HmacSha256::new_from_slice(key).expect("HMAC requires a key");
hmac.update(data);
hmac.finalize().into_bytes().to_vec()
}
// Adds dynamic noise padding before and after ciphertext
fn add_noise_padding(ciphertext: &[u8]) -> Vec {
let mut rng = rand::thread_rng();
let prefix_len = rng.gen_range(8..=64);
let suffix_len = rng.gen_range(8..=64);
let mut padded = Vec::with_capacity(3 + prefix_len + ciphertext.len() + suffix_len);
let original_len = (ciphertext.len() as u16).to_be_bytes();
padded.extend_from_slice(&original_len);
padded.push(prefix_len as u8);
// Prefix noise
let mut prefix_noise = vec![0u8; prefix_len];
rng.fill(&mut prefix_noise[..]);
padded.extend(prefix_noise);
// Ciphertext
padded.extend_from_slice(ciphertext);
// Suffix noise
let mut suffix_noise = vec![0u8; suffix_len];
rng.fill(&mut suffix_noise[..]);
padded.extend(suffix_noise);
padded
}
// Removes dynamic padding
fn remove_noise_padding(padded: &[u8]) -> Option> {
if padded.len() < 3 {
return None;
}
let original_len = u16::from_be_bytes([padded[0], padded[1]]) as usize;
let prefix_len = padded[2] as usize;
if padded.len() < 3 + prefix_len + original_len {
return None;
}
let start = 3 + prefix_len;
let end = start + original_len;
Some(padded[start..end].to_vec())
}
// Encrypt message, return base64-encoded output
fn quantum_encrypt(input: &str, conversation_id: &str, message_id: &str, secret: &[u8]) -> String {
let midstate = generate_midstate(conversation_id.as_bytes());
let nonce = generate_nonce();
let key = derive_key(message_id, &midstate, &nonce, secret);
let plaintext = input.as_bytes();
let ciphertext = stream_cipher(plaintext, key, &nonce);
let padded_ciphertext = add_noise_padding(&ciphertext);
let tag = hmac_auth(&padded_ciphertext, &key);
let mut output = Vec::new();
output.extend_from_slice(&nonce);
output.extend_from_slice(&padded_ciphertext);
output.extend_from_slice(&tag);
STANDARD.encode(&output)
}
// Decrypt base64-encoded message and validate
fn quantum_decrypt(
encoded: &str,
conversation_id: &str,
message_id: &str,
secret: &[u8],
) -> Result {
if is_replay(conversation_id, message_id) {
return Err(DecryptError::ReplayDetected);
}
let decoded = STANDARD.decode(encoded).map_err(|_| DecryptError::InvalidBase64)?;
if decoded.len() < 48 {
return Err(DecryptError::CiphertextTooShort);
}
let (nonce, rest) = decoded.split_at(16);
let (padded_ciphertext, tag) = rest.split_at(rest.len() - 32);
let midstate = generate_midstate(conversation_id.as_bytes());
let key = derive_key(message_id, &midstate, nonce, secret);
let expected_tag = hmac_auth(padded_ciphertext, &key);
if expected_tag.ct_eq(tag).unwrap_u8() != 1 {
return Err(DecryptError::HmacVerificationFailed);
}
let ciphertext = remove_noise_padding(padded_ciphertext)
.ok_or(DecryptError::CiphertextTooShort)?;
let decrypted = stream_cipher(&ciphertext, key, nonce);
String::from_utf8(decrypted).map_err(|_| DecryptError::InvalidUtf8)
}
fn main() {
tracing_subscriber::fmt::init();
let (alice_secret, alice_public) = generate_keypair();
let (bob_secret, bob_public) = generate_keypair();
let alice_shared_secret = compute_shared_secret(alice_secret, &bob_public);
let bob_shared_secret = compute_shared_secret(bob_secret, &alice_public);
assert_eq!(alice_shared_secret, bob_shared_secret);
let message = "Hello Cryptix! 🧠🔐";
let conversation_id = "CONV-ALPHA-007";
let message_id = "MSG-QUANTUM-TEST-42";
info!("Shared Secret: {}", hex::encode(alice_shared_secret));
let start_enc = Instant::now();
let encrypted = quantum_encrypt(message, conversation_id, message_id, &alice_shared_secret);
let duration_enc = start_enc.elapsed();
info!("Encrypted (Base64): {}", encrypted);
info!("Encryption took: {:.3?}", duration_enc);
let classical_bits = 256;
let quantum_bits = classical_bits / 2;
let estimated_classical_seconds = 2f64.powi(classical_bits as i32) * duration_enc.as_secs_f64();
let estimated_quantum_seconds = 2f64.powi(quantum_bits as i32) * duration_enc.as_secs_f64();
info!("Estimated brute-force time:");
info!(" - Classical (2^{classical_bits} ops): {:.3e} seconds (~{:.3e} Years)",
estimated_classical_seconds, estimated_classical_seconds / (60.0*60.0*24.0*365.25));
info!(" - Quantum (Grover 2^{quantum_bits} ops): {:.3e} seconds (~{:.3e} Years)",
estimated_quantum_seconds, estimated_quantum_seconds / (60.0*60.0*24.0*365.25));
info!("--- Quantum Decryption Debug ---");
let start_dec = Instant::now();
match protected_decrypt(
message_id,
&STANDARD.decode(&encrypted).unwrap(),
|| quantum_decrypt(&encrypted, conversation_id, message_id, &bob_shared_secret)
.map_err(|e| match e {
DecryptError::ReplayDetected => "Replay detected",
DecryptError::InvalidBase64 => "Invalid base64",
DecryptError::CiphertextTooShort => "Ciphertext too short",
DecryptError::HmacVerificationFailed => "HMAC verification failed",
DecryptError::InvalidUtf8 => "Invalid UTF-8",
}),
) {
Ok(decrypted) => {
let duration_dec = start_dec.elapsed();
info!("Decrypted Message: {}", decrypted);
info!("Decryption took: {:.3?}", duration_dec);
assert_eq!(message, decrypted);
info!("Decryption successful and verified!");
}
Err(e) => error!("Decryption failed: {}", e),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::replay_guard::reset_replay_cache;
use x25519_dalek::{EphemeralSecret, PublicKey};
use rand::rngs::OsRng;
use std::time::Duration;
#[test]
fn test_roundtrip() {
let msg = "Test123!";
let conv = "c1";
let msg_id = "m1";
let secret = b"shared-key";
reset_replay_cache();
let encrypted = quantum_encrypt(msg, conv, msg_id, secret);
let decrypted = quantum_decrypt(&encrypted, conv, msg_id, secret)
.expect("Decryption unexpectedly failed");
assert_eq!(msg, decrypted);
}
#[test]
fn test_hmac_failure() {
let msg = "Test tamper!";
let conv = "c1";
let msg_id = "m1";
let secret = b"shared-key";
let mut enc = quantum_encrypt(msg, conv, msg_id, secret);
let mut bytes = base64::engine::general_purpose::STANDARD.decode(&enc).unwrap();
bytes[20] ^= 0xFF;
enc = base64::engine::general_purpose::STANDARD.encode(&bytes);
assert!(quantum_decrypt(&enc, conv, msg_id, secret).is_err());
}
#[test]
fn test_empty_message() {
let msg = "";
let conv = "conv-empty";
let msg_id = "msg-empty";
let secret = b"empty-secret";
let encrypted = quantum_encrypt(msg, conv, msg_id, secret);
let decrypted = quantum_decrypt(&encrypted, conv, msg_id, secret).unwrap();
assert_eq!(msg, decrypted);
}
#[test]
fn test_different_nonce_produces_different_ciphertext() {
let msg = "NonceTest";
let conv = "conv-nonce";
let msg_id = "msg-nonce";
let secret = b"nonce-key";
let ct1 = quantum_encrypt(msg, conv, msg_id, secret);
let ct2 = quantum_encrypt(msg, conv, msg_id, secret);
assert_ne!(ct1, ct2);
}
#[test]
fn test_wrong_secret_fails() {
let msg = "SecretMismatch!";
let conv = "conv-secret";
let msg_id = "msg-secret";
let correct_secret = b"correct-key";
let wrong_secret = b"wrong-key";
let encrypted = quantum_encrypt(msg, conv, msg_id, correct_secret);
let result = quantum_decrypt(&encrypted, conv, msg_id, wrong_secret);
assert!(result.is_err());
}
#[test]
fn test_wrong_message_id_fails() {
let msg = "WrongMsgID!";
let conv = "conv-wrongid";
let msg_id = "msg-correct";
let wrong_msg_id = "msg-wrong";
let secret = b"key";
let encrypted = quantum_encrypt(msg, conv, msg_id, secret);
let result = quantum_decrypt(&encrypted, conv, wrong_msg_id, secret);
assert!(result.is_err());
}
#[test]
fn test_hmac_tampering_detected() {
let msg = "CTEqTest!";
let conv = "conv-cteq";
let msg_id = "msg-cteq";
let secret = b"secure-key";
let encrypted = quantum_encrypt(msg, conv, msg_id, secret);
let mut decoded = base64::engine::general_purpose::STANDARD.decode(&encrypted).unwrap();
let hmac_offset = decoded.len() - 32;
decoded[hmac_offset] ^= 0xFF;
let tampered = base64::engine::general_purpose::STANDARD.encode(&decoded);
let result = quantum_decrypt(&tampered, conv, msg_id, secret);
assert!(result.is_err(), "Tampered HMAC should fail");
}
#[test]
fn test_invalid_utf8_fails() {
let conv = "conv-bin";
let msg_id = "msg-bin";
let secret = b"key";
let mut bad_bytes = quantum_encrypt("Valid UTF8", conv, msg_id, secret);
let mut raw = base64::engine::general_purpose::STANDARD.decode(&bad_bytes).unwrap();
raw[40] = 0xFF;
bad_bytes = base64::engine::general_purpose::STANDARD.encode(&raw);
let result = quantum_decrypt(&bad_bytes, conv, msg_id, secret);
assert!(result.is_err());
}
fn generate_keypair() -> (EphemeralSecret, PublicKey) {
let secret = EphemeralSecret::random_from_rng(OsRng);
let public = PublicKey::from(&secret);
(secret, public)
}
fn compute_shared_secret(secret: EphemeralSecret, public: &PublicKey) -> [u8; 32] {
secret.diffie_hellman(public).to_bytes()
}
#[test]
fn test_keypair_generation() {
let (secret, public) = generate_keypair();
assert_eq!(public.as_bytes().len(), 32);
let shared = secret.diffie_hellman(&public).to_bytes();
assert_eq!(shared.len(), 32);
}
#[test]
fn test_shared_secret_symmetry() {
let (alice_secret, alice_public) = generate_keypair();
let (bob_secret, bob_public) = generate_keypair();
let alice_shared = compute_shared_secret(alice_secret, &bob_public);
let bob_shared = compute_shared_secret(bob_secret, &alice_public);
assert_eq!(alice_shared, bob_shared);
}
#[test]
fn test_shared_secret_same_keypair_matches() {
let (secret, public) = generate_keypair();
let _shared1 = compute_shared_secret(secret, &public);
// Can't reuse the secret; test omitted.
}
#[test]
fn test_padding_entropy() {
let msg = "X";
let conv = "conv-pad";
let msg_id = "pad1";
let secret = b"pad-key";
let ct1 = quantum_encrypt(msg, conv, msg_id, secret);
let ct2 = quantum_encrypt(msg, conv, msg_id, secret);
assert_ne!(ct1, ct2, "Padding should produce entropy");
}
#[test]
fn test_encryption_decryption_speed() {
let msg = "Benchmarking test message!";
let conv = "conv-benchmark";
let msg_id = "msg-benchmark";
let secret = b"speed-key";
reset_replay_cache();
let start_enc = std::time::Instant::now();
let encrypted = quantum_encrypt(msg, conv, msg_id, secret);
let dur_enc = start_enc.elapsed();
assert!(
dur_enc < Duration::from_millis(5),
"Encryption took too long: {:?}",
dur_enc
);
let start_dec = std::time::Instant::now();
let decrypted = quantum_decrypt(&encrypted, conv, msg_id, secret)
.expect("Decryption failed unexpectedly");
let dur_dec = start_dec.elapsed();
assert!(
dur_dec < Duration::from_millis(5),
"Decryption took too long: {:?}",
dur_dec
);
assert_eq!(msg, decrypted);
}
}
// replay_guard.rs @Cryptis
// v.1.3
// Replay Functions
// ASVS Level 3 compliant - ASVS 3.8.1–3.9.1
use lru::LruCache;
use once_cell::sync::Lazy;
use std::num::NonZeroUsize;
use std::sync::Mutex;
use std::time::{SystemTime, UNIX_EPOCH};
static REPLAY_CACHE: Lazy>> =
Lazy::new(|| Mutex::new(LruCache::new(NonZeroUsize::new(10_000).unwrap()))); // max 10k entries
pub fn is_replay(conversation_id: &str, message_id: &str) -> bool {
let ctx = format!("{}::{}", conversation_id, message_id);
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_secs();
let mut cache = REPLAY_CACHE.lock().unwrap();
match cache.get(&ctx) {
Some(×tamp) if now - timestamp < 300 => true, // Replay detected within last 5 minutes
_ => {
cache.put(ctx, now);
false
}
}
}
/// Resets the replay cache for testing.
#[cfg(test)]
pub fn reset_replay_cache() {
let mut cache = REPLAY_CACHE.lock().unwrap();
cache.clear();
}
#[cfg(test)]
mod tests {
use super::*;
// use std::thread::sleep;
// use std::time::Duration;
#[test]
fn test_replay_cache() {
let conv_id = "conversation1";
let msg_id = "message1";
assert_eq!(is_replay(conv_id, msg_id), false);
assert_eq!(is_replay(conv_id, msg_id), true);
assert_eq!(is_replay(conv_id, "message2"), false);
assert_eq!(is_replay("conversation2", msg_id), false);
}
#[test]
fn test_replay_cache_expiration() {
let conv_id = "conv-expire";
let msg_id = "msg-expire";
assert_eq!(is_replay(conv_id, msg_id), false);
assert_eq!(is_replay(conv_id, msg_id), true);
// Activate for real test
// sleep(Duration::from_secs(6 * 60));
// assert_eq!(is_replay(conv_id, msg_id), false);
}
}
// ai_guard.rs @Cryptis
/*
This module provides protective mechanisms for secure message decryption.
It defends against replay attacks, excessive HMAC failures, payload anomalies,
and high message rates to enhance overall decryption security.
@TODO:
- Memory-Growth: USED_MESSAGE_IDS and FAILED_HMAC_COUNTER grow without limit.
- Mutex Locking: Under very high loads, mutex locks can become a bottleneck.
- Duration calculation: now.duration_since(*t).unwrap_or(Duration::ZERO) can panic when the system time changes.
- Missing rate limiting for HMAC fails
- Naming of context in case of HMAC fail
- Add AI mechanism
*/
use std::collections::{HashMap, HashSet};
use std::sync::Mutex;
use std::time::{Duration, Instant, SystemTime};
use once_cell::sync::Lazy;
use tracing::{warn, error};
static USED_MESSAGE_IDS: Lazy>> = Lazy::new(|| Mutex::new(HashSet::new()));
static FAILED_HMAC_COUNTER: Lazy>> = Lazy::new(|| Mutex::new(HashMap::new()));
static DECRYPTION_TIMES: Lazy>> = Lazy::new(|| Mutex::new(Vec::new()));
static MESSAGE_TIMESTAMPS: Lazy>>> = Lazy::new(|| Mutex::new(HashMap::new()));
const MAX_PAYLOAD_SIZE: usize = 1024;
const HMAC_FAIL_THRESHOLD: u32 = 5;
const ANOMALY_WINDOW_SIZE: usize = 20;
const MAX_MSGS_PER_MIN: usize = 30;
// Replay attack
pub fn check_replay(message_id: &str) -> bool {
let mut used = USED_MESSAGE_IDS.lock().unwrap();
if used.contains(message_id) {
warn!("Replay detected: {}", message_id);
return true;
}
used.insert(message_id.to_string());
false
}
// Failed HMAC attempt
pub fn register_hmac_fail(context: &str) -> bool {
let mut fails = FAILED_HMAC_COUNTER.lock().unwrap();
let count = fails.entry(context.to_string()).or_insert(0);
*count += 1;
if *count > HMAC_FAIL_THRESHOLD {
error!("Too many HMAC failures for {}", context);
return true;
}
false
}
// Decryption duration / anomalies (3x average).
pub fn log_decryption_time(duration: Duration) {
let mut times = DECRYPTION_TIMES.lock().unwrap();
times.push(duration);
if times.len() > ANOMALY_WINDOW_SIZE {
times.remove(0);
}
let avg = times.iter().sum::() / times.len() as u32;
if duration > avg * 3 {
warn!("Decryption time anomaly: {:?} (avg: {:?})", duration, avg);
}
}
// Payload size
pub fn payload_anomaly_check(data: &[u8]) -> bool {
if data.len() > MAX_PAYLOAD_SIZE {
warn!("Payload too large: {} bytes", data.len());
return true;
}
false
}
// Message rate per conversation
pub fn message_rate_check(conversation_id: &str) -> bool {
let mut timestamps = MESSAGE_TIMESTAMPS.lock().unwrap();
let now = SystemTime::now();
let times = timestamps.entry(conversation_id.to_string()).or_insert_with(Vec::new);
times.push(now);
times.retain(|t| now.duration_since(*t).unwrap_or(Duration::ZERO) < Duration::from_secs(60));
if times.len() > MAX_MSGS_PER_MIN {
warn!("Message rate too high for {}: {} msgs/min", conversation_id, times.len());
return true;
}
false
}
pub fn protected_decrypt(
message_id: &str,
ciphertext: &[u8],
decrypt_fn: impl FnOnce() -> Result,
) -> Result {
if check_replay(message_id) {
return Err("Replay attack detected");
}
if payload_anomaly_check(ciphertext) {
return Err("Payload anomaly detected");
}
let start = Instant::now();
let result = decrypt_fn();
let duration = start.elapsed();
log_decryption_time(duration);
if message_rate_check(message_id) {
return Err("Message rate anomaly");
}
match &result {
Err(e) if *e == "HMAC verification failed" => {
if register_hmac_fail(message_id) {
return Err("Too many failed attempts");
}
}
_ => {}
}
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_replay_detection() {
let id = "msg1";
assert!(!check_replay(id));
assert!(check_replay(id));
}
#[test]
fn test_hmac_fail_counter() {
let ctx = "ctx1";
for _i in 0..HMAC_FAIL_THRESHOLD {
assert!(!register_hmac_fail(ctx));
}
assert!(register_hmac_fail(ctx));
}
#[test]
fn test_payload_anomaly() {
let normal_payload = vec![0u8; MAX_PAYLOAD_SIZE];
assert!(!payload_anomaly_check(&normal_payload));
let large_payload = vec![0u8; MAX_PAYLOAD_SIZE + 1];
assert!(payload_anomaly_check(&large_payload));
}
#[test]
fn test_message_rate_check() {
let conv_id = "conv1";
{
let mut timestamps = MESSAGE_TIMESTAMPS.lock().unwrap();
timestamps.remove(conv_id);
}
for _ in 0..MAX_MSGS_PER_MIN {
assert!(!message_rate_check(conv_id));
}
assert!(message_rate_check(conv_id));
}
#[test]
fn test_protected_decrypt_replay() {
let id = "msg_replay";
check_replay(id);
let result: Result<(), &str> = protected_decrypt(id, b"payload", || Ok(()));
assert!(result.is_err());
assert_eq!(result.unwrap_err(), "Replay attack detected");
}
#[test]
fn test_protected_decrypt_payload_anomaly() {
let id = "msg_payload";
let large_payload = vec![0u8; MAX_PAYLOAD_SIZE + 10];
let result: Result<(), &str> = protected_decrypt(id, &large_payload, || Ok(()));
assert!(result.is_err());
assert_eq!(result.unwrap_err(), "Payload anomaly detected");
}
}

use std::time::Instant;
// === Configuration ===
const NUM_ROUNDS: usize = 24;
const ROUND_CONSTANTS: [u64; NUM_ROUNDS] = [
0x243F6A8885A308D3, 0x13198A2E03707344, 0xA4093822299F31D0, 0x082EFA98EC4E6C89,
0x452821E638D01377, 0xBE5466CF34E90C6C, 0xC0AC29B7C97C50DD, 0x3F84D5B5B5470917,
0x9216D5D98979FB1B, 0xD1310BA698DFB5AC, 0x2FFD72DBD01ADFB7, 0xB8E1AFED6A267E96,
0x9B05688C2B3E6C1F, 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179, 0xCBBB9D5DC1059ED8,
0x629A292A367CD507, 0x9159015A3070DD17, 0x152FECD8F70E5939, 0x67332667FFC00B31,
0x8EB44A8768581511, 0xDB0C2E0D64F98FA7, 0x47B5481DBEFA4FA4, 0x0FC19DC68B8CD5B5,
];
// === Dynamic S-Box Generation Using Input Bytes ===
fn generate_sbox(seed: u64, input_bytes: &[u8]) -> [u8; 256] {
let mut sbox = [0u8; 256];
for i in 0..256 {
sbox[i] = i as u8;
}
// Seed mix
let mut mixed_seed = seed;
if input_bytes.len() > 7 {
mixed_seed ^= (input_bytes[2] as u64) << 16;
mixed_seed ^= (input_bytes[5] as u64) << 8;
mixed_seed ^= input_bytes[7] as u64;
} else {
for (i, &b) in input_bytes.iter().enumerate() {
mixed_seed ^= (b as u64) << (8 * (i % 8));
}
}
// Shuffle 1
let mut state = mixed_seed;
for i in (1..256).rev() {
state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
let j = (state % (i as u64 + 1)) as usize;
sbox.swap(i, j);
}
// Shuffle 2
for i in (1..256).rev() {
state = state.wrapping_mul(1442695040888963407).wrapping_add(1);
let j = (state % (i as u64 + 1)) as usize;
sbox.swap(i, j);
}
sbox
}
// Byte substitution with dynamic S-Box
fn byte_substitute(x: u8, sbox: &[u8; 256]) -> u8 {
sbox[x as usize]
}
fn apply_byte_substitution(x: u64, sbox: &[u8; 256]) -> u64 {
let mut result = 0u64;
for i in 0..8 {
let byte = ((x >> (i * 8)) & 0xFF) as u8;
let substituted = byte_substitute(byte, sbox);
result |= (substituted as u64) << (i * 8);
}
result
}
// Improved bit mixing with an additional nonlinear round and input bytes
fn bit_mix(mut x: u64, rc: u64, input_bytes: &[u8]) -> u64 {
x = x.wrapping_add(rc);
x ^= x.rotate_left(7);
x = x.wrapping_add(x.rotate_left(17));
x ^= x.wrapping_mul(0x94D049BB133111EB);
x = x.wrapping_sub(x.rotate_right(19));
x ^= rc.rotate_left(11);
x ^= (x.wrapping_mul(0xA24BAED4963EE407)).rotate_left(23);
if input_bytes.len() > 6 {
let b3 = input_bytes[3] as u64;
let b6 = input_bytes[6] as u64;
x ^= (b3.wrapping_mul(0xDEADBEEFDEADBEEF) ^ b6.wrapping_mul(0xBADF00D1BADF00D1)).rotate_left(13);
}
x
}
// One round permutation, with stronger interaction between state words and input bytes
fn permute_round(state: &mut [u64; 8], round: usize, sbox: &[u8; 256], input_bytes: &[u8]) {
let rc = ROUND_CONSTANTS[round % ROUND_CONSTANTS.len()];
for i in 0..8 {
state[i] = bit_mix(state[i], rc, input_bytes);
}
for i in 0..8 {
state[i] = apply_byte_substitution(state[i], sbox);
}
for i in 0..8 {
let left = state[(i + 7) % 8];
let right = state[(i + 1) % 8];
let center = state[(i + 4) % 8];
let extra = state[(i + 3) % 8];
state[i] ^= left.rotate_left((round as u32 + i as u32 * 2) % 64);
state[i] ^= right.rotate_right((round as u32 + i as u32 * 3) % 64);
state[i] ^= center.rotate_left(11);
state[i] ^= extra.wrapping_mul(0x9E3779B97F4A7C15).rotate_left((round as u32 + i as u32 * 5) % 64);
}
}
// Complete permutation with dynamic S-Box (from initial state seed + input bytes)
fn permute(state: &mut [u64; 8], input_bytes: &[u8]) {
let seed = state.iter().fold(0u64, |acc, &v| acc ^ v);
let sbox = generate_sbox(seed, input_bytes);
for round in 0..NUM_ROUNDS {
permute_round(state, round, &sbox, input_bytes);
}
}
// Padding
fn pad_block(data: &[u8]) -> Vec {
let mut padded = data.to_vec();
padded.push(0x80);
while padded.len() % 8 != 0 {
padded.push(0x00);
}
padded
}
// Hash function
fn hash(inputs: &[&[u8]]) -> [u64; 8] {
let mut state = [0u64; 8];
for &block in inputs {
let padded = pad_block(block);
for (i, chunk) in padded.chunks(8).enumerate() {
let mut val = 0u64;
for (j, &b) in chunk.iter().enumerate() {
val |= (b as u64) << (j * 8);
}
state[i % 8] ^= val;
}
permute(&mut state, &padded);
}
state
}
// Helper function to print hashes
fn print_hash(label: &str, input: &[u8], hashval: &[u64; 8]) {
print!("{} ({} bytes): ", label, input.len());
for &v in hashval {
print!("{:016x}", v);
}
println!();
}
// === main ===
fn main() {
let test_inputs = vec![
b"".as_ref(),
b"short".as_ref(),
b"some medium length data".as_ref(),
b"this is a longer input data to test the hash function with multiple rounds".as_ref(),
&[0u8; 1000][..],
];
println!("=== Cryptix Frost Hash ===");
println!("=== Serial Hashes ===");
for (i, input) in test_inputs.iter().enumerate() {
let hashval = hash(&[*input]);
print_hash(&format!("Input {}", i), input, &hashval);
}
let bigdata = vec![0x55u8; 10_000_000];
let start = Instant::now();
let _ = hash(&[&bigdata]);
println!("Hash time for 10MB: {:.3?}", start.elapsed());
// Tests
avalanche_test();
collision_test();
speed_test();
determinism_test();
differential_test();
}
// === Tests ===
// Avalanche test function
fn avalanche_test() {
let input = b"hello world";
let mut modified = input.clone().to_vec();
modified[0] ^= 0x01;
let h1 = hash(&[input]);
let h2 = hash(&[&modified]);
println!("--- Avalanche Test ---");
print_hash("Original", input, &h1);
print_hash("Modified", &modified, &h2);
let mut diff_bits = 0;
for i in 0..8 {
diff_bits += (h1[i] ^ h2[i]).count_ones();
}
println!("Differing bits: {}", diff_bits);
}
// Collision test: scan many similar inputs for collisions
fn collision_test() {
println!("--- Collision Test ---");
let base = b"collision_test_base_string";
let mut collisions = 0;
let tries = 200;
for i in 0..tries {
let mut input = base.to_vec();
input.push(i as u8);
let h1 = hash(&[&input]);
for j in (i + 1)..tries {
let mut input2 = base.to_vec();
input2.push(j as u8);
let h2 = hash(&[&input2]);
if h1 == h2 {
println!("Collision found between inputs {} and {}", i, j);
collisions += 1;
}
}
}
println!("Total collisions in {} tries: {}", tries, collisions);
}
// Speed test for various input sizes
fn speed_test() {
println!("--- Speed Test ---");
let sizes = [1, 16, 64, 256, 1024, 4096, 16_384, 65_536];
for &size in &sizes {
let data = vec![0xAAu8; size];
let start = Instant::now();
let _ = hash(&[&data]);
let elapsed = start.elapsed();
println!("Input size: {:6} bytes, Time: {:?}", size, elapsed);
}
}
// Determinism test: same input -> same output
fn determinism_test() {
println!("--- Determinism Test ---");
let input = b"determinism_test_input_data";
let h1 = hash(&[input]);
let h2 = hash(&[input]);
assert_eq!(h1, h2);
println!("Determinism test passed!");
}
// Differential Analysis: Evaluates Avalanche Effect Across Input Variations
fn differential_test() {
let base = b"diff_test_input_data_for_hash";
let mut total_diff = 0u32;
let mut pairs = 0u32;
for i in 0..base.len() {
for b in 0u8..=255 {
let input1 = base.to_vec();
let mut input2 = base.to_vec();
input2[i] = b;
let h1 = hash(&[&input1]);
let h2 = hash(&[&input2]);
let mut diff_bits = 0;
for idx in 0..8 {
diff_bits += (h1[idx] ^ h2[idx]).count_ones();
}
total_diff += diff_bits;
pairs += 1;
}
}
println!("Differential test average differing bits: {}", total_diff / pairs);
}