DigestRandomGenerator
using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Utilities;
namespace Renci.SshNet.Security.Org.BouncyCastle.Crypto.Prng
{
    internal class DigestRandomGenerator : IRandomGenerator
    {
        private const long CYCLE_COUNT = 10;
        private long stateCounter;
        private long seedCounter;
        private IDigest digest;
        private byte[] state;
        private byte[] seed;
        public DigestRandomGenerator(IDigest digest)
        {
            this.digest = digest;
            seed = new byte[digest.GetDigestSize()];
            seedCounter = 1;
            state = new byte[digest.GetDigestSize()];
            stateCounter = 1;
        }
        public void AddSeedMaterial(byte[] inSeed)
        {
            lock (this) {
                DigestUpdate(inSeed);
                DigestUpdate(seed);
                DigestDoFinal(seed);
            }
        }
        public void AddSeedMaterial(long rSeed)
        {
            lock (this) {
                DigestAddCounter(rSeed);
                DigestUpdate(seed);
                DigestDoFinal(seed);
            }
        }
        public void NextBytes(byte[] bytes)
        {
            NextBytes(bytes, 0, bytes.Length);
        }
        public void NextBytes(byte[] bytes, int start, int len)
        {
            lock (this) {
                int num = 0;
                GenerateState();
                int num2 = start + len;
                for (int i = start; i < num2; i++) {
                    if (num == state.Length) {
                        GenerateState();
                        num = 0;
                    }
                    bytes[i] = state[num++];
                }
            }
        }
        private void CycleSeed()
        {
            DigestUpdate(seed);
            DigestAddCounter(seedCounter++);
            DigestDoFinal(seed);
        }
        private void GenerateState()
        {
            DigestAddCounter(stateCounter++);
            DigestUpdate(state);
            DigestUpdate(seed);
            DigestDoFinal(state);
            if (stateCounter % 10 == 0)
                CycleSeed();
        }
        private void DigestAddCounter(long seedVal)
        {
            byte[] array = new byte[8];
            Pack.UInt64_To_LE((ulong)seedVal, array);
            digest.BlockUpdate(array, 0, array.Length);
        }
        private void DigestUpdate(byte[] inSeed)
        {
            digest.BlockUpdate(inSeed, 0, inSeed.Length);
        }
        private void DigestDoFinal(byte[] result)
        {
            digest.DoFinal(result, 0);
        }
    }
}