libnzrng 1.0.0

Pseudo random number generator library
Documentation
/*
    libNZ - experimental cryptography library
    Copyright (C) 2021  Sylvain Saucier

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

#![allow(dead_code)]

pub struct Rng {
  pub s:u64,      //how many bytes have been drawn, unused for block rng
  pub a:u64,      //a component post factorization
  pub b:u64,      //b component post factorization
  pub c:u64,      //c component post factorization
}
impl Rng {

  pub fn new( init:Option<[u8;32]> ) -> Rng {
    let newrng:Rng;
    let mut eb:[u8;32];

    match init {
      Some(data) => {
        eb = data;
      }
      None => {
        eb = [0u8;32];
        match getrandom::getrandom(&mut eb) {
          Ok(_x) => {},
          Err(x) => {panic!("nz::Rng::new() Cannot seed the RNG in a secure manner.\n{:?}", x)}
        }
      }
    };

    let mut bytes = [0u64;4];    
    bytes[0] = u64::from_be_bytes( [eb[0],  eb[1],  eb[2],  eb[3],  eb[4],  eb[5],  eb[6],  eb[7]] );
    bytes[1] = u64::from_be_bytes( [eb[8],  eb[9],  eb[10], eb[11], eb[12], eb[13], eb[14], eb[15]] );
    bytes[2] = u64::from_be_bytes( [eb[16], eb[17], eb[18], eb[19], eb[20], eb[21], eb[22], eb[23]] );
    bytes[3] = u64::from_be_bytes( [eb[24], eb[25], eb[26], eb[27], eb[28], eb[29], eb[30], eb[31]] );

    newrng = Rng { 
      a:bytes[0],
      b:bytes[1],
      c:bytes[2],
      s:bytes[3],
    };

    return newrng;
  }

  pub fn get(&mut self) -> u64 {
    let output = self.a ^ self.b ^ self.c;
    self.s += 1;

    if self.s % 1024 == 0 {
      let temp = self.a;
      self.a = self.c;
      self.c = temp;
    }
    if self.s % 64 == 0 {
      self.b = ( self.b << 13 ) | ( self.b >> ( 64 - 13 ) );
    }

    self.a = (self.a << 11) | (self.a >> (64 - 11));
    self.c = ( ( self.c << 17 ) | ( self.c >> ( 64 - 17 ) ) ).wrapping_add(output);



    return output;
  }

}