using System; using System.Buffers; using System.Security.Cryptography; namespace SharpChat { public static class RNG { public const string CHARS = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789"; private static Random NormalRandom { get; } = new(); private static RandomNumberGenerator SecureRandom { get; } = RandomNumberGenerator.Create(); public static int Next() { return NormalRandom.Next(); } public static int Next(int max) { return NormalRandom.Next(max); } public static int Next(int min, int max) { return NormalRandom.Next(min, max); } public static void NextBytes(byte[] buffer) { SecureRandom.GetBytes(buffer); } public static int SecureNext() { return SecureNext(int.MaxValue); } public static int SecureNext(int max) { return SecureNext(0, max); } public static int SecureNext(int min, int max) { --max; if(min == max) return min; uint umax = (uint)max - (uint)min; uint num; byte[] buffer = ArrayPool.Shared.Rent(4); try { SecureRandom.GetBytes(buffer); num = BitConverter.ToUInt32(buffer); if(umax != uint.MaxValue) { ++umax; if((umax & (umax - 1)) != 0) { uint limit = uint.MaxValue - (uint.MaxValue & umax) - 1; while(num > limit) { SecureRandom.GetBytes(buffer); num = BitConverter.ToUInt32(buffer); } } } } finally { ArrayPool.Shared.Return(buffer); } return (int)((num % umax) + min); } private static string RandomStringInternal(Func next, int length) { char[] str = new char[length]; for(int i = 0; i < length; ++i) str[i] = CHARS[next(CHARS.Length)]; return new string(str); } public static string RandomString(int length) { return RandomStringInternal(Next, length); } public static string SecureRandomString(int length) { return RandomStringInternal(SecureNext, length); } } }