1
0
mirror of synced 2024-11-23 22:41:01 +01:00

Update to support encrypted datatables, all on server side

This commit is contained in:
asesidaa 2023-10-05 02:09:37 +08:00
parent bc6f65f4a0
commit 0d3b575903
4 changed files with 80 additions and 60 deletions

View File

@ -10,11 +10,14 @@ public static class Constants
public const string DEFAULT_DB_NAME = "taiko.db3";
public const string MUSIC_INFO_FILE_NAME = "musicinfo.json";
public const string MUSIC_INFO_COMPRESSED_FILE_NAME = "musicinfo.bin";
public const string MUSIC_ATTRIBUTE_FILE_NAME = "music_attribute.json";
public const string MUSIC_INFO_BASE_NAME = "musicinfo";
public const string MUSIC_ATTRIBUTE_BASE_NAME = "music_attribute";
public const string MUSIC_ATTRIBUTE_COMPRESSED_FILE_NAME = "music_attribute.bin";
public const string WORDLIST_BASE_NAME = "wordlist";
public const string MUSIC_ORDER_BASE_NAME = "music_order";
public const string DAN_DATA_FILE_NAME = "dan_data.json";
public const string INTRO_DATA_FILE_NAME = "intro_data.json";

View File

@ -4,6 +4,8 @@ using SharedProject.Models;
using SharedProject.Utils;
using Swan.Mapping;
using System.Collections.Immutable;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text.Json;
using TaikoLocalServer.Settings;
using Throw;
@ -120,10 +122,19 @@ public class GameDataService : IGameDataService
public async Task InitializeAsync()
{
var dataPath = PathHelper.GetDataPath();
var musicInfoPath = Path.Combine(dataPath, Constants.MUSIC_INFO_FILE_NAME);
var compressedMusicInfoPath = Path.Combine(dataPath, Constants.MUSIC_INFO_COMPRESSED_FILE_NAME);
var musicAttributePath = Path.Combine(dataPath, Constants.MUSIC_ATTRIBUTE_FILE_NAME);
var compressedMusicAttributePath = Path.Combine(dataPath, Constants.MUSIC_ATTRIBUTE_COMPRESSED_FILE_NAME);
var musicInfoPath = Path.Combine(dataPath, $"{Constants.MUSIC_INFO_BASE_NAME}.json");
var enctyptedInfo = Path.Combine(dataPath, $"{Constants.MUSIC_INFO_BASE_NAME}.bin");
var musicAttributePath = Path.Combine(dataPath, $"{Constants.MUSIC_ATTRIBUTE_BASE_NAME}.json");
var encryptedAttribute = Path.Combine(dataPath, $"{Constants.MUSIC_ATTRIBUTE_BASE_NAME}.bin");
var wordlistPath = Path.Combine(dataPath, $"{Constants.WORDLIST_BASE_NAME}.json");
var encryptedWordlist = Path.Combine(dataPath, $"{Constants.WORDLIST_BASE_NAME}.bin");
var musicOrderPath = Path.Combine(dataPath, $"{Constants.MUSIC_ORDER_BASE_NAME}.json");
var encryptedMusicOrder = Path.Combine(dataPath, $"{Constants.MUSIC_ORDER_BASE_NAME}.bin");
var danDataPath = Path.Combine(dataPath, settings.DanDataFileName);
var gaidenDataPath = Path.Combine(dataPath, settings.GaidenDataFileName);
var songIntroDataPath = Path.Combine(dataPath, settings.IntroDataFileName);
@ -134,14 +145,32 @@ public class GameDataService : IGameDataService
var lockedSongsDataPath = Path.Combine(dataPath, settings.LockedSongsDataFileName);
var qrCodeDataPath = Path.Combine(dataPath, settings.QRCodeDataFileName);
if (File.Exists(compressedMusicInfoPath))
if (File.Exists(enctyptedInfo))
{
TryDecompressMusicInfo();
DecryptDataTable(enctyptedInfo, musicInfoPath);
}
if (File.Exists(compressedMusicAttributePath))
if (File.Exists(encryptedAttribute))
{
TryDecompressMusicAttribute();
DecryptDataTable(encryptedAttribute, musicAttributePath);
}
if (File.Exists(encryptedWordlist))
{
DecryptDataTable(encryptedWordlist, wordlistPath);
}
if (File.Exists(encryptedMusicOrder))
{
DecryptDataTable(encryptedMusicOrder, musicOrderPath);
}
if (!File.Exists(wordlistPath))
{
throw new FileNotFoundException("Wordlist file not found!");
}
if (!File.Exists(musicOrderPath))
{
throw new FileNotFoundException("Music order file not found!");
}
await using var musicInfoFile = File.OpenRead(musicInfoPath);
await using var musicAttributeFile = File.OpenRead(musicAttributePath);
await using var danDataFile = File.OpenRead(danDataPath);
@ -189,29 +218,26 @@ public class GameDataService : IGameDataService
InitializeQRCodeData(qrCodeData);
}
private static void TryDecompressMusicInfo()
private static void DecryptDataTable(string inputFileName, string outputFileName)
{
var dataPath = PathHelper.GetDataPath();
var musicInfoPath = Path.Combine(dataPath, Constants.MUSIC_INFO_FILE_NAME);
var compressedMusicInfoPath = Path.Combine(dataPath, Constants.MUSIC_INFO_COMPRESSED_FILE_NAME);
using var compressed = File.Open(compressedMusicInfoPath, FileMode.Open);
using var output = File.Create(musicInfoPath);
GZip.Decompress(compressed, output, true);
}
private static void TryDecompressMusicAttribute()
{
var dataPath = PathHelper.GetDataPath();
var musicAttributePath = Path.Combine(dataPath, Constants.MUSIC_ATTRIBUTE_FILE_NAME);
var compressedMusicAttributePath = Path.Combine(dataPath, Constants.MUSIC_ATTRIBUTE_COMPRESSED_FILE_NAME);
using var compressed = File.Open(compressedMusicAttributePath, FileMode.Open);
using var output = File.Create(musicAttributePath);
GZip.Decompress(compressed, output, true);
}
var aes = Aes.Create();
aes.Mode = CipherMode.CBC;
aes.KeySize = 256;
aes.Padding = PaddingMode.PKCS7;
aes.Key = Convert.FromHexString("3530304242323633353537423431384139353134383346433246464231354534");
var iv = new byte[16];
using var fs = File.OpenRead(inputFileName);
var count = fs.Read(iv, 0, 16);
count.Throw("Read IV for datatable failed!").IfNotEquals(16);
aes.IV = iv;
using var cs = new CryptoStream(fs, aes.CreateDecryptor(), CryptoStreamMode.Read);
using var ms = new MemoryStream();
cs.CopyTo(ms);
ms.Position = 0;
using var gz = new GZipStream(ms, CompressionMode.Decompress);
using var output = File.Create(outputFileName);
gz.CopyTo(output);
}
private void InitializeIntroData(List<SongIntroductionData>? introData)
{

View File

@ -87,6 +87,18 @@
<Content Update="wwwroot\data\qrcode_data.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\music_order.bin">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\musicinfo.bin">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\wordlist.bin">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\music_attribute.bin">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>

View File

@ -1,5 +1,7 @@
using System.Collections.Immutable;
using System.IO.Compression;
using System.Net;
using System.Security.Cryptography;
using System.Text.Json;
using ICSharpCode.SharpZipLib.GZip;
using Swan.Mapping;
@ -54,32 +56,9 @@ public class GameDataService : IGameDataService
private async Task<T> GetData<T>(string dataBaseUrl, string fileBaseName) where T : notnull
{
T? data;
try
{
data = await client.GetFromJsonAsync<T>($"{dataBaseUrl}/data/{fileBaseName}.json");
data.ThrowIfNull();
return data;
}
catch (HttpRequestException e)
{
if (e.StatusCode != HttpStatusCode.NotFound)
{
throw;
}
await using var compressed = await client.GetStreamAsync($"{dataBaseUrl}/data/{fileBaseName}.bin");
await using var gZipInputStream = new GZipInputStream(compressed);
using var decompressed = new MemoryStream();
// Decompress
await gZipInputStream.CopyToAsync(decompressed);
// Reset stream for reading
decompressed.Position = 0;
data = await JsonSerializer.DeserializeAsync<T>(decompressed);
data.ThrowIfNull();
return data;
}
var data = await client.GetFromJsonAsync<T>($"{dataBaseUrl}/data/{fileBaseName}.json");
data.ThrowIfNull();
return data;
}
public string GetMusicNameBySongId(uint songId)