lib_q_random/traits.rs
1// Allow clippy warnings in trait definitions
2// These are legitimate patterns for API design
3#![allow(clippy::struct_excessive_bools, clippy::doc_markdown)]
4
5//! Core traits for lib-q-random
6//!
7//! This module defines the fundamental traits that form the interface
8//! for random number generation in the libQ ecosystem.
9
10#[cfg(feature = "alloc")]
11use alloc::{
12 boxed::Box,
13 collections::BTreeMap,
14 string::String,
15};
16use core::fmt;
17
18use rand_core::{
19 CryptoRng,
20 Rng,
21};
22
23use crate::Result;
24
25/// Enhanced random number generator trait for cryptographic applications
26///
27/// This trait extends the standard `Rng` and `CryptoRng` traits with
28/// additional functionality required for secure cryptographic operations.
29pub trait SecureRng: Rng + CryptoRng + Send + Sync {
30 /// Fill the buffer with cryptographically secure random bytes
31 ///
32 /// This method provides the same functionality as `Rng::fill_bytes`
33 /// but with additional security guarantees and error handling.
34 ///
35 /// # Arguments
36 ///
37 /// * `dest` - Buffer to fill with random bytes
38 ///
39 /// # Errors
40 ///
41 /// Returns an error if the random number generation fails or if
42 /// the generated bytes don't meet security requirements.
43 fn fill_bytes_secure(&mut self, dest: &mut [u8]) -> Result<()> {
44 self.fill_bytes(dest);
45 Ok(())
46 }
47
48 /// Generate a random u32 with security validation
49 ///
50 /// # Errors
51 ///
52 /// Returns an error if the random number generation fails.
53 fn next_u32_secure(&mut self) -> Result<u32> {
54 Ok(self.next_u32())
55 }
56
57 /// Generate a random u64 with security validation
58 ///
59 /// # Errors
60 ///
61 /// Returns an error if the random number generation fails.
62 fn next_u64_secure(&mut self) -> Result<u64> {
63 Ok(self.next_u64())
64 }
65
66 /// Initialize the RNG with entropy (if supported)
67 ///
68 /// # Arguments
69 ///
70 /// * `entropy` - Entropy data to initialize the RNG
71 ///
72 /// # Errors
73 ///
74 /// Returns an error if the entropy is invalid or initialization fails.
75 fn initialize(&mut self, entropy: &[u8]) -> Result<()> {
76 // Default implementation does nothing
77 let _ = entropy;
78 Ok(())
79 }
80
81 /// Check if the RNG is cryptographically secure
82 ///
83 /// Returns `true` if the RNG provides cryptographically secure randomness,
84 /// `false` otherwise (e.g., for deterministic RNGs used in testing).
85 fn is_secure(&self) -> bool {
86 true
87 }
88
89 /// Get the entropy quality estimate (0.0 to 1.0)
90 ///
91 /// Returns an estimate of the entropy quality, where 1.0 represents
92 /// perfect entropy and 0.0 represents no entropy.
93 fn entropy_quality(&self) -> f64 {
94 1.0
95 }
96
97 /// Get the RNG's security level
98 ///
99 /// Returns a description of the RNG's security characteristics.
100 fn security_level(&self) -> SecurityLevel {
101 if self.is_secure() {
102 SecurityLevel::CryptographicallySecure
103 } else {
104 SecurityLevel::Deterministic
105 }
106 }
107
108 /// Reseed the RNG with fresh entropy
109 ///
110 /// This method allows the RNG to be reseeded with fresh entropy,
111 /// which is important for long-running applications.
112 ///
113 /// # Errors
114 ///
115 /// Returns an error if reseeding fails or is not supported.
116 fn reseed(&mut self) -> Result<()> {
117 // Default implementation does nothing
118 Ok(())
119 }
120
121 /// Get the RNG's internal state size
122 ///
123 /// Returns the size of the RNG's internal state in bytes.
124 fn state_size(&self) -> usize {
125 0
126 }
127
128 /// Get the RNG's reseed interval
129 ///
130 /// Returns the recommended number of bytes to generate before reseeding,
131 /// or `None` if reseeding is not required.
132 fn reseed_interval(&self) -> Option<usize> {
133 None
134 }
135}
136
137/// Entropy source trait for providing random data
138///
139/// This trait defines the interface for entropy sources that can provide
140/// random data to RNG implementations.
141pub trait EntropySource: Send + Sync {
142 /// Get entropy from the source
143 ///
144 /// # Arguments
145 ///
146 /// * `dest` - Buffer to fill with entropy data
147 ///
148 /// # Errors
149 ///
150 /// Returns an error if entropy cannot be obtained from the source.
151 fn get_entropy(&mut self, dest: &mut [u8]) -> Result<()>;
152
153 /// Check if the entropy source is available
154 ///
155 /// Returns `true` if the entropy source is available and can provide
156 /// entropy, `false` otherwise.
157 fn is_available(&self) -> bool {
158 true
159 }
160
161 /// Get the entropy source's quality estimate (0.0 to 1.0)
162 ///
163 /// Returns an estimate of the entropy source's quality, where 1.0
164 /// represents perfect entropy and 0.0 represents no entropy.
165 fn quality(&self) -> f64 {
166 1.0
167 }
168
169 /// Get the entropy source's name
170 ///
171 /// Returns a human-readable name for the entropy source.
172 fn name(&self) -> &'static str {
173 "Unknown"
174 }
175
176 /// Get the entropy source's type
177 ///
178 /// Returns the type of entropy source.
179 fn source_type(&self) -> EntropySourceType {
180 EntropySourceType::User // Default to User for custom implementations
181 }
182
183 /// Get the maximum entropy that can be obtained in one call
184 ///
185 /// Returns the maximum number of bytes that can be obtained in a single
186 /// call to `get_entropy`, or `None` if there's no limit.
187 fn max_entropy_per_call(&self) -> Option<usize> {
188 None
189 }
190
191 /// Check if the entropy source requires initialization
192 ///
193 /// Returns `true` if the entropy source requires initialization before use.
194 fn requires_initialization(&self) -> bool {
195 false
196 }
197
198 /// Initialize the entropy source
199 ///
200 /// # Arguments
201 ///
202 /// * `config` - Configuration parameters for initialization
203 ///
204 /// # Errors
205 ///
206 /// Returns an error if initialization fails.
207 fn initialize(&mut self, config: &EntropyConfig) -> Result<()> {
208 let _ = config;
209 Ok(())
210 }
211}
212
213/// RNG provider trait for creating and managing RNG instances
214///
215/// This trait defines the interface for RNG providers that can create
216/// and manage RNG instances with different characteristics.
217pub trait RngProvider: Send + Sync {
218 /// Create a new RNG instance
219 ///
220 /// # Arguments
221 ///
222 /// * `config` - Configuration for the RNG
223 ///
224 /// # Errors
225 ///
226 /// Returns an error if the RNG cannot be created.
227 #[cfg(feature = "alloc")]
228 fn create_rng(&self, config: &RngConfig) -> Result<Box<dyn SecureRng>>;
229
230 /// Get the provider's name
231 ///
232 /// Returns a human-readable name for the provider.
233 fn name(&self) -> &'static str;
234
235 /// Get the provider's capabilities
236 ///
237 /// Returns the capabilities of the provider.
238 fn capabilities(&self) -> ProviderCapabilities;
239
240 /// Check if the provider supports a specific configuration
241 ///
242 /// # Arguments
243 ///
244 /// * `config` - Configuration to check
245 ///
246 /// Returns `true` if the provider supports the configuration.
247 fn supports_config(&self, config: &RngConfig) -> bool {
248 let _ = config;
249 true
250 }
251
252 /// Get the provider's priority
253 ///
254 /// Returns a priority value for the provider, where higher values
255 /// indicate higher priority.
256 fn priority(&self) -> u32 {
257 0
258 }
259}
260
261/// Security level enumeration
262#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
263pub enum SecurityLevel {
264 /// Deterministic (not cryptographically secure)
265 Deterministic,
266 /// Cryptographically secure
267 CryptographicallySecure,
268 /// Hardware-based security
269 Hardware,
270 /// Software-based security
271 Software,
272}
273
274impl fmt::Display for SecurityLevel {
275 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276 match self {
277 Self::Deterministic => write!(f, "Deterministic"),
278 Self::CryptographicallySecure => write!(f, "Cryptographically Secure"),
279 Self::Hardware => write!(f, "Hardware"),
280 Self::Software => write!(f, "Software"),
281 }
282 }
283}
284
285/// Entropy source type enumeration
286#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
287pub enum EntropySourceType {
288 /// Operating system entropy source
289 OperatingSystem,
290 /// Hardware random number generator
291 Hardware,
292 /// User-provided entropy
293 User,
294 /// Deterministic source (for testing)
295 Deterministic,
296}
297
298impl fmt::Display for EntropySourceType {
299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300 match self {
301 Self::OperatingSystem => write!(f, "Operating System"),
302 Self::Hardware => write!(f, "Hardware"),
303 Self::User => write!(f, "User"),
304 Self::Deterministic => write!(f, "Deterministic"),
305 }
306 }
307}
308
309/// RNG configuration structure
310pub struct RngConfig {
311 /// Security level required
312 pub security_level: SecurityLevel,
313 /// Entropy source to use
314 #[cfg(feature = "alloc")]
315 pub entropy_source: Option<Box<dyn EntropySource>>,
316 /// Reseed interval in bytes
317 pub reseed_interval: Option<usize>,
318 /// Additional configuration parameters
319 #[cfg(feature = "alloc")]
320 pub parameters: BTreeMap<String, String>,
321}
322
323impl Default for RngConfig {
324 fn default() -> Self {
325 Self {
326 security_level: SecurityLevel::CryptographicallySecure,
327 #[cfg(feature = "alloc")]
328 entropy_source: None,
329 reseed_interval: None,
330 #[cfg(feature = "alloc")]
331 parameters: BTreeMap::new(),
332 }
333 }
334}
335
336/// Entropy configuration structure
337#[derive(Debug, Clone)]
338pub struct EntropyConfig {
339 /// Minimum entropy quality required
340 pub min_quality: f64,
341 /// Maximum entropy per call
342 pub max_per_call: Option<usize>,
343 /// Additional configuration parameters
344 #[cfg(feature = "alloc")]
345 pub parameters: BTreeMap<String, String>,
346}
347
348impl Default for EntropyConfig {
349 fn default() -> Self {
350 Self {
351 min_quality: 0.8,
352 max_per_call: None,
353 #[cfg(feature = "alloc")]
354 parameters: BTreeMap::new(),
355 }
356 }
357}
358
359/// Provider capabilities structure
360#[derive(Debug, Clone, Copy, PartialEq, Eq)]
361pub struct ProviderCapabilities {
362 /// Can provide cryptographically secure randomness
363 pub secure: bool,
364 /// Can provide deterministic randomness
365 pub deterministic: bool,
366 /// Supports hardware entropy sources
367 pub hardware: bool,
368 /// Supports reseeding
369 pub reseeding: bool,
370 /// Supports custom entropy sources
371 pub custom_entropy: bool,
372 /// Supports no_std environments
373 pub no_std: bool,
374 /// Supports WASM environments
375 pub wasm: bool,
376}
377
378impl Default for ProviderCapabilities {
379 fn default() -> Self {
380 Self {
381 secure: true,
382 deterministic: false,
383 hardware: false,
384 reseeding: false,
385 custom_entropy: false,
386 no_std: true,
387 wasm: false,
388 }
389 }
390}
391
392#[cfg(test)]
393mod tests {
394 #[cfg(all(not(feature = "std"), feature = "alloc"))]
395 use alloc::format;
396
397 use super::*;
398
399 #[test]
400 fn test_security_level_ordering() {
401 assert!(SecurityLevel::CryptographicallySecure > SecurityLevel::Deterministic);
402 assert!(SecurityLevel::Hardware > SecurityLevel::CryptographicallySecure);
403 }
404
405 #[test]
406 #[cfg(any(feature = "std", feature = "alloc"))]
407 fn test_entropy_source_type_display() {
408 assert_eq!(
409 format!("{}", EntropySourceType::OperatingSystem),
410 "Operating System"
411 );
412 assert_eq!(format!("{}", EntropySourceType::Hardware), "Hardware");
413 }
414
415 #[test]
416 fn test_rng_config_default() {
417 let config = RngConfig::default();
418 assert_eq!(
419 config.security_level,
420 SecurityLevel::CryptographicallySecure
421 );
422 assert!(config.reseed_interval.is_none());
423 }
424
425 #[test]
426 fn test_entropy_config_default() {
427 let config = EntropyConfig::default();
428 #[allow(clippy::float_cmp)]
429 {
430 assert_eq!(config.min_quality, 0.8);
431 }
432 assert!(config.max_per_call.is_none());
433 }
434
435 #[test]
436 fn test_provider_capabilities_default() {
437 let caps = ProviderCapabilities::default();
438 assert!(caps.secure);
439 assert!(!caps.deterministic);
440 assert!(!caps.hardware);
441 assert!(!caps.reseeding);
442 assert!(!caps.custom_entropy);
443 assert!(caps.no_std);
444 assert!(!caps.wasm);
445 }
446}