#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) #pragma warning disable using System; using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters; using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities; namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators { /// Generator for MGF1 as defined in Pkcs 1v2 public sealed class Mgf1BytesGenerator : IDerivationFunction { private readonly IDigest m_digest; private readonly int m_hLen; private byte[] m_buffer; /// the digest to be used as the source of generated bytes public Mgf1BytesGenerator(IDigest digest) { m_digest = digest; m_hLen = digest.GetDigestSize(); } public void Init(IDerivationParameters parameters) { if (!(parameters is MgfParameters mgfParameters)) throw new ArgumentException("MGF parameters required for MGF1Generator"); m_buffer = new byte[mgfParameters.SeedLength + 4 + m_hLen]; mgfParameters.GetSeed(m_buffer, 0); } /// the underlying digest. public IDigest Digest => m_digest; /// Fill len bytes of the output buffer with bytes generated from the derivation function. /// public int GenerateBytes(byte[] output, int outOff, int length) { Check.OutputLength(output, outOff, length, "output buffer too small"); #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER return GenerateBytes(output.AsSpan(outOff, length)); #else int hashPos = m_buffer.Length - m_hLen; int counterPos = hashPos - 4; uint counter = 0; m_digest.Reset(); int end = outOff + length; int limit = end - m_hLen; while (outOff <= limit) { Pack.UInt32_To_BE(counter++, m_buffer, counterPos); m_digest.BlockUpdate(m_buffer, 0, hashPos); m_digest.DoFinal(output, outOff); outOff += m_hLen; } if (outOff < end) { Pack.UInt32_To_BE(counter, m_buffer, counterPos); m_digest.BlockUpdate(m_buffer, 0, hashPos); m_digest.DoFinal(m_buffer, hashPos); Array.Copy(m_buffer, hashPos, output, outOff, end - outOff); } return length; #endif } #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER public int GenerateBytes(Span output) { int hashPos = m_buffer.Length - m_hLen; int counterPos = hashPos - 4; uint counter = 0; m_digest.Reset(); int pos = 0, length = output.Length, limit = length - m_hLen; while (pos <= limit) { Pack.UInt32_To_BE(counter++, m_buffer.AsSpan(counterPos)); m_digest.BlockUpdate(m_buffer.AsSpan(0, hashPos)); m_digest.DoFinal(output[pos..]); pos += m_hLen; } if (pos < length) { Pack.UInt32_To_BE(counter, m_buffer.AsSpan(counterPos)); m_digest.BlockUpdate(m_buffer.AsSpan(0, hashPos)); m_digest.DoFinal(m_buffer.AsSpan(hashPos)); m_buffer.AsSpan(hashPos, length - pos).CopyTo(output[pos..]); } return length; } #endif } } #pragma warning restore #endif