<PackageReference Include="SSH.NET" Version="2023.0.1" />

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); } } }