diff --git a/SharpChat/ChatUserSession.cs b/SharpChat/ChatUserSession.cs index c6dc527..d5ae3bd 100644 --- a/SharpChat/ChatUserSession.cs +++ b/SharpChat/ChatUserSession.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Net; namespace SharpChat { - public class ChatUserSession : IDisposable, IPacketTarget { + public class ChatUserSession : IDisposable { public const int ID_LENGTH = 32; #if DEBUG @@ -22,9 +22,6 @@ namespace SharpChat { private int CloseCode { get; set; } = 1000; - public string TargetName => "@log"; - - private IPAddress _RemoteAddress = null; public IPAddress RemoteAddress { @@ -44,13 +41,7 @@ namespace SharpChat { public ChatUserSession(IWebSocketConnection ws) { Connection = ws; - Id = GenerateId(); - } - - private static string GenerateId() { - byte[] buffer = new byte[ID_LENGTH]; - RNG.NextBytes(buffer); - return buffer.GetIdString(); + Id = RNG.SecureRandomString(ID_LENGTH); } public void Send(IServerPacket packet) { diff --git a/SharpChat/Extensions.cs b/SharpChat/Extensions.cs deleted file mode 100644 index 144db14..0000000 --- a/SharpChat/Extensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Text; - -namespace SharpChat { - public static class Extensions { - public static string GetIdString(this byte[] buffer) { - const string id_chars = "abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - StringBuilder sb = new(); - foreach(byte b in buffer) - sb.Append(id_chars[b % id_chars.Length]); - return sb.ToString(); - } - } -} diff --git a/SharpChat/RNG.cs b/SharpChat/RNG.cs index d5d0f11..461096a 100644 --- a/SharpChat/RNG.cs +++ b/SharpChat/RNG.cs @@ -1,8 +1,11 @@ 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(); @@ -21,5 +24,60 @@ namespace SharpChat { 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); + } } }