mirror of
https://github.com/Magnus167/rustframe.git
synced 2025-08-20 04:00:01 +00:00
Merge pull request #65 from Magnus167/win-random
Refactor CryptoRng for cross-platform secure random byte generation
This commit is contained in:
commit
af70f9ffd7
@ -1,21 +1,23 @@
|
|||||||
use std::fs::File;
|
#[cfg(unix)]
|
||||||
use std::io::Read;
|
use std::{fs::File, io::Read};
|
||||||
|
|
||||||
use crate::random::Rng;
|
use crate::random::Rng;
|
||||||
|
|
||||||
/// Cryptographically secure RNG sourcing randomness from `/dev/urandom`.
|
#[cfg(unix)]
|
||||||
pub struct CryptoRng {
|
pub struct CryptoRng {
|
||||||
file: File,
|
file: File,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
impl CryptoRng {
|
impl CryptoRng {
|
||||||
/// Open `/dev/urandom` and create a new generator.
|
/// Open `/dev/urandom`.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let file = File::open("/dev/urandom").expect("failed to open /dev/urandom");
|
let file = File::open("/dev/urandom").expect("failed to open /dev/urandom");
|
||||||
Self { file }
|
Self { file }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
impl Rng for CryptoRng {
|
impl Rng for CryptoRng {
|
||||||
fn next_u64(&mut self) -> u64 {
|
fn next_u64(&mut self) -> u64 {
|
||||||
let mut buf = [0u8; 8];
|
let mut buf = [0u8; 8];
|
||||||
@ -26,6 +28,67 @@ impl Rng for CryptoRng {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub struct CryptoRng;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
impl CryptoRng {
|
||||||
|
/// No handle is needed on Windows.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
impl Rng for CryptoRng {
|
||||||
|
fn next_u64(&mut self) -> u64 {
|
||||||
|
let mut buf = [0u8; 8];
|
||||||
|
win_fill(&mut buf).expect("BCryptGenRandom failed");
|
||||||
|
u64::from_ne_bytes(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fill `buf` with cryptographically secure random bytes using CNG.
|
||||||
|
///
|
||||||
|
/// * `BCryptGenRandom(NULL, buf, len, BCRYPT_USE_SYSTEM_PREFERRED_RNG)`
|
||||||
|
/// asks the OS for its system‑preferred DRBG (CTR_DRBG on modern
|
||||||
|
/// Windows).
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn win_fill(buf: &mut [u8]) -> Result<(), ()> {
|
||||||
|
use core::ffi::c_void;
|
||||||
|
|
||||||
|
type BcryptAlgHandle = *mut c_void;
|
||||||
|
type NTSTATUS = i32;
|
||||||
|
|
||||||
|
const BCRYPT_USE_SYSTEM_PREFERRED_RNG: u32 = 0x0000_0002;
|
||||||
|
|
||||||
|
#[link(name = "bcrypt")]
|
||||||
|
extern "system" {
|
||||||
|
fn BCryptGenRandom(
|
||||||
|
hAlgorithm: BcryptAlgHandle,
|
||||||
|
pbBuffer: *mut u8,
|
||||||
|
cbBuffer: u32,
|
||||||
|
dwFlags: u32,
|
||||||
|
) -> NTSTATUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NT_SUCCESS(status) == status >= 0
|
||||||
|
let status = unsafe {
|
||||||
|
BCryptGenRandom(
|
||||||
|
core::ptr::null_mut(),
|
||||||
|
buf.as_mut_ptr(),
|
||||||
|
buf.len() as u32,
|
||||||
|
BCRYPT_USE_SYSTEM_PREFERRED_RNG,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if status >= 0 {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Convenience constructor for [`CryptoRng`].
|
/// Convenience constructor for [`CryptoRng`].
|
||||||
pub fn crypto_rng() -> CryptoRng {
|
pub fn crypto_rng() -> CryptoRng {
|
||||||
CryptoRng::new()
|
CryptoRng::new()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user