This commit is contained in:
gamer147
2024-09-05 08:32:54 -04:00
parent 8d62c9f238
commit ee7e276036
45 changed files with 1506 additions and 0 deletions

View File

@@ -0,0 +1,152 @@
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
namespace SVSim.EmulatedEntrypoint.Security;
/// <summary>
/// Helper class for encrypting/decrypting requests bodies and responses to/from the game client.
/// </summary>
public static class Encryption
{
private const int EncryptionKeySize = 256;
private const int EncryptionBlockSize = 128;
private const CipherMode EncryptionMode = CipherMode.CBC;
private const int UdIdKeySize = 16;
private const int KeyStringSize = 32;
private const int EncodingValueOffset = 10;
/// <summary>
/// Encrypts an array of bytes using RJ256 with a subset of the user's UdId as the key.
/// </summary>
/// <param name="sourceData">the data to encrypt</param>
/// <param name="udId">the UdId of the user this data is encrypted for</param>
/// <returns>the encrypted bytes</returns>
public static byte[] Encrypt(byte[] sourceData, string udId)
{
using (var rj = Aes.Create())
{
rj.KeySize = EncryptionKeySize;
rj.Mode = EncryptionMode;
rj.BlockSize = EncryptionBlockSize;
string keyString = GenerateKeyString();
string udIdKey = udId.Replace("-", string.Empty).Substring(0, UdIdKeySize);
byte[] keyStringBytes = Encoding.UTF8.GetBytes(keyString);
byte[] rgbIV = Encoding.UTF8.GetBytes(udIdKey);
ICryptoTransform transform = rj.CreateEncryptor(keyStringBytes, rgbIV);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write))
{
cs.Write(sourceData);
cs.FlushFinalBlock();
byte[] encryptedResults = ms.ToArray();
byte[] encryptedResultsAndKey = new byte[encryptedResults.Length + keyStringBytes.Length];
Array.Copy(encryptedResults, 0, encryptedResultsAndKey, 0, encryptedResults.Length);
Array.Copy(keyStringBytes, 0, encryptedResultsAndKey, encryptedResults.Length, keyStringBytes.Length);
return encryptedResultsAndKey;
}
}
}
}
/// <summary>
/// Decrypts data that has been encrypted with the given UdId.
/// </summary>
/// <param name="encryptedData">Previously encrypted data</param>
/// <param name="udId">The UdId previously used to encrypt the data</param>
/// <returns>the decrypted bytes</returns>
public static byte[] Decrypt(byte[] encryptedData, string udId)
{
using (var rj = Aes.Create())
{
rj.KeySize = EncryptionKeySize;
rj.Mode = EncryptionMode;
rj.BlockSize = EncryptionBlockSize;
byte[] rgbIv = Encoding.UTF8.GetBytes(udId.Replace("-", string.Empty).Substring(0, UdIdKeySize));
byte[] keyBytes = new byte[KeyStringSize];
byte[] encryptedValueBytes = new byte[encryptedData.Length - KeyStringSize];
Array.Copy(encryptedData, encryptedData.Length - keyBytes.Length, keyBytes, 0, keyBytes.Length);
Array.Copy(encryptedData, 0, encryptedValueBytes, 0, encryptedValueBytes.Length);
ICryptoTransform transform = rj.CreateDecryptor(keyBytes, rgbIv);
using (MemoryStream ms = new MemoryStream(encryptedValueBytes))
{
using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Read))
{
byte[] decryptedValueBytes = new byte[encryptedValueBytes.Length];
cs.Read(decryptedValueBytes, 0, encryptedValueBytes.Length);
cs.FlushFinalBlock();
return decryptedValueBytes;
}
}
}
}
public static string Encode(string sourceData)
{
int length = sourceData.Length;
string encodeBuf = $"{length:x4}";
foreach (char value in sourceData)
{
encodeBuf += $"{GetRandom(),1:x}";
encodeBuf += $"{GetRandom(),1:x}";
encodeBuf += ((char)(Convert.ToInt32(value) + EncodingValueOffset)).ToString();
encodeBuf += $"{GetRandom(),1:x}";
}
encodeBuf += GenerateIvString();
return encodeBuf;
}
public static string? Decode(string? encodedData)
{
if (encodedData == null || encodedData.Length < 4)
{
return encodedData;
}
int num = int.Parse(encodedData.Substring(0, 4), NumberStyles.AllowHexSpecifier);
string text = "";
int num2 = 2;
foreach (char value in encodedData.Substring(4, encodedData.Length - 4))
{
if (num2 % 4 == 0)
{
text += ((char)(Convert.ToInt32(value) - EncodingValueOffset)).ToString();
}
num2++;
if (text.Length >= num)
{
break;
}
}
return text;
}
// TODO Clean this up and de-magic number it
private static string GenerateIvString()
{
string text = "";
for (int i = 0; i < KeyStringSize; i++)
{
text += $"{GetRandom()}";
}
return text;
}
private static string GenerateKeyString()
{
string text = "";
for (int i = 0; i < KeyStringSize; i++)
{
text += $"{Random.Shared.Next(0, ushort.MaxValue):x}";
}
return Convert.ToBase64String(Encoding.ASCII.GetBytes(text)).Substring(0, KeyStringSize);
}
private static int GetRandom()
{
const int MinRandomValue = 1;
const int MaxRandomValue = 9;
return Random.Shared.Next(MinRandomValue, MaxRandomValue);
}
}

View File

@@ -0,0 +1,8 @@
using Microsoft.AspNetCore.Authentication;
namespace SVSim.EmulatedEntrypoint.Security.SteamSessionAuthentication;
public class SteamAuthenticationHandlerOptions : AuthenticationSchemeOptions
{
}

View File

@@ -0,0 +1,21 @@
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
namespace SVSim.EmulatedEntrypoint.Security.SteamSessionAuthentication;
public class SteamSessionAuthenticationHandler : AuthenticationHandler<SteamAuthenticationHandlerOptions>
{
public SteamSessionAuthenticationHandler(IOptionsMonitor<SteamAuthenticationHandlerOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{
}
public SteamSessionAuthenticationHandler(IOptionsMonitor<SteamAuthenticationHandlerOptions> options, ILoggerFactory logger, UrlEncoder encoder) : base(options, logger, encoder)
{
}
protected async override Task<AuthenticateResult> HandleAuthenticateAsync()
{
return AuthenticateResult.Fail("Not implemented");
}
}