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 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";
|
||||||
|
@ -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)
|
||||||
|
@ -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>
|
||||||
|
@ -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,33 +56,10 @@ 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 = await client.GetFromJsonAsync<T>($"{dataBaseUrl}/data/{fileBaseName}.json");
|
|
||||||
data.ThrowIfNull();
|
data.ThrowIfNull();
|
||||||
return data;
|
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)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user