public void Read(Stream psarc, bool lazy = false) { _toc.Clear(); _reader = new BigEndianBinaryReader(psarc); _header.MagicNumber = _reader.ReadUInt32(); if (_header.MagicNumber == 1347633490U)//PSAR (BE) { //Parse Header _header.VersionNumber = _reader.ReadUInt32(); _header.CompressionMethod = _reader.ReadUInt32(); _header.TotalTOCSize = _reader.ReadUInt32(); _header.TOCEntrySize = _reader.ReadUInt32(); _header.NumFiles = _reader.ReadUInt32(); _header.BlockSizeAlloc = _reader.ReadUInt32(); _header.ArchiveFlags = _reader.ReadUInt32(); //Read TOC int tocSize = (int)(_header.TotalTOCSize - 32U); if (_header.ArchiveFlags == 4) //TOC_ENCRYPTED { // Decrypt TOC var tocStream = new MemoryStream(); using (var decStream = new MemoryStream()) { RijndaelEncryptor.DecryptPSARC(psarc, decStream, _header.TotalTOCSize); int bytesRead; int decSize = 0; var buffer = new byte[_header.BlockSizeAlloc]; while ((bytesRead = decStream.Read(buffer, 0, buffer.Length)) > 0) { decSize += bytesRead; if (decSize > tocSize) { bytesRead = tocSize - (decSize - bytesRead); } tocStream.Write(buffer, 0, bytesRead); } } tocStream.Position = 0; _reader = new BigEndianBinaryReader(tocStream); } ParseTOC(); //Parse zBlocksSizeList int tocChunkSize = (int)(_header.NumFiles * _header.TOCEntrySize);//(int)_reader.BaseStream.Position //don't alter this with. causes issues int zNum = (tocSize - tocChunkSize) / bNum; var zLengths = new uint[zNum]; for (int i = 0; i < zNum; i++) { switch (bNum) { case 2: //64KB zLengths[i] = _reader.ReadUInt16(); break; case 3: //16MB zLengths[i] = _reader.ReadUInt24(); break; case 4: //4GB zLengths[i] = _reader.ReadUInt32(); break; } } _zBlocksSizeList = zLengths; //TODO: validate _reader.BaseStream.Flush(); //Free tocStream resources _reader = new BigEndianBinaryReader(psarc); // Validate psarc size // if (psarc.Length < RequiredPsarcSize()) // throw new InvalidDataException("Truncated psarc."); // try to unpack corrupt CDLC for now switch (_header.CompressionMethod) { case 2053925218: //zlib (BE) ReadManifest(); psarc.Seek(_header.TotalTOCSize, SeekOrigin.Begin); if (!lazy) { // Decompress Data InflateEntries(); } break; case 1819962721: //lzma (BE) throw new NotImplementedException("LZMA compression not supported."); default: throw new InvalidDataException("Unknown compression."); } } psarc.Flush(); }
public void Write(Stream str, bool encrypt) { if (encrypt) { this.header.archiveFlags = 4; } this.header.TOCEntrySize = 30; this.UpdateManifest(); Dictionary <Entry, byte[]> dictionary; List <uint> list; this.deflateEntries(out dictionary, out list, this.header.blockSize); byte b = 1; uint num = 256; do { num *= 256; b += 1; }while (num < this.header.blockSize); BigEndianBinaryWriter bigEndianBinaryWriter = new BigEndianBinaryWriter(str); this.header.TotalTOCSize = (uint)(32 + this.header.TOCEntrySize * (this.Entries.Count) + ((int)b * list.Count)); this.Entries[0].Offset = (ulong)this.header.TotalTOCSize; for (int i = 1; i < this.Entries.Count; i++) { this.Entries[i].Offset = this.Entries[i - 1].Offset + (ulong)(dictionary[this.Entries[i - 1]].Length); } bigEndianBinaryWriter.Write(this.header.MagicNumber); bigEndianBinaryWriter.Write(this.header.VersionNumber); bigEndianBinaryWriter.Write(this.header.CompressionMethod); bigEndianBinaryWriter.Write(this.header.TotalTOCSize); bigEndianBinaryWriter.Write(this.header.TOCEntrySize); bigEndianBinaryWriter.Write(this.Entries.Count); bigEndianBinaryWriter.Write(this.header.blockSize); bigEndianBinaryWriter.Write(this.header.archiveFlags); foreach (Entry current in this.Entries) { current.UpdateNameMD5(); bigEndianBinaryWriter.Write((current.id == 0) ? new byte[16] : current.MD5); bigEndianBinaryWriter.Write(current.zIndex); bigEndianBinaryWriter.WriteUInt40((ulong)current.Data.Length); bigEndianBinaryWriter.WriteUInt40(current.Offset); } foreach (uint current2 in list) { switch (b) { case 2: bigEndianBinaryWriter.Write((ushort)current2); break; case 3: bigEndianBinaryWriter.WriteUInt24(current2); break; case 4: bigEndianBinaryWriter.Write(current2); break; } } foreach (Entry current in this.Entries) { bigEndianBinaryWriter.Write(dictionary[current]); } if (encrypt) { var encStream = new MemoryStreamExtension(); using (var outputStream = new MemoryStreamExtension()) { str.Seek(32, SeekOrigin.Begin); RijndaelEncryptor.EncryptPSARC(str, outputStream, this.header.TotalTOCSize); int bytesRead; byte[] buffer = new byte[30000]; str.Seek(0, SeekOrigin.Begin); while ((bytesRead = str.Read(buffer, 0, buffer.Length)) > 0) { encStream.Write(buffer, 0, bytesRead); } int decMax = (int)this.header.TotalTOCSize - 32; int decSize = 0; outputStream.Seek(0, SeekOrigin.Begin); encStream.Seek(32, SeekOrigin.Begin); while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0) { decSize += bytesRead; if (decSize > decMax) { bytesRead = decMax - (decSize - bytesRead); } encStream.Write(buffer, 0, bytesRead); } } str.Seek(0, SeekOrigin.Begin); encStream.Seek(0, SeekOrigin.Begin); encStream.CopyTo(str); } str.Flush(); }
/// <summary> /// Packs Entries to zStream /// </summary> /// <param name="entryDeflatedData">zStreams</param> /// <param name="zLengths">zBlocksSizeList</param> private void DeflateEntries(out Dictionary <Entry, byte[]> entryDeflatedData, out List <uint> zLengths) { // TODO: This produces perfect results for song archives (original vs repacked) // there are slight differences in the binary of large archives (original vs repacked). WHY? // entryDeflatedData = new Dictionary <Entry, byte[]>(); uint blockSize = _header.BlockSizeAlloc; zLengths = new List <uint>(); var ndx = 0; // for debugging var step = Math.Round(1.0 / (_toc.Count + 2) * 100, 3); double progress = 0; GlobalExtension.ShowProgress("Deflating Entries ..."); foreach (Entry entry in _toc) { var zList = new List <Tuple <byte[], int> >(); entry.zIndexBegin = (uint)zLengths.Count; entry.Data.Seek(0, SeekOrigin.Begin); while (entry.Data.Position < entry.Data.Length) { var array_i = new byte[blockSize]; var array_o = new byte[blockSize * 2]; var memoryStream = new MemoryStream(array_o); int plain_len = entry.Data.Read(array_i, 0, array_i.Length); int packed_len = (int)RijndaelEncryptor.Zip(array_i, memoryStream, plain_len, false); if (packed_len >= plain_len) {// If packed data "worse" than plain (i.e. already packed) z = 0 zList.Add(new Tuple <byte[], int>(array_i, plain_len)); } else { // If packed data is good if (packed_len < (blockSize - 1)) { // If packed data fits maximum packed block size z = packed_len zList.Add(new Tuple <byte[], int>(array_o, packed_len)); } else {// Write plain. z = 0 zList.Add(new Tuple <byte[], int>(array_i, plain_len)); } } } int zSisesSum = 0; foreach (var zSize in zList) { zSisesSum += zSize.Item2; zLengths.Add((uint)zSize.Item2); } var array3 = new byte[zSisesSum]; var memoryStream2 = new MemoryStream(array3); foreach (var entryblock in zList) { memoryStream2.Write(entryblock.Item1, 0, entryblock.Item2); } entryDeflatedData.Add(entry, array3); progress += step; GlobalExtension.UpdateProgress.Value = (int)progress; Debug.WriteLine("Deflating: " + ndx++); } }
public static string Decrypt(string cipherText) { return(RijndaelEncryptor.Decrypt(cipherText)); }
public void Read(Stream str) { this.Entries.Clear(); BigEndianBinaryReader bigEndianBinaryReader = new BigEndianBinaryReader(str); this.header.MagicNumber = bigEndianBinaryReader.ReadUInt32(); this.header.VersionNumber = bigEndianBinaryReader.ReadUInt32(); this.header.CompressionMethod = bigEndianBinaryReader.ReadUInt32(); this.header.TotalTOCSize = bigEndianBinaryReader.ReadUInt32(); this.header.TOCEntrySize = bigEndianBinaryReader.ReadUInt32(); this.header.numFiles = bigEndianBinaryReader.ReadUInt32(); this.header.blockSize = bigEndianBinaryReader.ReadUInt32(); this.header.archiveFlags = bigEndianBinaryReader.ReadUInt32(); var tocStream = str; BigEndianBinaryReader bigEndianBinaryReaderTOC = bigEndianBinaryReader; if (this.header.archiveFlags == 4) { var decStream = new TempFileStream(); using (var outputStream = new MemoryStream()) { RijndaelEncryptor.DecryptPSARC(str, outputStream, this.header.TotalTOCSize); int bytesRead; byte[] buffer = new byte[30000]; int decMax = (int)this.header.TotalTOCSize - 32; int decSize = 0; outputStream.Seek(0, SeekOrigin.Begin); while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0) { decSize += bytesRead; if (decSize > decMax) { bytesRead = decMax - (decSize - bytesRead); } decStream.Write(buffer, 0, bytesRead); } } decStream.Seek(0, SeekOrigin.Begin); str.Seek(this.header.TotalTOCSize, SeekOrigin.Begin); tocStream = decStream; bigEndianBinaryReaderTOC = new BigEndianBinaryReader(tocStream); } if (this.header.MagicNumber == 1347633490) { if (this.header.CompressionMethod == 2053925218) { byte b = 1; uint num = 256; do { num *= 256; b += 1; }while (num < this.header.blockSize); int num2 = 0; while (num2 < this.header.numFiles) { this.Entries.Add(new Entry { id = num2, MD5 = bigEndianBinaryReaderTOC.ReadBytes(16), zIndex = bigEndianBinaryReaderTOC.ReadUInt32(), Length = bigEndianBinaryReaderTOC.ReadUInt40(), Offset = bigEndianBinaryReaderTOC.ReadUInt40() }); num2++; } long decMax = (this.header.archiveFlags == 4) ? 32 : 0; uint num3 = (this.header.TotalTOCSize - (uint)(tocStream.Position + decMax)) / (uint)b; uint[] array = new uint[num3]; num2 = 0; while (num2 < num3) { switch (b) { case 2: array[num2] = (uint)bigEndianBinaryReaderTOC.ReadUInt16(); break; case 3: array[num2] = bigEndianBinaryReaderTOC.ReadUInt24(); break; case 4: array[num2] = bigEndianBinaryReaderTOC.ReadUInt32(); break; } num2++; } this.inflateEntries(bigEndianBinaryReader, array.ToArray <uint>(), this.header.blockSize); this.ReadNames(); } } str.Flush(); }
/// <summary> /// Writes to the inputStream /// <para>Default 'seek' is true, flushes and seeks to the end of stream after write is finished</para> /// <para>Eliminates the need for coding output.Flush() followed by output.Seek(0, SeekOrigin.Begin)</para> /// </summary> /// <param name="inputStream"></param> /// <param name="encrypt"></param> /// <param name="seek"></param> public void Write(Stream inputStream, bool encrypt = false, bool seek = true) { _header.ArchiveFlags = encrypt ? 4U : 0U; _header.TOCEntrySize = 30U; // track artifacts WriteManifest(); //Pack entries List <uint> zLengths; Dictionary <Entry, byte[]> zStreams; DeflateEntries(out zStreams, out zLengths); //Build zLengths _writer = new BigEndianBinaryWriter(inputStream); _header.TotalTOCSize = (uint)(32 + _toc.Count * _header.TOCEntrySize + zLengths.Count * bNum); _toc[0].Offset = _header.TotalTOCSize; for (int i = 1; i < _toc.Count; i++) { _toc[i].Offset = _toc[i - 1].Offset + (ulong)(zStreams[_toc[i - 1]].Length); } //Write Header _writer.Write(_header.MagicNumber); _writer.Write(_header.VersionNumber); _writer.Write(_header.CompressionMethod); _writer.Write(_header.TotalTOCSize); _writer.Write(_header.TOCEntrySize); _writer.Write(_toc.Count); _writer.Write(_header.BlockSizeAlloc); _writer.Write(_header.ArchiveFlags); var step = Math.Round(1D / (this.TOC.Count + 2) * 100, 3); double progress = 0; GlobalExtension.ShowProgress("Writing tocData ..."); //Write Table of contents foreach (Entry entry in _toc) { entry.UpdateNameMD5(); _writer.Write(entry.MD5); _writer.Write(entry.zIndexBegin); _writer.WriteUInt40((ulong)entry.Data.Length); _writer.WriteUInt40(entry.Offset); progress += step; GlobalExtension.UpdateProgress.Value = (int)progress; Console.WriteLine("Writing tocData: " + entry.Id); } foreach (uint zLen in zLengths) { switch (bNum) { case 2: //16bit _writer.Write((ushort)zLen); break; case 3: //24bit _writer.WriteUInt24(zLen); break; case 4: //32bit _writer.Write(zLen); break; } } zLengths = null; progress = 0; GlobalExtension.ShowProgress("Writing zData ..."); // Write zData foreach (Entry entry in _toc) { // skip NamesBlock.bin //if (current.Name == "NamesBlock.bin") // continue; //try //{ // use chunk write method to avoid OOM Exceptions var z = zStreams[entry]; var len = z.Length; if (len > _header.BlockSizeAlloc) { using (var msInput = new MemoryStreamExtension(z)) using (var msExt = new MemoryStreamExtension()) using (var _writer2 = new BigEndianBinaryWriter(msExt)) { int bytesRead; int totalBytesRead = 0; var buffer = new byte[_header.BlockSizeAlloc]; while ((bytesRead = msInput.Read(buffer, 0, buffer.Length)) > 0) { totalBytesRead += bytesRead; if (totalBytesRead > len) { bytesRead = len - (totalBytesRead - bytesRead); } using (var msOutput = new MemoryStreamExtension()) { msOutput.Write(buffer, 0, bytesRead); _writer2.Write(msOutput.ToArray()); } } _writer.Write(msExt.ToArray()); } } else { _writer.Write(zStreams[entry]); } if (entry.Data != null) { entry.Data.Close(); } //} //catch (Exception ex) //{ // Console.WriteLine("<ERROR> _writer.Write: " + ex.Message); // _writer.Flush(); // _writer.Dispose(); // break; //} progress += step; GlobalExtension.UpdateProgress.Value = (int)progress; Console.WriteLine("Writing zData: " + entry.Id); } zStreams = null; if (encrypt) // Encrypt TOC { using (var outputStream = new MemoryStreamExtension()) using (var encStream = new MemoryStreamExtension()) { inputStream.Position = 32L; RijndaelEncryptor.EncryptPSARC(inputStream, outputStream, _header.TotalTOCSize); inputStream.Position = 0L; // quick copy header from input stream var buffer = new byte[32]; encStream.Write(buffer, 0, inputStream.Read(buffer, 0, buffer.Length)); encStream.Position = 32; //sanity check ofc inputStream.Flush(); int tocSize = (int)_header.TotalTOCSize - 32; int decSize = 0; buffer = new byte[1024 * 16]; // more efficient use of memory var ndx = 0; // for debugging step = Math.Round(1D / (((double)tocSize / buffer.Length) + 2) * 100, 3); progress = 0; GlobalExtension.ShowProgress("Writing encryptedData ..."); int bytesRead; while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0) { decSize += bytesRead; if (decSize > tocSize) { bytesRead = tocSize - (decSize - bytesRead); } encStream.Write(buffer, 0, bytesRead); progress += step; GlobalExtension.UpdateProgress.Value = (int)progress; Console.WriteLine("Writing encryptedData: " + ndx++); } inputStream.Position = 0; encStream.Position = 0; encStream.CopyTo(inputStream, (int)_header.BlockSizeAlloc); } } if (seek) { inputStream.Flush(); inputStream.Seek(0, SeekOrigin.Begin); } //GlobalExtension.HideProgress(); }
public static string Encrypt(string plainText) { return(RijndaelEncryptor.Encrypt(plainText)); }
public static string GetValue(string key, bool reload) { if (appSettings != null && appSettings.ContainsKey(key) && !reload) { return(appSettings[key]); } else { Init(); string masterEncryptedAppHash = serverKey.EncryptWithPublicKey(config.ApplicationHash); //RSAKeyPair tempKey = new RSAKeyPair(); //RijndaelKeyVectorPair clientKey = GetClientKey(masterEncryptedAppHash, tempKey); ConfigurationResponse valueResponse = client.GetValue(masterEncryptedAppHash, RijndaelEncryptor.Encrypt(key, clientKey.Base64Key, clientKey.Base64InitializationVector)); string retVal = string.Empty; if (!string.IsNullOrEmpty(valueResponse.SettingValue)) { retVal = RijndaelEncryptor.Decrypt(valueResponse.SettingValue, clientKey.Base64Key, clientKey.Base64InitializationVector); } if (appSettings.ContainsKey(key)) { appSettings[key] = retVal; } else { appSettings.Add(key, retVal); } lastResponse = valueResponse; return(retVal); } }
public string Encrypt(string clearText, string strKey, string strIv) { return(RijndaelEncryptor.Encrypt(clearText, strKey, strIv)); }
public void Read(Stream psarc, bool lazy = false) { this.TOC.Clear(); _reader = new BigEndianBinaryReader(psarc); this.header.MagicNumber = _reader.ReadUInt32(); if (this.header.MagicNumber == 1347633490)//PSAR (BE) { //Parse Header this.header.VersionNumber = _reader.ReadUInt32(); this.header.CompressionMethod = _reader.ReadUInt32(); this.header.TotalTOCSize = _reader.ReadUInt32(); this.header.TOCEntrySize = _reader.ReadUInt32(); this.header.numFiles = _reader.ReadUInt32(); this.header.blockSizeAlloc = _reader.ReadUInt32(); this.header.archiveFlags = _reader.ReadUInt32(); //Read TOC const int headerSize = 32; int tocSize = (int)this.header.TotalTOCSize - headerSize; if (this.header.archiveFlags == 4) //TOC_ENCRYPTED { // Decrypt TOC var tocStream = new MemoryStream(); using (var decStream = new MemoryStream()) { RijndaelEncryptor.DecryptPSARC(psarc, decStream, this.header.TotalTOCSize); int bytesRead; int decSize = 0; var buffer = new byte[this.header.blockSizeAlloc]; while ((bytesRead = decStream.Read(buffer, 0, buffer.Length)) > 0) { decSize += bytesRead; if (decSize > tocSize) { bytesRead = tocSize - (decSize - bytesRead); } tocStream.Write(buffer, 0, bytesRead); } } tocStream.Seek(0, SeekOrigin.Begin); _reader = new BigEndianBinaryReader(tocStream); } ParseTOC(); //Parse zBlocksSizeList int zNum = (int)((tocSize - this.header.numFiles * this.header.TOCEntrySize) / bNum); var zLengths = new uint[zNum]; for (int i = 0; i < zNum; i++) { switch (bNum) { case 2: //64KB zLengths[i] = _reader.ReadUInt16(); break; case 3: //16MB zLengths[i] = _reader.ReadUInt24(); break; case 4: //4GB zLengths[i] = _reader.ReadUInt32(); break; } } this.zBlocksSizeList = zLengths.ToArray(); _reader.BaseStream.Flush(); _reader = new BigEndianBinaryReader(psarc); // Validate psarc size // if (psarc.Length < RequiredPsarcSize()) // throw new InvalidDataException("Truncated psarc."); // try to unpack corrupt CDLC for now if (this.header.CompressionMethod == 2053925218) //zlib (BE) { //Read Filenames ReadManifest(); psarc.Seek(this.header.TotalTOCSize, SeekOrigin.Begin); if (!lazy) {// Read Data InflateEntries(); } } else if (this.header.CompressionMethod == 1819962721)//lzma (BE) { throw new NotImplementedException("LZMA compression not supported."); } } psarc.Flush(); }
public void Write(Stream psarc, bool encrypt) { this.header.archiveFlags = encrypt ? 4U : 0U; this.header.TOCEntrySize = 30; this.WriteManifest(); //Pack entries Dictionary <Entry, byte[]> zStreams; List <uint> zLengths; DeflateEntries(out zStreams, out zLengths); //Build zLengths _writer = new BigEndianBinaryWriter(psarc); this.header.TotalTOCSize = (uint)(32 + this.TOC.Count * this.header.TOCEntrySize + zLengths.Count * bNum); this.TOC[0].Offset = (ulong)this.header.TotalTOCSize; for (int i = 1; i < this.TOC.Count; i++) { this.TOC[i].Offset = this.TOC[i - 1].Offset + (ulong)(zStreams[this.TOC[i - 1]].Length); } //Write Header _writer.Write(this.header.MagicNumber); _writer.Write(this.header.VersionNumber); _writer.Write(this.header.CompressionMethod); _writer.Write(this.header.TotalTOCSize); _writer.Write(this.header.TOCEntrySize); _writer.Write(this.TOC.Count); _writer.Write(this.header.blockSizeAlloc); _writer.Write(this.header.archiveFlags); //Write Table of contents foreach (Entry current in this.TOC) { current.UpdateNameMD5(); _writer.Write((current.Id == 0) ? new byte[16] : current.MD5); _writer.Write(current.zIndexBegin); _writer.WriteUInt40((ulong)current.Data.Length); _writer.WriteUInt40(current.Offset); } foreach (uint zLen in zLengths) { switch (bNum) { case 2: _writer.Write((ushort)zLen); break; case 3: _writer.WriteUInt24(zLen); break; case 4: _writer.Write(zLen); break; } } //Write zData foreach (Entry current in this.TOC) { _writer.Write(zStreams[current]); current.Data.Close(); } if (encrypt) {// Encrypt TOC var encStream = new MemoryStreamExtension(); using (var outputStream = new MemoryStreamExtension()) { int bytesRead; int decSize = 0; var buffer = new byte[30000]; int tocSize = (int)this.header.TotalTOCSize - 32; psarc.Seek(32, SeekOrigin.Begin); RijndaelEncryptor.EncryptPSARC(psarc, outputStream, this.header.TotalTOCSize); psarc.Seek(0, SeekOrigin.Begin); while ((bytesRead = psarc.Read(buffer, 0, buffer.Length)) > 0) { encStream.Write(buffer, 0, bytesRead); } outputStream.Seek(0, SeekOrigin.Begin); encStream.Seek(32, SeekOrigin.Begin); while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0) { decSize += bytesRead; if (decSize > tocSize) { bytesRead = tocSize - (decSize - bytesRead); } encStream.Write(buffer, 0, bytesRead); } } psarc.Seek(0, SeekOrigin.Begin); encStream.Seek(0, SeekOrigin.Begin); encStream.CopyTo(psarc, (int)this.header.blockSizeAlloc); } psarc.Flush(); }
/// <summary> /// Inflates selected entry. /// </summary> /// <param name="entry">Entry to unpack.</param> /// <param name = "destfilepath">Destination file used instead of the temp file.</param> public void InflateEntry(Entry entry, string destfilepath = "") { if (entry.Length == 0) { return; //skip empty files } // Decompress Entry const int zHeader = 0x78DA; uint zChunkID = entry.zIndexBegin; int blockSize = (int)_header.BlockSizeAlloc; //bool isZlib = _header.CompressionMethod == 2053925218; if (destfilepath.Length > 0) { entry.Data = new FileStream(destfilepath, FileMode.Create, FileAccess.Write, FileShare.Read); } else { if (UseMemory) { entry.Data = new MemoryStreamExtension(); } else { entry.Data = new TempFileStream(); } } _reader.BaseStream.Position = (long)entry.Offset; do { // check for corrupt CDLC content and catch exceptions try { if (_zBlocksSizeList[zChunkID] == 0U) // raw. full cluster used. { entry.Data.Write(_reader.ReadBytes(blockSize), 0, blockSize); } else { var num = _reader.ReadUInt16(); _reader.BaseStream.Position -= 2L; var array = _reader.ReadBytes((int)_zBlocksSizeList[zChunkID]); if (num == zHeader) { // compressed try { RijndaelEncryptor.Unzip(array, entry.Data, false); } catch (Exception ex) //IOException { // corrupt CDLC zlib.net exception ... try to unpack if (String.IsNullOrEmpty(entry.Name)) { ErrMsg.AppendLine(String.Format(@"CDLC contains a zlib exception.{1}Warning: {0}", ex.Message, Environment.NewLine)); } else { ErrMsg.AppendLine(String.Format(@"CDLC contains a broken datachunk in file '{0}'.{2}Warning Type 1: {1}", entry.Name.Split('/').Last(), ex.Message, Environment.NewLine)); } Debug.Write(ErrMsg.ToString()); } } else // raw. used only for data(chunks) smaller than 64 kb { entry.Data.Write(array, 0, array.Length); } } zChunkID += 1; } catch (Exception ex) // index is outside the bounds of the array { // corrupt CDLC data length ... try to unpack ErrMsg.AppendLine(String.Format(@"CDLC contains a broken datachunk in file '{0}'.{2}Warning Type 2: {1}", entry.Name.Split('/').Last(), ex.Message, Environment.NewLine)); Debug.Write(ErrMsg.ToString()); break; } } while (entry.Data.Length < (long)entry.Length); entry.Data.Seek(0, SeekOrigin.Begin); entry.Data.Flush(); }
static void Main(string[] args) { var arguments = new Arguments(); var options = GetOptions(arguments); if (args.Length == 0) { options.WriteOptionDescriptions(Console.Out); return; } try { options.Parse(args); if (arguments.ShowHelp) { options.WriteOptionDescriptions(Console.Out); return; } var inputFiles = arguments.InputFiles.ToList(); if (!arguments.InputFiles.Any() && args.Length > 0) { inputFiles.Add(args.First()); } foreach (var file in inputFiles) { FileAttributes attr = File.GetAttributes(Path.GetFullPath(file)); if ((attr & FileAttributes.Directory) == FileAttributes.Directory && Directory.Exists(file)) { foreach (var file1 in Directory.EnumerateFiles(file, "*.*", SearchOption.AllDirectories)) { if (File.Exists(file1)) { arguments.InputFiles.Add(file1); } } } else { arguments.InputFiles.Add(file); } } var missingFiles = arguments.InputFiles.Where(i => !File.Exists(i)).ToList(); if (missingFiles.Any()) { var message = "The specified input file(s) do not exist: \n" + string.Join("\n", missingFiles.Select(f => "\t" + f)); ShowHelpfulError(message); } } catch (OptionException ex) { ShowHelpfulError(ex.Message); return; } foreach (var inputPath in arguments.InputFiles) { var outputDirectory = Path.GetDirectoryName(inputPath); using (var inputStream = File.OpenRead(inputPath)) { if (!arguments.Encrypt) { var outputFilename = Path.GetFileName(inputPath) + ".decrypted"; var outputPath = Path.Combine(outputDirectory, outputFilename); Directory.CreateDirectory(outputDirectory); using (var outputStream = File.Create(outputPath)) RijndaelEncryptor.DecryptFile(inputStream, outputStream, RijndaelEncryptor.PCFilesKey); } if (arguments.Encrypt) { var outputFilename = Path.GetFileName(inputPath) + ".encrypted"; var outputPath = Path.Combine(outputDirectory, outputFilename); Directory.CreateDirectory(outputDirectory); using (var outputStream = File.Create(outputPath)) RijndaelEncryptor.EncryptFile(inputStream, outputStream, RijndaelEncryptor.PCFilesKey); } } } }
public static void PackSng(Stream input, Stream output, Platform platform) { EndianBitConverter conv; Int32 platformHeader; switch (platform.platform) { case GamePlatform.Pc: case GamePlatform.Mac: // Desktop conv = EndianBitConverter.Little; platformHeader = 3; break; case GamePlatform.XBox360: case GamePlatform.PS3: // Console conv = EndianBitConverter.Big; platformHeader = 1; break; default: conv = EndianBitConverter.Little; platformHeader = 3; break; } using (EndianBinaryWriter w = new EndianBinaryWriter(conv, output)) { w.Write((Int32)0x4A); w.Write(platformHeader); byte[] inputChartData = null; using (var mStream = new MemoryStream()) { input.CopyTo(mStream); inputChartData = mStream.ToArray(); } // pack with zlib MemoryStream zData = new MemoryStream(); ZOutputStream zOut = new ZOutputStream(zData, zlib.zlibConst.Z_BEST_COMPRESSION); zOut.Write(inputChartData, 0, inputChartData.Length); zOut.finish(); byte[] packed = zData.ToArray(); if (platformHeader == 3) { MemoryStream encrypted = new MemoryStream(); MemoryStream plain = new MemoryStream(); var encw = new EndianBinaryWriter(conv, plain); // write size of uncompressed data and packed data itself encw.Write((Int32)inputChartData.Length); encw.Write(packed); encw.Flush(); MemoryStream inputPlainStream = new MemoryStream(plain.ToArray()); // choose key byte[] key; switch (platform.platform) { case GamePlatform.Mac: key = RijndaelEncryptor.SngKeyMac; break; default: //PC key = RijndaelEncryptor.SngKeyPC; break; } // encrypt (writes 16B IV and encrypted data) RijndaelEncryptor.EncryptSngData(inputPlainStream, encrypted, key); w.Write(encrypted.ToArray()); // append zero signature w.Write(new Byte[56]); } else { // unencrypted and unsigned w.Write((Int32)inputChartData.Length); w.Write(packed); } output.Flush(); } }
public void Write(Stream inputStream, bool encrypt = false, bool seek = true) { _header.ArchiveFlags = encrypt ? 4U : 0U; _header.TOCEntrySize = 30U; WriteManifest(); //Pack entries List <uint> zLengths; Dictionary <Entry, byte[]> zStreams; DeflateEntries(out zStreams, out zLengths); //Build zLengths _writer = new BigEndianBinaryWriter(inputStream); _header.TotalTOCSize = (uint)(32 + _toc.Count * _header.TOCEntrySize + zLengths.Count * bNum); _toc[0].Offset = _header.TotalTOCSize; for (int i = 1; i < _toc.Count; i++) { _toc[i].Offset = _toc[i - 1].Offset + (ulong)(zStreams[_toc[i - 1]].Length); } //Write Header _writer.Write(_header.MagicNumber); _writer.Write(_header.VersionNumber); _writer.Write(_header.CompressionMethod); _writer.Write(_header.TotalTOCSize); _writer.Write(_header.TOCEntrySize); _writer.Write(_toc.Count); _writer.Write(_header.BlockSizeAlloc); _writer.Write(_header.ArchiveFlags); //Write Table of contents foreach (Entry current in _toc) { current.UpdateNameMD5(); _writer.Write(current.MD5); _writer.Write(current.zIndexBegin); _writer.WriteUInt40((ulong)current.Data.Length);//current.Length _writer.WriteUInt40(current.Offset); } foreach (uint zLen in zLengths) { switch (bNum) { case 2: //16bit _writer.Write((ushort)zLen); break; case 3: //24bit _writer.WriteUInt24(zLen); break; case 4: //32bit _writer.Write(zLen); break; } } zLengths = null; // Write zData var ndx = 0; // for debugging var step = Math.Round(1D / (this.TOC.Count + 2) * 100, 3); double progress = 0; GlobalExtension.ShowProgress("Writing Zipped Data ..."); foreach (Entry current in _toc) { _writer.Write(zStreams[current]); progress += step; GlobalExtension.UpdateProgress.Value = (int)progress; Debug.WriteLine("Zipped: " + ndx++); current.Data.Close(); } zStreams = null; if (encrypt) // Encrypt TOC { using (var outputStream = new MemoryStreamExtension()) { var encStream = new MemoryStreamExtension(); inputStream.Position = 32L; RijndaelEncryptor.EncryptPSARC(inputStream, outputStream, _header.TotalTOCSize); inputStream.Position = 0L; // quick copy header from input stream var buffer = new byte[32]; encStream.Write(buffer, 0, inputStream.Read(buffer, 0, buffer.Length)); encStream.Position = 32; //sanity check ofc inputStream.Flush(); int tocSize = (int)_header.TotalTOCSize - 32; int decSize = 0; buffer = new byte[1024 * 16]; // more efficient use of memory ndx = 0; // for debugging step = Math.Round(1D / (((double)tocSize / buffer.Length) + 2) * 100, 3); progress = 0; GlobalExtension.ShowProgress("Writing Encrypted Data ..."); int bytesRead; while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0) { decSize += bytesRead; if (decSize > tocSize) { bytesRead = tocSize - (decSize - bytesRead); } encStream.Write(buffer, 0, bytesRead); progress += step; GlobalExtension.UpdateProgress.Value = (int)progress; Debug.WriteLine("Encrypted: " + ndx++); } inputStream.Position = 0; encStream.Position = 0; encStream.CopyTo(inputStream, (int)_header.BlockSizeAlloc); } } if (seek) // May be redundant { inputStream.Flush(); inputStream.Position = 0; } //GlobalExtension.HideProgress(); }
public string Decrypt(string cipherText, string strKey, string strIv) { return(RijndaelEncryptor.Decrypt(cipherText, strKey, strIv)); }
/// <summary> /// Inflates selected entry. /// </summary> /// <param name="entry">Enty to unpack.</param> /// <param name = "destfilepath">Destanation file used instead of the temp file.</param> public void InflateEntry(Entry entry, string destfilepath = "") { if (entry.Length > 0) {// Decompress Entry uint zChunkID = entry.zIndexBegin; int blockSize = (int)this.header.blockSizeAlloc; bool isZlib = this.header.CompressionMethod == 2053925218; const int zHeader = 0x78DA; if (destfilepath.Length > 0) { entry.Data = new FileStream(destfilepath, FileMode.Create, FileAccess.Write, FileShare.Read); } else { entry.Data = new TempFileStream(); } var data = entry.Data; _reader.BaseStream.Position = (long)entry.Offset; do { // check for corrupt CDLC content and catch exceptions try { if (this.zBlocksSizeList[zChunkID] == 0) { // raw byte[] array = _reader.ReadBytes(blockSize); data.Write(array, 0, blockSize); } else { var num = _reader.ReadUInt16(); _reader.BaseStream.Position -= 2; byte[] array = _reader.ReadBytes((int)this.zBlocksSizeList[zChunkID]); if (num == zHeader) { // compressed try { RijndaelEncryptor.Unzip(array, data, false); } catch (Exception ex) { // corrupt CDLC zlib.net exception ... try to unpack if (String.IsNullOrEmpty(entry.Name)) { ErrMSG = String.Format(@"{1}CDLC contains a zlib exception.{1}Warning: {0}{1}", ex.Message, Environment.NewLine); } else { ErrMSG = String.Format(@"{2}CDLC contains a broken datachunk in file '{0}'.{2}Warning: {1}{2}", entry.Name.Split('/').Last(), ex.Message, Environment.NewLine); } Console.Write(ErrMSG); } } else { // raw. used only after 0? data.Write(array, 0, array.Length); } } zChunkID += 1; } catch (Exception ex) // index is outside the bounds of the array { // corrupt CDLC data length ... try to unpack ErrMSG = String.Format(@"{2}CDLC contains a broken datachunk in file '{0}'.{2}Warning: {1}{2}", entry.Name.Split('/').Last(), ex.Message, Environment.NewLine); Console.Write(ErrMSG + Environment.NewLine); break; } }while (data.Length < (long)entry.Length); data.Seek(0, SeekOrigin.Begin); data.Flush(); } }
public void Write(Stream inputStream, bool encrypt) { // TODO: This produces perfect results for song archives (original vs repacked) // there are slight differences in the binary of large archives (original vs repacked). WHY? // this.header.archiveFlags = encrypt ? 4U : 0U; this.header.TOCEntrySize = 30; this.WriteManifest(); //Pack entries Dictionary <Entry, byte[]> zStreams; List <uint> zLengths; DeflateEntries(out zStreams, out zLengths); //Build zLengths _writer = new BigEndianBinaryWriter(inputStream); this.header.TotalTOCSize = (uint)(32 + this.TOC.Count * this.header.TOCEntrySize + zLengths.Count * bNum); this.TOC[0].Offset = (ulong)this.header.TotalTOCSize; for (int i = 1; i < this.TOC.Count; i++) { this.TOC[i].Offset = this.TOC[i - 1].Offset + (ulong)(zStreams[this.TOC[i - 1]].Length); } //Write Header _writer.Write(this.header.MagicNumber); _writer.Write(this.header.VersionNumber); _writer.Write(this.header.CompressionMethod); _writer.Write(this.header.TotalTOCSize); _writer.Write(this.header.TOCEntrySize); _writer.Write(this.TOC.Count); _writer.Write(this.header.blockSizeAlloc); _writer.Write(this.header.archiveFlags); //Write Table of contents foreach (Entry current in this.TOC) { current.UpdateNameMD5(); _writer.Write((current.Id == 0) ? new byte[16] : current.MD5); _writer.Write(current.zIndexBegin); _writer.WriteUInt40((ulong)current.Data.Length); _writer.WriteUInt40(current.Offset); } foreach (uint zLen in zLengths) { switch (bNum) { case 2: _writer.Write((ushort)zLen); break; case 3: _writer.WriteUInt24(zLen); break; case 4: _writer.Write(zLen); break; } } // Write zData var ndx = 0; // for debugging var step = Math.Round(1.0 / (this.TOC.Count + 2) * 100, 3); double progress = 0; GlobalExtension.ShowProgress("Writing Zipped Data ..."); foreach (Entry current in this.TOC) { _writer.Write(zStreams[current]); progress += step; GlobalExtension.UpdateProgress.Value = (int)progress; Debug.WriteLine("Zipped: " + ndx++); current.Data.Close(); } if (encrypt) // Encrypt TOC { using (var outputStream = new MemoryStreamExtension()) { var encStream = new MemoryStreamExtension(); inputStream.Seek(32, SeekOrigin.Begin); RijndaelEncryptor.EncryptPSARC(inputStream, outputStream, this.header.TotalTOCSize); inputStream.Seek(0, SeekOrigin.Begin); int bytesRead; var buffer = new byte[32]; bytesRead = inputStream.Read(buffer, 0, buffer.Length); inputStream.Flush(); // quick copy header from input stream encStream.Write(buffer, 0, bytesRead); encStream.Seek(32, SeekOrigin.Begin); int tocSize = (int)this.header.TotalTOCSize - 32; int decSize = 0; buffer = new byte[1024 * 16]; // more effecient use of memory ndx = 0; // for debuging step = Math.Round(1.0 / ((tocSize / buffer.Length) + 2) * 100, 3); progress = 0; GlobalExtension.ShowProgress("Writing Encrypted Data ..."); while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0) { decSize += bytesRead; if (decSize > tocSize) { bytesRead = tocSize - (decSize - bytesRead); } encStream.Write(buffer, 0, bytesRead); progress += step; GlobalExtension.UpdateProgress.Value = (int)progress; Debug.WriteLine("Encrypted: " + ndx++); } inputStream.Seek(0, SeekOrigin.Begin); encStream.Seek(0, SeekOrigin.Begin); encStream.CopyTo(inputStream, (int)this.header.blockSizeAlloc); } } inputStream.Flush(); GlobalExtension.HideProgress(); }