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,12 +10,15 @@ public static class Constants
public const string DEFAULT_DB_NAME = "taiko.db3"; public const string DEFAULT_DB_NAME = "taiko.db3";
public const string MUSIC_INFO_FILE_NAME = "musicinfo.json"; public const string MUSIC_INFO_BASE_NAME = "musicinfo";
public const string MUSIC_INFO_COMPRESSED_FILE_NAME = "musicinfo.bin"; public const string MUSIC_ATTRIBUTE_BASE_NAME = "music_attribute";
public const string MUSIC_ATTRIBUTE_FILE_NAME = "music_attribute.json";
public const string MUSIC_ATTRIBUTE_COMPRESSED_FILE_NAME = "music_attribute.bin"; 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 DAN_DATA_FILE_NAME = "dan_data.json";
public const string INTRO_DATA_FILE_NAME = "intro_data.json"; public const string INTRO_DATA_FILE_NAME = "intro_data.json";
public const string EVENT_FOLDER_DATA_FILE_NAME = "event_folder_data.json"; public const string EVENT_FOLDER_DATA_FILE_NAME = "event_folder_data.json";

View File

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

View File

@ -87,6 +87,18 @@
<Content Update="wwwroot\data\qrcode_data.json"> <Content Update="wwwroot\data\qrcode_data.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </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>
<ItemGroup> <ItemGroup>

View File

@ -1,5 +1,7 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using System.IO.Compression;
using System.Net; using System.Net;
using System.Security.Cryptography;
using System.Text.Json; using System.Text.Json;
using ICSharpCode.SharpZipLib.GZip; using ICSharpCode.SharpZipLib.GZip;
using Swan.Mapping; using Swan.Mapping;
@ -54,32 +56,9 @@ public class GameDataService : IGameDataService
private async Task<T> GetData<T>(string dataBaseUrl, string fileBaseName) where T : notnull private async Task<T> GetData<T>(string dataBaseUrl, string fileBaseName) where T : notnull
{ {
T? data; var data = await client.GetFromJsonAsync<T>($"{dataBaseUrl}/data/{fileBaseName}.json");
try data.ThrowIfNull();
{ return data;
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;
}
} }
public string GetMusicNameBySongId(uint songId) public string GetMusicNameBySongId(uint songId)