Skip to main content

blvm_primitives/crypto/
mod.rs

1//! Cryptographic hash functions with CPU feature detection and optimizations
2//!
3//! Provides optimized SHA256 implementations that automatically select
4//! the best available implementation based on CPU features:
5//! - AVX2 SIMD (8-way parallel) - fastest on modern CPUs
6//! - SSE4 SIMD (4-way parallel) - fallback for older CPUs  
7//! - Generic (sha2 crate with asm) - baseline for all CPUs
8//!
9//! The sha2 crate with "asm" feature already includes optimized assembly,
10//! but we can add batch processing and CPU feature detection for better
11//! performance in batch scenarios.
12
13use sha2::{Digest, Sha256};
14
15#[cfg(target_arch = "x86_64")]
16pub mod avx2_batch;
17#[cfg(target_arch = "x86_64")]
18pub mod hash_compare;
19#[cfg(target_arch = "x86_64")]
20pub mod sha256_avx2;
21#[cfg(target_arch = "x86_64")]
22pub mod sha_ni;
23#[cfg(target_arch = "x86_64")]
24pub mod simd_bytes;
25
26pub mod int_ops;
27
28/// CPU feature detection for runtime optimization selection
29pub mod cpu_features {
30    /// Check if AVX2 is available
31    ///
32    /// Hot-path function called during hash operation dispatch.
33    /// Always inline for maximum performance.
34    #[cfg(target_arch = "x86_64")]
35    #[inline(always)]
36    pub fn has_avx2() -> bool {
37        std::arch::is_x86_feature_detected!("avx2")
38    }
39
40    /// Check if SSE4.1 is available
41    ///
42    /// Hot-path function called during hash operation dispatch.
43    /// Always inline for maximum performance.
44    #[cfg(target_arch = "x86_64")]
45    #[inline(always)]
46    pub fn has_sse41() -> bool {
47        std::arch::is_x86_feature_detected!("sse4.1")
48    }
49
50    /// Check if Intel SHA-NI is available
51    ///
52    /// Hot-path function called during hash operation dispatch.
53    /// Always inline for maximum performance.
54    #[cfg(target_arch = "x86_64")]
55    #[inline(always)]
56    pub fn has_sha_ni() -> bool {
57        std::arch::is_x86_feature_detected!("sha")
58    }
59
60    #[cfg(not(target_arch = "x86_64"))]
61    pub fn has_avx2() -> bool {
62        false
63    }
64
65    #[cfg(not(target_arch = "x86_64"))]
66    pub fn has_sse41() -> bool {
67        false
68    }
69
70    #[cfg(not(target_arch = "x86_64"))]
71    pub fn has_sha_ni() -> bool {
72        false
73    }
74}
75
76/// Optimized SHA256 hasher with CPU feature detection
77pub struct OptimizedSha256;
78
79impl OptimizedSha256 {
80    /// Create a new SHA256 hasher with automatic CPU feature detection
81    pub fn new() -> Self {
82        Self
83    }
84
85    /// Hash data using the best available implementation
86    ///
87    /// Priority:
88    /// 1. SHA-NI (Intel SHA Extensions) - 10-15x faster for single hashes
89    /// 2. sha2 crate with asm - baseline fallback
90    ///
91    /// For batch operations, see batch_sha256 in optimizations module.
92    pub fn hash(&self, data: &[u8]) -> [u8; 32] {
93        #[cfg(target_arch = "x86_64")]
94        {
95            // Try SHA-NI first (hardware accelerated, optimal for single hashes)
96            if sha_ni::is_sha_ni_available() {
97                return sha_ni::sha256(data);
98            }
99        }
100
101        // Fallback: sha2 crate with asm optimizations
102        let mut hasher = Sha256::new();
103        hasher.update(data);
104        let hash = hasher.finalize();
105        let mut result = [0u8; 32];
106        result.copy_from_slice(&hash);
107        result
108    }
109
110    /// Compute double SHA256 (SHA256(SHA256(data)))
111    ///
112    /// Uses SHA-NI if available for optimal single-hash performance.
113    pub fn hash256(&self, data: &[u8]) -> [u8; 32] {
114        #[cfg(target_arch = "x86_64")]
115        {
116            if sha_ni::is_sha_ni_available() {
117                return sha_ni::hash256(data);
118            }
119        }
120
121        let first = self.hash(data);
122        self.hash(&first)
123    }
124}
125
126impl Default for OptimizedSha256 {
127    fn default() -> Self {
128        Self::new()
129    }
130}
131
132/// Convenience function for single SHA256 hash
133pub fn sha256(data: &[u8]) -> [u8; 32] {
134    OptimizedSha256::new().hash(data)
135}
136
137/// Convenience function for double SHA256 hash (Bitcoin standard)
138pub fn hash256(data: &[u8]) -> [u8; 32] {
139    OptimizedSha256::new().hash256(data)
140}