Better session ID generation code.

This commit is contained in:
flash 2023-02-10 08:06:07 +01:00
parent 8050a295c1
commit dbdaaeec9e
3 changed files with 60 additions and 24 deletions

View File

@ -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) {

View File

@ -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();
}
}
}

View File

@ -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<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);
}
}
}