From 101639060ffb193d6078611c8e95359b4f108e17 Mon Sep 17 00:00:00 2001 From: AXiX-official <2879710747@qq.com> Date: Mon, 26 Aug 2024 23:03:10 +0800 Subject: [PATCH] Auto Generate UnityCN Info --- UnityAsset.NET/BundleFile/BundleFile.cs | 42 ++++++++++++----------- UnityAsset.NET/BundleFile/UnityCN.cs | 35 ++++++++++++++++--- UnityAsset.NET/Compression/Compression.cs | 14 ++++---- UnityAsset.NET/UnityAsset.NET.csproj | 7 ++-- 4 files changed, 63 insertions(+), 35 deletions(-) diff --git a/UnityAsset.NET/BundleFile/BundleFile.cs b/UnityAsset.NET/BundleFile/BundleFile.cs index 891d493..d5e36b9 100644 --- a/UnityAsset.NET/BundleFile/BundleFile.cs +++ b/UnityAsset.NET/BundleFile/BundleFile.cs @@ -47,6 +47,16 @@ public BundleFile(string path, string? key = null) { } + public BundleFile(byte[] data, string? key = null) + { + using AssetReader reader = new AssetReader(data); + + UnityCNKey = key; + + Header = new Header(reader); + ReadBundleWithHeader(reader, Header, key); + } + public BundleFile(Stream input, string? key = null) { using AssetReader reader = new AssetReader(input); @@ -266,13 +276,13 @@ private void ReadBlocks(AssetReader reader) } } - public void WriteToFile(string path, string infoPacker = "none", string dataPacker = "none", bool unityCN = false) + public void WriteToFile(string path, string infoPacker = "none", string dataPacker = "none", bool unityCN = false, string key = "") { using FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write); - Write(fs, infoPacker, dataPacker, unityCN); + Write(fs, infoPacker, dataPacker, unityCN, key); } - public void Write(Stream output, string infoPacker = "none", string dataPacker = "none", bool unityCN = false) + public void Write(Stream output, string infoPacker = "none", string dataPacker = "none", bool unityCN = false, string key = "") { MemoryStream compressedStream = new MemoryStream(); @@ -312,13 +322,17 @@ public void Write(Stream output, string infoPacker = "none", string dataPacker = if (unityCN) { - if (UnityCNKey == null) - { - throw new Exception("UnityCN key is required for encryption"); - } if (UnityCNInfo == null) { - throw new Exception("TODO: UnityCNInfo is null"); + if (key != "") + { + UnityCNKey = key; + UnityCNInfo = new UnityCN(UnityCNKey); + } + else + { + throw new Exception("UnityCN key is required for encryption"); + } } UnityCNInfo.reset(); compressedStream.Position = 0; @@ -424,18 +438,6 @@ private void calculateSize(long BlocksStreamLength, bool unityCN) Header.size = size; } - public void Bumbo() - { - var blockFlag = DataInfo.BlocksInfo[^1].flags; - var blockSize = int.MaxValue / 2; - DataInfo.BlocksInfo.Add(new StorageBlockInfo((uint)blockSize, (uint)blockSize, blockFlag)); - DataInfo.DirectoryInfo[^1].size += blockSize; - cabStreams[^1].SetLength(cabStreams[^1].Length + blockSize); - cabStreams[^1].Position = cabStreams[^1].Length - blockSize; - cabStreams[^1].Write(new byte[blockSize]); - cabStreams[^1].Position = 0; - } - private int[] ParseVersion() { var versionSplit = Regex.Replace(Header.unityRevision, @"\D", ".").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries); diff --git a/UnityAsset.NET/BundleFile/UnityCN.cs b/UnityAsset.NET/BundleFile/UnityCN.cs index 0fe5838..014c88b 100644 --- a/UnityAsset.NET/BundleFile/UnityCN.cs +++ b/UnityAsset.NET/BundleFile/UnityCN.cs @@ -40,12 +40,29 @@ public UnityCN(AssetReader reader, string key) reset(); } + public UnityCN(string key) + { + SetKey(key); + + value = 0; + + InfoBytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xA6, 0xB1, 0xDE, 0x48, 0x9E, 0x2B, 0x53, 0x5C]; + InfoKey = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10]; + EncryptKey(InfoKey, InfoBytes); + + SignatureKey = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10]; + SignatureBytes = Encoding.UTF8.GetBytes(Signature); + EncryptKey(SignatureKey, SignatureBytes); + + reset(); + } + public void reset() { - var infoBytes = InfoBytes.ToArray(); - var infoKey = InfoKey.ToArray(); - var signatureBytes = SignatureBytes.ToArray(); - var signatureKey = SignatureKey.ToArray(); + var infoBytes = (byte[])InfoBytes.Clone(); + var infoKey = (byte[])InfoKey.Clone(); + var signatureBytes = (byte[])SignatureBytes.Clone(); + var signatureKey = (byte[])SignatureKey.Clone(); DecryptKey(signatureKey, signatureBytes); @@ -123,6 +140,16 @@ private void DecryptKey(byte[] key, byte[] data) data[i] ^= key[i]; } } + + private void EncryptKey(byte[] key, byte[] data) + { + if (Encryptor != null) + { + key = Encryptor.TransformFinalBlock(key, 0, key.Length); + for (int i = 0; i < 0x10; i++) + data[i] ^= key[i]; + } + } private int DecryptByte(Span bytes, ref int offset, ref int index) { diff --git a/UnityAsset.NET/Compression/Compression.cs b/UnityAsset.NET/Compression/Compression.cs index 4554b9d..e1be82f 100644 --- a/UnityAsset.NET/Compression/Compression.cs +++ b/UnityAsset.NET/Compression/Compression.cs @@ -12,11 +12,9 @@ public static void DecompressToStream(ReadOnlySpan compressedData, Stream { case "lz4": byte[] decompressedData = new byte[decompressedSize]; - int size = LZ4.Decode(compressedData, new Span(decompressedData)); + var size = LZ4Codec.Decode(compressedData, new Span(decompressedData)); if (size != decompressedSize) - { - throw new Exception($"LZ4 decompression failed, expected {decompressedSize} bytes, got {size} bytes"); - } + throw new Exception($"Decompressed size mismatch, expected {decompressedSize}, got {size}"); decompressedStream.Write(decompressedData, 0, decompressedData.Length); break; case "lzma": @@ -42,12 +40,12 @@ public static List CompressStream(MemoryStream uncompressedStream, string case "none": return uncompressedData.ToList(); case "lz4": - byte[] compressedData = new byte[LZ4.MaximumOutputSize(uncompressedData.Length)]; - int compressedSize = LZ4.EncodeFast(uncompressedData, compressedData); + byte[] compressedData = new byte[LZ4Codec.MaximumOutputSize(uncompressedData.Length)]; + int compressedSize = LZ4Codec.Encode(uncompressedData, compressedData); return compressedData.Take(compressedSize).ToList(); case "lz4hc": byte[] compressedDataHC = new byte[LZ4Codec.MaximumOutputSize(uncompressedData.Length)]; - int compressedSizeHC = LZ4Codec.Encode(uncompressedData, compressedDataHC, LZ4Level.L09_HC); + int compressedSizeHC = LZ4Codec.Encode(uncompressedData, compressedDataHC, LZ4Level.L12_MAX); return compressedDataHC.Take(compressedSizeHC).ToList(); case "lzma": var encoder = new Encoder(); @@ -56,7 +54,7 @@ public static List CompressStream(MemoryStream uncompressedStream, string long fileSize = uncompressedStream.Length; uncompressedStream.Position = 0; encoder.Code(uncompressedStream, compressedStream, -1, -1, null); - Console.WriteLine($"Compressed {fileSize} bytes to {compressedStream.Length} bytes"); + //Console.WriteLine($"Compressed {fileSize} bytes to {compressedStream.Length} bytes"); return compressedStream.ToArray().ToList(); default: throw new ArgumentException($"Unsupported compression type {compressionType}"); diff --git a/UnityAsset.NET/UnityAsset.NET.csproj b/UnityAsset.NET/UnityAsset.NET.csproj index d1cec10..606b72c 100644 --- a/UnityAsset.NET/UnityAsset.NET.csproj +++ b/UnityAsset.NET/UnityAsset.NET.csproj @@ -6,19 +6,20 @@ enable AXiX A .NET library for reading and modifying Unity assets and bundles. - 0.0.4-beta.1 + 0.0.4-beta.2 UnityAsset.NET AXiX https://github.com/AXiX-official/UnityAsset.NET https://github.com/AXiX-official/UnityAsset.NET true - 0.0.4.1 - 0.0.4.1 + 0.0.4.2 + 0.0.4.2 True README.md Unity LICENSE True + true