sharp-chat/SharpChatCommon/RNG.cs

84 lines
2.4 KiB
C#
Raw Permalink Normal View History

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() {
return NormalRandom.Next();
2022-08-30 15:00:58 +00:00
}
public static int Next(int max) {
return NormalRandom.Next(max);
2022-08-30 15:00:58 +00:00
}
public static int Next(int min, int max) {
return NormalRandom.Next(min, max);
2022-08-30 15:00:58 +00:00
}
public static void NextBytes(byte[] buffer) {
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
}
}