//
// sha1prng.cxx
// 
// A pseudo-random number generator based on the NIST/NSA's Secure
// Hash Algorithm using an specified in Section 3.1 of FIPS186
//
// this implementation
// Copyright (C) 1996-7 by Leonard Janke (janke@unixg.ubc.ca)

#include <lmisc/lmisc.hxx>
#include <prng/sha1prng.hxx>
#include <chnhash/sha1.hxx>
#include <cstring>

const u32 SHA1PRNG::t[5]={ SHA::H0, SHA::H1, SHA::H2, SHA::H3, SHA::H4 };

SHA1PRNG::SHA1PRNG(const void* pS, const int preSeedSize) : PRNG(20)
{
  SHA1* hashor=new SHA1;
  const u8* preSeed=(const u8*) pS;

  for (int i=0; i<preSeedSize/64; i++)
    hashor->ProcessMiddleBlock(preSeed+64*i);

  hashor->ProcessFinalBlock(preSeed+64*(preSeedSize/64),preSeedSize%64);

  hashor->ChainVariables(_seed);
  delete hashor;

  LMisc::MemSwap(_seed,5);
  LMisc::MemZero(_seed+5,11);

  SHA1::CompressBlock(t,_seed,_compressedSeed);

  AddMod160(_seed,_compressedSeed,_seed);
  IncMod160(_seed);

  LMisc::MemSwap(_compressedSeed,5);
  memcpy(_buffer,_compressedSeed,20);
}

SHA1PRNG::~SHA1PRNG()
{
}

void SHA1PRNG::RefillBuffer()
{
  SHA1::CompressBlock(t,_seed,_compressedSeed);

  AddMod160(_seed,_compressedSeed,_seed);
  IncMod160(_seed);

  LMisc::MemSwap(_compressedSeed,5);
  memcpy(_buffer,_compressedSeed,20);
}

