#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) #pragma warning disable using System; using System.Collections.Generic; using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities; namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng.Drbg { internal class DrbgUtilities { private static readonly IDictionary MaxSecurityStrengths = new Dictionary(StringComparer.OrdinalIgnoreCase); static DrbgUtilities() { MaxSecurityStrengths.Add("SHA-1", 128); MaxSecurityStrengths.Add("SHA-224", 192); MaxSecurityStrengths.Add("SHA-256", 256); MaxSecurityStrengths.Add("SHA-384", 256); MaxSecurityStrengths.Add("SHA-512", 256); MaxSecurityStrengths.Add("SHA-512/224", 192); MaxSecurityStrengths.Add("SHA-512/256", 256); } internal static int GetMaxSecurityStrength(IDigest d) { return MaxSecurityStrengths[d.AlgorithmName]; } internal static int GetMaxSecurityStrength(IMac m) { string name = m.AlgorithmName; return MaxSecurityStrengths[name.Substring(0, name.IndexOf("/"))]; } /** * Used by both Dual EC and Hash. */ #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER internal static void HashDF(IDigest digest, ReadOnlySpan seedMaterial, int seedLength, Span output) #else internal static void HashDF(IDigest digest, byte[] seedMaterial, int seedLength, byte[] output) #endif { // 1. temp = the Null string. // 2. . // 3. counter = an 8-bit binary value representing the integer "1". // 4. For i = 1 to len do // Comment : In step 4.1, no_of_bits_to_return // is used as a 32-bit string. // 4.1 temp = temp || Hash (counter || no_of_bits_to_return || // input_string). // 4.2 counter = counter + 1. // 5. requested_bits = Leftmost (no_of_bits_to_return) of temp. // 6. Return SUCCESS and requested_bits. int outputLength = (seedLength + 7) / 8; int digestSize = digest.GetDigestSize(); int len = outputLength / digestSize; int counter = 1; #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER Span dig = digestSize <= 128 ? stackalloc byte[digestSize] : new byte[digestSize]; Span header = stackalloc byte[5]; Pack.UInt32_To_BE((uint)seedLength, header[1..]); #else byte[] dig = new byte[digestSize]; byte[] header = new byte[5]; Pack.UInt32_To_BE((uint)seedLength, header, 1); #endif for (int i = 0; i <= len; i++, counter++) { header[0] = (byte)counter; #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER digest.BlockUpdate(header); digest.BlockUpdate(seedMaterial); digest.DoFinal(dig); int bytesToCopy = System.Math.Min(digestSize, outputLength - i * digestSize); dig[..bytesToCopy].CopyTo(output[(i * digestSize)..]); #else digest.BlockUpdate(header, 0, header.Length); digest.BlockUpdate(seedMaterial, 0, seedMaterial.Length); digest.DoFinal(dig, 0); int bytesToCopy = System.Math.Min(digestSize, outputLength - i * digestSize); Array.Copy(dig, 0, output, i * digestSize, bytesToCopy); #endif } // do a left shift to get rid of excess bits. if (seedLength % 8 != 0) { int shift = 8 - (seedLength % 8); uint carry = 0; for (int i = 0; i != outputLength; i++) { uint b = output[i]; output[i] = (byte)((b >> shift) | (carry << (8 - shift))); carry = b; } } } } } #pragma warning restore #endif