From c211d269ebf00cdf89b0b6e7eee3f080783883e8 Mon Sep 17 00:00:00 2001 From: MichaelO Date: Sat, 18 May 2024 14:31:21 +0800 Subject: [PATCH] updated to v2.11.2 (burlconfig.conf can export cipher type) --- .../Scripts/Editor/Bundle/BundleHelper.cs | 55 ++++++++++-- .../BundleCryptogramUtilityWindow.cs | 2 + .../BundleUrlConfigGeneratorWindow.cs | 30 +++++-- .../EditorWindow/CryptogramSettingWindow.cs | 2 + .../Scripts/Runtime/Bundle/BundleConfig.cs | 86 ++++++++++++++++++- Assets/OxGFrame/CHANGELOG.md | 5 ++ .../MediaFrame/Scripts/Editor/MediaHelper.cs | 4 +- .../Runtime/Core/Implement/MediaBase.cs | 9 +- Assets/OxGFrame/package.json | 2 +- README.md | 4 +- 10 files changed, 177 insertions(+), 22 deletions(-) diff --git a/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/BundleHelper.cs b/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/BundleHelper.cs index 31af36f9..9c7c08f8 100644 --- a/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/BundleHelper.cs +++ b/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/BundleHelper.cs @@ -1,10 +1,13 @@ using Newtonsoft.Json; +using NUnit.Framework; using OxGFrame.AssetLoader.Bundle; using OxGFrame.AssetLoader.Utility; using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Numerics; +using System.Text; using UnityEditor; using UnityEngine; using YooAsset.Editor; @@ -158,10 +161,12 @@ public static void ExportIndividualDlcBundles(string inputPath, string outputPat /// /// 產生 Bundle URL 配置檔至輸出路徑 (Export BundleUrlConfig to StreamingAssets [for Built-in]) /// - /// - /// + /// + /// + /// /// - public static void ExportBundleUrlConfig(string bundleIp, string bundleFallbackIp, string storeLink, string outputPath) + /// + public static void ExportBundleUrlConfig(string bundleIp, string bundleFallbackIp, string storeLink, string outputPath, bool cipher) { if (!Directory.Exists(outputPath)) Directory.CreateDirectory(outputPath); @@ -169,7 +174,7 @@ public static void ExportBundleUrlConfig(string bundleIp, string bundleFallbackI if (string.IsNullOrEmpty(bundleFallbackIp)) bundleFallbackIp = "127.0.0.1"; if (string.IsNullOrEmpty(storeLink)) storeLink = "http://"; - IEnumerable contents = new string[] + IEnumerable texts = new string[] { @$"# {PatchSetting.BUNDLE_IP} = First CDN Server IP or Domain (Plan A)", @$"# {PatchSetting.BUNDLE_FALLBACK_IP} = Second CDN Server IP or Domain (Plan B)", @@ -184,10 +189,48 @@ public static void ExportBundleUrlConfig(string bundleIp, string bundleFallbackI string bundleUrlFileName = $"{PatchSetting.setting.bundleUrlCfgName}{PatchSetting.BUNDLE_URL_CFG_EXTENSION}"; string fullOutputPath = Path.Combine(outputPath, bundleUrlFileName); + string content = string.Empty; + int idx = 0; + foreach (string txt in texts) + { + if (cipher) + { + // Without useless texts + if (idx < texts.ToArray().Length - 3) + { + idx++; + continue; + } + } + content += txt + "\n"; + } + + byte[] writeBuffer; + byte[] data = Encoding.UTF8.GetBytes(content); + + if (cipher) + { + // Encrypt + for (int i = 0; i < data.Length; i++) + { + data[i] ^= BundleConfig.cipher << 1; + } + + // Write data with header + int pos = 0; + byte[] dataWithHeader = new byte[data.Length + 2]; + // Write header (non-encrypted) + BundleConfig.WriteInt16(BundleConfig.cipherHeader, dataWithHeader, ref pos); + Buffer.BlockCopy(data, 0, dataWithHeader, pos, data.Length); + writeBuffer = dataWithHeader; + } + else + writeBuffer = data; + // 寫入配置文件 - File.WriteAllLines(fullOutputPath, contents, System.Text.Encoding.UTF8); + File.WriteAllBytes(fullOutputPath, writeBuffer); - Debug.Log($"【Export {bundleUrlFileName} Completes】"); + Debug.Log($"【Export Source is Cipher: {cipher}, {bundleUrlFileName} Completes】"); } #endregion diff --git a/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/EditorWindow/BundleCryptogramUtilityWindow.cs b/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/EditorWindow/BundleCryptogramUtilityWindow.cs index b6e6b75a..56c81a55 100644 --- a/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/EditorWindow/BundleCryptogramUtilityWindow.cs +++ b/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/EditorWindow/BundleCryptogramUtilityWindow.cs @@ -263,6 +263,7 @@ private void _DrawHT2XorPlusView() GUILayout.Label(new GUIContent("Head-Tail 2 XOR Plus Settings"), centeredStyle); EditorGUILayout.Space(); + var labelWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 200; this.hXorPlusKey = EditorGUILayout.IntField("Head XOR Plus KEY (0 ~ 255)", this.hXorPlusKey); if (this.hXorPlusKey < 0) this.hXorPlusKey = 0; @@ -276,6 +277,7 @@ private void _DrawHT2XorPlusView() this.j2XorPlusKey = EditorGUILayout.IntField("Jump 2 XOR Plus KEY (0 ~ 255)", this.j2XorPlusKey); if (this.j2XorPlusKey < 0) this.j2XorPlusKey = 0; else if (this.j2XorPlusKey > 255) this.j2XorPlusKey = 255; + EditorGUIUtility.labelWidth = labelWidth; this._DrawOperateButtonsView(this.cryptogramType); diff --git a/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/EditorWindow/BundleUrlConfigGeneratorWindow.cs b/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/EditorWindow/BundleUrlConfigGeneratorWindow.cs index b31eae03..16f8123f 100644 --- a/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/EditorWindow/BundleUrlConfigGeneratorWindow.cs +++ b/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/EditorWindow/BundleUrlConfigGeneratorWindow.cs @@ -90,7 +90,10 @@ private void _DrawBundleIPTextFieldView() EditorGUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); - this.bundleIp = EditorGUILayout.TextField("Bundle IP", this.bundleIp); + var labelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 180; + this.bundleIp = EditorGUILayout.TextField("Bundle IP or Domain", this.bundleIp); + EditorGUIUtility.labelWidth = labelWidth; if (EditorGUI.EndChangeCheck()) EditorStorage.SaveData(keySaver, "bundleIp", this.bundleIp); EditorGUILayout.EndHorizontal(); } @@ -101,7 +104,10 @@ private void _DrawBundleFallbackIPTextFieldView() EditorGUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); - this.bundleFallbackIp = EditorGUILayout.TextField("Bundle Fallback IP", this.bundleFallbackIp); + var labelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 180; + this.bundleFallbackIp = EditorGUILayout.TextField("Bundle Fallback IP or Domain", this.bundleFallbackIp); + EditorGUIUtility.labelWidth = labelWidth; if (EditorGUI.EndChangeCheck()) EditorStorage.SaveData(keySaver, "bundleFallbackIp", this.bundleFallbackIp); EditorGUILayout.EndHorizontal(); } @@ -112,7 +118,10 @@ private void _DrawStoreLinkTextFieldView() EditorGUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); + var labelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 180; this.storeLink = EditorGUILayout.TextField("Store Link", this.storeLink); + EditorGUIUtility.labelWidth = labelWidth; if (EditorGUI.EndChangeCheck()) EditorStorage.SaveData(keySaver, "storeLink", this.storeLink); EditorGUILayout.EndHorizontal(); } @@ -132,11 +141,22 @@ private void _DrawProcessButtonView() // process button Color bc = GUI.backgroundColor; GUI.backgroundColor = new Color32(255, 185, 83, 255); - if (GUILayout.Button("Process", GUILayout.MaxWidth(100f))) + if (GUILayout.Button("Cipher Process", GUILayout.MaxWidth(110f))) { string outputPath = Application.streamingAssetsPath; - BundleHelper.ExportBundleUrlConfig(this.bundleIp, this.bundleFallbackIp, this.storeLink, outputPath); - EditorUtility.DisplayDialog("Process Message", "Export BundleUrlConfig To StreamingAssets.", "OK"); + BundleHelper.ExportBundleUrlConfig(this.bundleIp, this.bundleFallbackIp, this.storeLink, outputPath, true); + EditorUtility.DisplayDialog("Process Message", "Export [Cipher] BundleUrlConfig To StreamingAssets.", "OK"); + AssetDatabase.Refresh(); + string bundleUrlFileName = $"{PatchSetting.setting.bundleUrlCfgName}{PatchSetting.BUNDLE_URL_CFG_EXTENSION}"; + if (this.autoReveal) EditorUtility.RevealInFinder($"{outputPath}/{bundleUrlFileName}"); + } + GUI.backgroundColor = bc; + GUI.backgroundColor = new Color32(255, 185, 83, 255); + if (GUILayout.Button("Plaintext Process", GUILayout.MaxWidth(125f))) + { + string outputPath = Application.streamingAssetsPath; + BundleHelper.ExportBundleUrlConfig(this.bundleIp, this.bundleFallbackIp, this.storeLink, outputPath, false); + EditorUtility.DisplayDialog("Process Message", "Export [Plaintext] BundleUrlConfig To StreamingAssets.", "OK"); AssetDatabase.Refresh(); string bundleUrlFileName = $"{PatchSetting.setting.bundleUrlCfgName}{PatchSetting.BUNDLE_URL_CFG_EXTENSION}"; if (this.autoReveal) EditorUtility.RevealInFinder($"{outputPath}/{bundleUrlFileName}"); diff --git a/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/EditorWindow/CryptogramSettingWindow.cs b/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/EditorWindow/CryptogramSettingWindow.cs index db146c8e..16c9c251 100644 --- a/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/EditorWindow/CryptogramSettingWindow.cs +++ b/Assets/OxGFrame/AssetLoader/Scripts/Editor/Bundle/EditorWindow/CryptogramSettingWindow.cs @@ -256,6 +256,7 @@ private void _DrawHT2XorPlusView() EditorGUILayout.Space(); EditorGUI.BeginChangeCheck(); + var labelWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 200; this.hXorPlusKey = EditorGUILayout.IntField("Head XOR Plus KEY (0 ~ 255)", this.hXorPlusKey); if (this.hXorPlusKey < 0) this.hXorPlusKey = 0; @@ -269,6 +270,7 @@ private void _DrawHT2XorPlusView() this.j2XorPlusKey = EditorGUILayout.IntField("Jump 2 XOR Plus KEY (0 ~ 255)", this.j2XorPlusKey); if (this.j2XorPlusKey < 0) this.j2XorPlusKey = 0; else if (this.j2XorPlusKey > 255) this.j2XorPlusKey = 255; + EditorGUIUtility.labelWidth = labelWidth; if (EditorGUI.EndChangeCheck()) this._isDirty = true; this._DrawOperateButtonsView(this.cryptogramType); diff --git a/Assets/OxGFrame/AssetLoader/Scripts/Runtime/Bundle/BundleConfig.cs b/Assets/OxGFrame/AssetLoader/Scripts/Runtime/Bundle/BundleConfig.cs index 39980ed9..510ccd50 100644 --- a/Assets/OxGFrame/AssetLoader/Scripts/Runtime/Bundle/BundleConfig.cs +++ b/Assets/OxGFrame/AssetLoader/Scripts/Runtime/Bundle/BundleConfig.cs @@ -2,10 +2,12 @@ using MyBox; using Newtonsoft.Json; using OxGFrame.AssetLoader.Utility.SecureMemory; +using OxGKit.LoggingSystem; using OxGKit.Utilities.Request; using System; using System.Collections.Generic; using System.IO; +using System.Text; using UnityEngine; namespace OxGFrame.AssetLoader.Bundle @@ -57,6 +59,16 @@ public class CryptogramType } #region 執行配置 + /// + /// 配置檔標檔頭 + /// + public const short cipherHeader = 0x584F; + + /// + /// 配置檔金鑰 + /// + public const byte cipher = 0x4D; + /// /// Patch 執行模式 /// @@ -171,6 +183,40 @@ internal static void ReleaseSecureString() /// private static AppConfig _appConfig = null; + #region Header Helper + public static void WriteInt16(short value, byte[] buffer, ref int pos) + { + WriteUInt16((ushort)value, buffer, ref pos); + } + + internal static void WriteUInt16(ushort value, byte[] buffer, ref int pos) + { + buffer[pos++] = (byte)value; + buffer[pos++] = (byte)(value >> 8); + } + + public static short ReadInt16(byte[] buffer, ref int pos) + { + if (BitConverter.IsLittleEndian) + { + short value = (short)((buffer[pos]) | (buffer[pos + 1] << 8)); + pos += 2; + return value; + } + else + { + short value = (short)((buffer[pos] << 8) | (buffer[pos + 1])); + pos += 2; + return value; + } + } + + internal static ushort ReadUInt16(byte[] buffer, ref int pos) + { + return (ushort)ReadInt16(buffer, ref pos); + } + #endregion + /// /// 取得 burlconfig 佈署配置檔的數據 /// @@ -182,19 +228,51 @@ public static async UniTask GetValueFromUrlCfg(string key) { string bundleUrlFileName = $"{PatchSetting.setting.bundleUrlCfgName}{PatchSetting.BUNDLE_URL_CFG_EXTENSION}"; string pathName = Path.Combine(GetRequestStreamingAssetsPath(), bundleUrlFileName); - var content = await Requester.RequestText(pathName, null, null, null, false); - if (string.IsNullOrEmpty(content)) return string.Empty; + var data = await Requester.RequestBytes(pathName); + if (data.Length == 0) + return string.Empty; + + #region Check data type + string content; + int pos = 0; + + // Read header (non-encrypted) + var header = ReadInt16(data, ref pos); + if (header == cipherHeader) + { + // Read data without header + byte[] dataWithoutHeader = new byte[data.Length - 2]; + Buffer.BlockCopy(data, pos, dataWithoutHeader, 0, data.Length - pos); + // Decrypt + for (int i = 0; i < dataWithoutHeader.Length; i++) + { + dataWithoutHeader[i] ^= cipher << 1; + } + // To string + content = Encoding.UTF8.GetString(dataWithoutHeader); + Logging.Print($"[Source is Cipher] Check -> burlconfig.conf:\n{content}"); + } + else + { + content = Encoding.UTF8.GetString(data); + Logging.Print($"[Source is Plaintext] Check -> burlconfig.conf:\n{content}"); + } + #endregion + + // Parsing var allWords = content.Split('\n'); var lines = new List(allWords); _urlCfgFileMap = new Dictionary(); foreach (var readLine in lines) { - if (readLine.IndexOf('#') != -1 && readLine[0] == '#') continue; + if (readLine.IndexOf('#') != -1 && readLine[0] == '#') + continue; var args = readLine.Split(' ', 2); if (args.Length >= 2) { - if (!_urlCfgFileMap.ContainsKey(args[0])) _urlCfgFileMap.Add(args[0], args[1].Replace("\n", "").Replace("\r", "")); + if (!_urlCfgFileMap.ContainsKey(args[0])) + _urlCfgFileMap.Add(args[0], args[1].Replace("\n", "").Replace("\r", "")); } } } diff --git a/Assets/OxGFrame/CHANGELOG.md b/Assets/OxGFrame/CHANGELOG.md index 714c9ee1..372c5a53 100644 --- a/Assets/OxGFrame/CHANGELOG.md +++ b/Assets/OxGFrame/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## [2.11.2] - 2024-05-18 +- Added burlconfig.conf can export cipher type (If the output is ciphertext, it will automatically determine whether to execute with the decryption process). + - Cipher process. + - Plaintext process. + ## [2.11.1] - 2024-05-17 - Added HT2XORPlus encryption stronger than HT2XOR (Recommended). - Updated YooAsset to v2.1.2 (new commits). diff --git a/Assets/OxGFrame/MediaFrame/Scripts/Editor/MediaHelper.cs b/Assets/OxGFrame/MediaFrame/Scripts/Editor/MediaHelper.cs index 729f46c0..e770ef6b 100644 --- a/Assets/OxGFrame/MediaFrame/Scripts/Editor/MediaHelper.cs +++ b/Assets/OxGFrame/MediaFrame/Scripts/Editor/MediaHelper.cs @@ -21,7 +21,7 @@ public static void ExportMediaUrlConfig(string audioUrlset, string videoUrlset, if (string.IsNullOrEmpty(audioUrlset)) audioUrlset = "127.0.0.1/audio/"; if (string.IsNullOrEmpty(videoUrlset)) videoUrlset = "127.0.0.1/video/"; - IEnumerable contents = new string[] + IEnumerable texts = new string[] { @$"# {MediaConfig.AUDIO_URLSET} = Audio Source Url Path", @$"# {MediaConfig.VIDEO_URLSET} = Video Source Url Path", @@ -33,7 +33,7 @@ public static void ExportMediaUrlConfig(string audioUrlset, string videoUrlset, string fullOutputPath = Path.Combine(outputPath, MediaConfig.MEDIA_URL_CFG_NAME); // 寫入配置文件 - File.WriteAllLines(fullOutputPath, contents, System.Text.Encoding.UTF8); + File.WriteAllLines(fullOutputPath, texts, System.Text.Encoding.UTF8); Debug.Log($"【Export {MediaConfig.MEDIA_URL_CFG_NAME} Completes】"); } diff --git a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Implement/MediaBase.cs b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Implement/MediaBase.cs index 4f032638..ea8fafa7 100644 --- a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Implement/MediaBase.cs +++ b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Implement/MediaBase.cs @@ -53,7 +53,8 @@ public async UniTask GetFileText() case RequestType.StreamingAssets: string pathName = System.IO.Path.Combine(GetRequestStreamingAssetsPath(), this.fullPathName); - if (string.IsNullOrEmpty(_urlCfgContent)) _urlCfgContent = await OxGKit.Utilities.Request.Requester.RequestText(pathName, null, null, null, false); + if (string.IsNullOrEmpty(_urlCfgContent)) + _urlCfgContent = await OxGKit.Utilities.Request.Requester.RequestText(pathName, null, null, null, false); return _urlCfgContent; } @@ -210,7 +211,8 @@ public void SetNames(string assetName, string mediaName) public const string AUDIO_URLSET = "audio_urlset"; public static string GetValueFromUrlCfg(string urlCfg, string key) { - if (string.IsNullOrEmpty(urlCfg)) return string.Empty; + if (string.IsNullOrEmpty(urlCfg)) + return string.Empty; var content = urlCfg; var allWords = content.Split('\n'); @@ -220,7 +222,8 @@ public static string GetValueFromUrlCfg(string urlCfg, string key) foreach (var readLine in lines) { Logging.Print($"readline: {readLine}"); - if (readLine.IndexOf('#') != -1 && readLine[0] == '#') continue; + if (readLine.IndexOf('#') != -1 && readLine[0] == '#') + continue; var args = readLine.Split(' ', 2); if (args.Length >= 2) { diff --git a/Assets/OxGFrame/package.json b/Assets/OxGFrame/package.json index cbf1899a..d376437d 100644 --- a/Assets/OxGFrame/package.json +++ b/Assets/OxGFrame/package.json @@ -2,7 +2,7 @@ "name": "com.michaelo.oxgframe", "displayName": "OxGFrame", "description": "The OxGFrame is a framework based on Unity for accelerating game development. Supports multi-platform Win, OSX, Android, iOS, WebGL.", - "version": "2.11.1", + "version": "2.11.2", "unity": "2021.3", "license": "MIT", "samples": [ diff --git a/README.md b/README.md index 9142122e..28898ddd 100644 --- a/README.md +++ b/README.md @@ -192,7 +192,9 @@ if (isInitialized) #### Bundle [burlconfig] (Bundle URL Config) 格式 -格式如下 **(store_link 針對非 Android, iOS 平台的,可以設置主程式下載的 link)** +格式如下,以下為明文類型 **(store_link 針對非 Android, iOS 平台的,可以設置主程式下載的 link)** +- 支持 Cipher Type (密文類型) +- 支持 Plaintext Type (明文類型) ``` # bundle_ip = First CDN Server IP or Domain (Plan A)