1+ use sha2:: { Sha256 , Digest } ;
2+ use rand:: { CryptoRng , Error , RngCore } ;
3+ use num_bigint:: BigUint ;
4+ use num_traits:: One ;
5+
6+ pub struct TestDRNG {
7+ seed : [ u8 ; 32 ] ,
8+ }
9+
10+ impl TestDRNG {
11+ pub fn new ( seed : & [ u8 ] ) -> Self {
12+ let mut hasher = Sha256 :: new ( ) ;
13+ hasher. update ( seed) ;
14+ let result = hasher. finalize ( ) ;
15+ let mut seed_bytes = [ 0u8 ; 32 ] ;
16+ seed_bytes. copy_from_slice ( & result) ;
17+ Self { seed : seed_bytes }
18+ }
19+
20+ pub fn randint ( & mut self , l : u64 , h : u64 ) -> u64 {
21+ assert ! ( l <= h) ;
22+ let range = h - l + 1 ;
23+ let bits = 64 - range. leading_zeros ( ) ;
24+ let bytes_needed = ( ( bits + 7 ) / 8 ) as usize ;
25+
26+ loop {
27+ let mut buf = vec ! [ 0u8 ; bytes_needed] ;
28+ self . fill_bytes ( & mut buf) ;
29+ let mut val = 0u64 ;
30+ for b in buf {
31+ val = ( val << 8 ) | b as u64 ;
32+ }
33+ if val < ( 1u64 << bits) {
34+ return l + ( val % range) ;
35+ }
36+ }
37+ }
38+
39+ pub fn randint_big ( & mut self , l : & BigUint , h : & BigUint ) -> BigUint {
40+ assert ! ( l <= h) ;
41+ let range = h - l + BigUint :: one ( ) ;
42+ let bits = range. bits ( ) ;
43+ let bytes_needed = ( ( bits + 7 ) / 8 ) as usize ;
44+
45+ loop {
46+ let mut buf = vec ! [ 0u8 ; bytes_needed] ;
47+ self . fill_bytes ( & mut buf) ;
48+ let val = BigUint :: from_bytes_be ( & buf) ;
49+ if val. bits ( ) <= bits {
50+ return l + ( val % & range) ;
51+ }
52+ }
53+ }
54+ }
55+
56+ impl RngCore for TestDRNG {
57+ fn next_u32 ( & mut self ) -> u32 {
58+ let val = u32:: from_be_bytes ( [ self . seed [ 0 ] , self . seed [ 1 ] , self . seed [ 2 ] , self . seed [ 3 ] ] ) ;
59+ let mut hasher = Sha256 :: new ( ) ;
60+ hasher. update ( val. to_be_bytes ( ) ) ;
61+ let result = hasher. finalize ( ) ;
62+ self . seed . copy_from_slice ( & result) ;
63+ val
64+ }
65+
66+ fn next_u64 ( & mut self ) -> u64 {
67+ ( ( self . next_u32 ( ) as u64 ) << 32 ) | ( self . next_u32 ( ) as u64 )
68+ }
69+
70+ fn fill_bytes ( & mut self , dest : & mut [ u8 ] ) {
71+ let mut i = 0 ;
72+ while i < dest. len ( ) {
73+ let rand = self . next_u32 ( ) . to_be_bytes ( ) ;
74+ for b in rand. iter ( ) {
75+ if i < dest. len ( ) {
76+ dest[ i] = * b;
77+ i += 1 ;
78+ } else {
79+ break ;
80+ }
81+ }
82+ }
83+ }
84+
85+ fn try_fill_bytes ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
86+ self . fill_bytes ( dest) ;
87+ Ok ( ( ) )
88+ }
89+ }
90+
91+ impl CryptoRng for TestDRNG { }
0 commit comments