2022-08-30 15:00:58 +00:00
|
|
|
|
using System;
|
2023-02-10 07:06:07 +00:00
|
|
|
|
using System.Buffers;
|
2022-08-30 15:00:58 +00:00
|
|
|
|
using System.Security.Cryptography;
|
|
|
|
|
|
|
|
|
|
namespace SharpChat {
|
|
|
|
|
public static class RNG {
|
2023-02-10 07:06:07 +00:00
|
|
|
|
public const string CHARS = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789";
|
|
|
|
|
|
2023-02-07 15:01:56 +00:00
|
|
|
|
private static Random NormalRandom { get; } = new();
|
2022-08-30 15:00:58 +00:00
|
|
|
|
private static RandomNumberGenerator SecureRandom { get; } = RandomNumberGenerator.Create();
|
|
|
|
|
|
|
|
|
|
public static int Next() {
|
2023-02-10 06:07:59 +00:00
|
|
|
|
return NormalRandom.Next();
|
2022-08-30 15:00:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Next(int max) {
|
2023-02-10 06:07:59 +00:00
|
|
|
|
return NormalRandom.Next(max);
|
2022-08-30 15:00:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Next(int min, int max) {
|
2023-02-10 06:07:59 +00:00
|
|
|
|
return NormalRandom.Next(min, max);
|
2022-08-30 15:00:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void NextBytes(byte[] buffer) {
|
2023-02-10 06:07:59 +00:00
|
|
|
|
SecureRandom.GetBytes(buffer);
|
2022-08-30 15:00:58 +00:00
|
|
|
|
}
|
2023-02-10 07:06:07 +00:00
|
|
|
|
|
|
|
|
|
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<byte>.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<byte>.Shared.Return(buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (int)((num % umax) + min);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string RandomStringInternal(Func<int, int> 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);
|
|
|
|
|
}
|
2022-08-30 15:00:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|