Rework How Room OPs Are Handled Per Room (if the game server itself isn't handling it, just send it to the room every time)
57 lines
2.3 KiB
C#
57 lines
2.3 KiB
C#
using System.Collections.Concurrent;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
|
|
namespace ReboundEmulator.Core
|
|
{
|
|
public sealed class Account
|
|
{
|
|
public required string ScreenName { get; init; }
|
|
public string ProfileId { get; init; } = "1000000000"; // pfid
|
|
public string Site { get; init; } = "pogo";
|
|
public int Tokens { get; set; } = 9999;
|
|
public string Avatar { get; set; } = "";
|
|
public bool OwnsPremiumAvatar { get; set; } = true; // enti.oava
|
|
public bool OwnsBadges { get; set; } = true; // enti.obad
|
|
}
|
|
|
|
public static class Sessions
|
|
{
|
|
static byte[] _secret = []; // set once at startup
|
|
static readonly ConcurrentDictionary<string, Account> Live = new(StringComparer.OrdinalIgnoreCase);
|
|
|
|
public static void Init(string secret) => _secret = Encoding.UTF8.GetBytes(secret);
|
|
|
|
// lkey = base64url(screenName) + "." + base64url(HMAC(screenName))
|
|
public static string Issue(string screenName)
|
|
{
|
|
var name = Encoding.UTF8.GetBytes(screenName);
|
|
return B64(name) + "." + B64(HMACSHA256.HashData(_secret, name));
|
|
}
|
|
|
|
public static Account? Find(string? lkey)
|
|
{
|
|
if (string.IsNullOrEmpty(lkey)) return null;
|
|
var parts = lkey.Split('.');
|
|
if (parts.Length != 2) return null;
|
|
try
|
|
{
|
|
var name = UnB64(parts[0]);
|
|
if (!CryptographicOperations.FixedTimeEquals(UnB64(parts[1]), HMACSHA256.HashData(_secret, name)))
|
|
return null; // forged or from another secret
|
|
var screenName = Encoding.UTF8.GetString(name);
|
|
// in-memory state for this run; recreated with defaults after a restart
|
|
return Live.GetOrAdd(screenName, n => new Account { ScreenName = n });
|
|
}
|
|
catch (FormatException) { return null; }
|
|
}
|
|
|
|
static string B64(byte[] b) => Convert.ToBase64String(b).TrimEnd('=').Replace('+', '-').Replace('/', '_');
|
|
static byte[] UnB64(string s)
|
|
{
|
|
s = s.Replace('-', '+').Replace('_', '/');
|
|
return Convert.FromBase64String(s + new string('=', (4 - s.Length % 4) % 4));
|
|
}
|
|
}
|
|
}
|