-
-
Save rust-play/333adf415d111f9c0ad80d7261a0eeac to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #[allow(unused_imports)] | |
| use sha2::{Digest, Sha256}; | |
| #[allow(unused_imports)] | |
| use std::time::Instant; | |
| // ============================================================================ | |
| // Cross-Platform Hardware CPU Tick Counter | |
| // ============================================================================ | |
| /// Reads the low-level CPU tick counter across x86/x86_64, AArch64, and RISC-V. | |
| /// Falls back to sub-nanosecond std::time::Instant if hardware counter is unavailable. | |
| #[inline(always)] | |
| pub fn read_cpu_ticks() -> u64 { | |
| #[cfg(target_arch = "x86_64")] | |
| { | |
| // Safety: RDTSC is available on all 64-bit x86 processors | |
| unsafe { std::arch::x86_64::_rdtsc() } | |
| } | |
| #[cfg(target_arch = "x86")] | |
| { | |
| // Safety: RDTSC is available on standard x86 processors (Pentium+) | |
| unsafe { std::arch::x86::_rdtsc() } | |
| } | |
| #[cfg(target_arch = "aarch64")] | |
| { | |
| let ticks: u64; | |
| // Read virtual timer count register (CNTVCT_EL0) on ARM64 / Apple Silicon | |
| unsafe { | |
| std::arch::asm!( | |
| "mrs {}, cntvct_el0", | |
| out(reg) ticks, | |
| options(nomem, nostack, preserves_flags) | |
| ); | |
| } | |
| ticks | |
| } | |
| #[cfg(target_arch = "riscv64")] | |
| { | |
| let ticks: u64; | |
| unsafe { | |
| std::arch::asm!( | |
| "rdcycle {}", | |
| out(reg) ticks, | |
| options(nomem, nostack, preserves_flags) | |
| ); | |
| } | |
| ticks | |
| } | |
| #[cfg(not(any( | |
| target_arch = "x86_64", | |
| target_arch = "x86", | |
| target_arch = "aarch64", | |
| target_arch = "riscv64" | |
| )))] | |
| { | |
| // Portable fallback | |
| Instant::now().elapsed().as_nanos() as u64 | |
| } | |
| } | |
| // ============================================================================ | |
| // Sound CPU Jitter Entropy Collector | |
| // ============================================================================ | |
| pub struct JitterEntropyCollector; | |
| impl JitterEntropyCollector { | |
| /// Collects hardware timing jitter across memory and pipeline execution state. | |
| /// Interleaves CPU instruction mixing to enforce non-deterministic cycle variations. | |
| pub fn collect_raw_entropy(samples: usize) -> Vec<u8> { | |
| let mut raw_bytes = Vec::with_capacity(samples * 8); | |
| let mut state: u64 = read_cpu_ticks(); | |
| for i in 0..samples { | |
| let t0 = read_cpu_ticks(); | |
| // Perform non-trivial arithmetic loop to force instruction pipeline dependency | |
| for j in 0..16 { | |
| state = state | |
| .wrapping_mul(6364136223846793005) | |
| .wrapping_add((i ^ j) as u64); | |
| } | |
| let t1 = read_cpu_ticks(); | |
| let delta = t1.wrapping_sub(t0) ^ state; | |
| raw_bytes.extend_from_slice(&delta.to_le_bytes()); | |
| } | |
| raw_bytes | |
| } | |
| /// Sound Entropy Extraction: Uses SHA-256 cryptographic hashing to condense | |
| /// correlated microarchitectural jitter into 32 unbiased, uniformly random bytes. | |
| pub fn extract_unbiased_seed(samples: usize) -> [u8; 32] { | |
| let raw_entropy = Self::collect_raw_entropy(samples); | |
| let mut hasher = Sha256::new(); | |
| hasher.update(&raw_entropy); | |
| hasher.finalize().into() | |
| } | |
| } | |
| // ============================================================================ | |
| // Von Neumann Extractor (Pure Uncorrelated Pair Stream Debiasing) | |
| // ============================================================================ | |
| pub struct VonNeumannExtractor { | |
| buffered_bit: Option<bool>, | |
| } | |
| impl VonNeumannExtractor { | |
| pub fn new() -> Self { | |
| Self { buffered_bit: None } | |
| } | |
| pub fn process_bit(&mut self, bit: bool) -> Option<bool> { | |
| match self.buffered_bit.take() { | |
| None => { | |
| self.buffered_bit = Some(bit); | |
| None | |
| } | |
| Some(prev_bit) => match (prev_bit, bit) { | |
| (false, true) => Some(false), // 01 -> 0 | |
| (true, false) => Some(true), // 10 -> 1 | |
| _ => None, // 00 or 11 -> Discard | |
| }, | |
| } | |
| } | |
| pub fn process_slice(&mut self, bits: &[bool]) -> Vec<bool> { | |
| let mut result = Vec::new(); | |
| for &bit in bits { | |
| if let Some(unbiased_bit) = self.process_bit(bit) { | |
| result.push(unbiased_bit); | |
| } | |
| } | |
| result | |
| } | |
| pub fn reset(&mut self) { | |
| self.buffered_bit = None; | |
| } | |
| } | |
| impl Default for VonNeumannExtractor { | |
| fn default() -> Self { | |
| Self::new() | |
| } | |
| } | |
| // ============================================================================ | |
| // Execution Example | |
| // ============================================================================ | |
| fn main() { | |
| println!("Platform Architecture initialized. Reading hardware cycles..."); | |
| println!("Initial Hardware Tick: {}", read_cpu_ticks()); | |
| let num_samples = 10_000; | |
| // 1. Gather raw jitter bytes directly from CPU ticks | |
| let raw_bytes = JitterEntropyCollector::collect_raw_entropy(num_samples); | |
| // Extract LSB bits from raw cycles to test Von Neumann efficiency | |
| let raw_bits: Vec<bool> = raw_bytes | |
| .iter() | |
| .flat_map(|&b| (0..8).map(move |i| ((b >> i) & 1) == 1)) | |
| .collect(); | |
| let mut extractor = VonNeumannExtractor::new(); | |
| let debiased_bits = extractor.process_slice(&raw_bits); | |
| println!("\n--- Raw Jitter Extraction ---"); | |
| println!("Raw bits sampled : {}", raw_bits.len()); | |
| println!("Debiased bit yield: {}", debiased_bits.len()); | |
| println!( | |
| "Extraction efficiency: {:.2}%", | |
| (debiased_bits.len() as f64 / raw_bits.len() as f64) * 100.0 | |
| ); | |
| // 2. Cryptographic Extraction (The theoretically sound production model) | |
| let crypto_seed = JitterEntropyCollector::extract_unbiased_seed(num_samples); | |
| println!("\n--- Cryptographic Extractor (SHA-256) ---"); | |
| println!("Extracted 256-bit Seed: {:02x?}", crypto_seed); | |
| } | |
| #[cfg(test)] | |
| mod tests { | |
| use super::*; | |
| #[test] | |
| fn test_tick_counter_progresses() { | |
| let t0 = read_cpu_ticks(); | |
| let t1 = read_cpu_ticks(); | |
| assert!(t1 >= t0, "Hardware tick counter must increment monotonically"); | |
| } | |
| #[test] | |
| fn test_jitter_collector() { | |
| let seed = JitterEntropyCollector::extract_unbiased_seed(1_000); | |
| assert_eq!(seed.len(), 32); | |
| // Ensure not all bytes are zero | |
| assert!(seed.iter().any(|&b| b != 0)); | |
| } | |
| #[test] | |
| fn test_von_neumann_pairs() { | |
| let mut extractor = VonNeumannExtractor::new(); | |
| assert_eq!(extractor.process_bit(false), None); | |
| assert_eq!(extractor.process_bit(true), Some(false)); | |
| assert_eq!(extractor.process_bit(true), None); | |
| assert_eq!(extractor.process_bit(false), Some(true)); | |
| assert_eq!(extractor.process_bit(false), None); | |
| assert_eq!(extractor.process_bit(false), None); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| version = "1" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment