1use crate::MemSecurityResult;
2use borsh::{BorshDeserialize, BorshSerialize};
3use rand_chacha::ChaCha20Rng;
4use rand_core::{RngCore, SeedableRng};
5use std::ops::{Add, Sub};
6use zeroize::Zeroize;
7
8pub struct CsprngArraySimple;
10
11impl CsprngArraySimple {
12 pub fn gen_u8_byte() -> u8 {
19 CsprngArray::<1>::gen().0[0]
20 }
21 pub fn gen_u8_array() -> CsprngArray<8> {
29 CsprngArray::<8>::gen()
30 }
31
32 pub fn gen_u16_array() -> CsprngArray<16> {
40 CsprngArray::<16>::gen()
41 }
42
43 pub fn gen_u24_array() -> CsprngArray<24> {
51 CsprngArray::<24>::gen()
52 }
53
54 pub fn gen_u32_array() -> CsprngArray<32> {
62 CsprngArray::<32>::gen()
63 }
64
65 pub fn gen_u64_array() -> CsprngArray<64> {
73 CsprngArray::<64>::gen()
74 }
75}
76
77#[derive(BorshSerialize, BorshDeserialize)]
89pub struct CsprngArray<const N: usize>([u8; N]);
90
91impl<const N: usize> AsRef<[u8]> for CsprngArray<N> {
92 fn as_ref(&self) -> &[u8] {
93 self.expose_borrowed()
94 }
95}
96
97impl<const N: usize> CsprngArray<N> {
98 pub fn gen() -> Self {
105 let mut rng = ChaCha20Rng::from_entropy();
106 let mut buffer = [0u8; N];
107 rng.fill_bytes(&mut buffer);
108
109 let outcome = CsprngArray(buffer);
110
111 buffer.fill(0);
112
113 outcome
114 }
115
116 pub fn take(mut self, buffer: &mut [u8; N]) -> MemSecurityResult<()> {
118 let found = buffer.len();
120
121 if found != N {
122 Err(crate::MemSecurityErr::InvalidArrayLength { expected: N, found })
123 } else {
124 buffer[0..N].copy_from_slice(&self.0);
125
126 self.zeroize();
127
128 Ok(())
129 }
130 }
131
132 pub fn take_zeroize_on_error(mut self, buffer: &mut [u8; N]) -> MemSecurityResult<()> {
134 let found = buffer.len();
135
136 if found != N {
137 self.zeroize();
138
139 Err(crate::MemSecurityErr::InvalidArrayLength { expected: N, found })
140 } else {
141 buffer[0..N].copy_from_slice(&self.0);
142
143 self.zeroize();
144
145 Ok(())
146 }
147 }
148
149 pub fn expose(&self) -> [u8; N] {
152 self.0
153 }
154
155 pub fn expose_borrowed(&self) -> &[u8] {
158 self.0.as_ref()
159 }
160
161 #[cfg(debug_assertions)]
164 pub fn dangerous_debug(&self) -> &[u8; N] {
165 &self.0
166 }
167}
168
169impl<const N: usize> Zeroize for CsprngArray<N> {
170 fn zeroize(&mut self) {
171 self.0.fill(0);
172
173 assert_eq!(self.0, [0u8; N]); }
175}
176
177impl<const N: usize> core::fmt::Debug for CsprngArray<N> {
178 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
179 f.debug_struct("CsprngArray(REDACTED)").finish()
180 }
181}
182
183impl<const N: usize> core::fmt::Display for CsprngArray<N> {
184 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
185 f.debug_struct("CsprngArray(REDACTED)").finish()
186 }
187}
188
189impl<const N: usize> Drop for CsprngArray<N> {
190 fn drop(&mut self) {
191 self.zeroize()
192 }
193}
194
195pub trait MinMaxNum: PartialOrd + Add + Sub + Copy {
210 const MIN_VALUE: Self;
212 const MAX_VALUE: Self;
214}
215
216impl MinMaxNum for u8 {
217 const MIN_VALUE: u8 = core::u8::MIN;
218 const MAX_VALUE: u8 = core::u8::MAX;
219}
220
221impl MinMaxNum for u16 {
222 const MIN_VALUE: u16 = core::u16::MIN;
223 const MAX_VALUE: u16 = core::u16::MAX;
224}
225
226impl MinMaxNum for u32 {
227 const MIN_VALUE: u32 = core::u32::MIN;
228 const MAX_VALUE: u32 = core::u32::MAX;
229}
230
231impl MinMaxNum for u64 {
232 const MIN_VALUE: u64 = core::u64::MIN;
233 const MAX_VALUE: u64 = core::u64::MAX;
234}
235
236impl MinMaxNum for u128 {
237 const MIN_VALUE: u128 = core::u128::MIN;
238 const MAX_VALUE: u128 = core::u128::MAX;
239}
240
241impl MinMaxNum for f32 {
242 const MIN_VALUE: f32 = core::f32::MIN;
243 const MAX_VALUE: f32 = core::f32::MAX;
244}
245
246impl MinMaxNum for f64 {
247 const MIN_VALUE: f64 = core::f64::MIN;
248 const MAX_VALUE: f64 = core::f64::MAX;
249}
250
251impl MinMaxNum for i8 {
252 const MIN_VALUE: i8 = core::i8::MIN;
253 const MAX_VALUE: i8 = core::i8::MAX;
254}
255
256impl MinMaxNum for i16 {
257 const MIN_VALUE: i16 = core::i16::MIN;
258 const MAX_VALUE: i16 = core::i16::MAX;
259}
260
261impl MinMaxNum for i32 {
262 const MIN_VALUE: i32 = core::i32::MIN;
263 const MAX_VALUE: i32 = core::i32::MAX;
264}
265
266impl MinMaxNum for i64 {
267 const MIN_VALUE: i64 = core::i64::MIN;
268 const MAX_VALUE: i64 = core::i64::MAX;
269}
270
271impl MinMaxNum for i128 {
272 const MIN_VALUE: i128 = core::i128::MIN;
273 const MAX_VALUE: i128 = core::i128::MAX;
274}