Update to support encrypted datatables, all on server side
This commit is contained in:
parent
bc6f65f4a0
commit
0d3b575903
@ -10,12 +10,15 @@ 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";
|
||||
public const string EVENT_FOLDER_DATA_FILE_NAME = "event_folder_data.json";
|
||||
|
@ -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,28 +218,25 @@ 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)
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user