libnzrng/
lib.rs

1/*
2    libNZ - experimental cryptography library
3    Copyright (C) 2021  Sylvain Saucier
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU Affero General Public License as
7    published by the Free Software Foundation, either version 3 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU Affero General Public License for more details.
14
15    You should have received a copy of the GNU Affero General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.
17*/
18
19#![allow(dead_code)]
20
21pub struct Rng {
22  pub s:u64,      //how many bytes have been drawn, unused for block rng
23  pub a:u64,      //a component post factorization
24  pub b:u64,      //b component post factorization
25  pub c:u64,      //c component post factorization
26}
27impl Rng {
28
29  pub fn new( init:Option<[u8;32]> ) -> Rng {
30    let newrng:Rng;
31    let mut eb:[u8;32];
32
33    match init {
34      Some(data) => {
35        eb = data;
36      }
37      None => {
38        eb = [0u8;32];
39        match getrandom::getrandom(&mut eb) {
40          Ok(_x) => {},
41          Err(x) => {panic!("nz::Rng::new() Cannot seed the RNG in a secure manner.\n{:?}", x)}
42        }
43      }
44    };
45
46    let mut bytes = [0u64;4];    
47    bytes[0] = u64::from_be_bytes( [eb[0],  eb[1],  eb[2],  eb[3],  eb[4],  eb[5],  eb[6],  eb[7]] );
48    bytes[1] = u64::from_be_bytes( [eb[8],  eb[9],  eb[10], eb[11], eb[12], eb[13], eb[14], eb[15]] );
49    bytes[2] = u64::from_be_bytes( [eb[16], eb[17], eb[18], eb[19], eb[20], eb[21], eb[22], eb[23]] );
50    bytes[3] = u64::from_be_bytes( [eb[24], eb[25], eb[26], eb[27], eb[28], eb[29], eb[30], eb[31]] );
51
52    newrng = Rng { 
53      a:bytes[0],
54      b:bytes[1],
55      c:bytes[2],
56      s:bytes[3],
57    };
58
59    return newrng;
60  }
61
62  pub fn get(&mut self) -> u64 {
63    let output = self.a ^ self.b ^ self.c;
64    self.s += 1;
65
66    if self.s % 1024 == 0 {
67      let temp = self.a;
68      self.a = self.c;
69      self.c = temp;
70    }
71    if self.s % 64 == 0 {
72      self.b = ( self.b << 13 ) | ( self.b >> ( 64 - 13 ) );
73    }
74
75    self.a = (self.a << 11) | (self.a >> (64 - 11));
76    self.c = ( ( self.c << 17 ) | ( self.c >> ( 64 - 17 ) ) ).wrapping_add(output);
77
78
79
80    return output;
81  }
82
83}