internal Stream OpenEncryptedEntry(AgsiArchive arc, AgsiEntry entry) { uint enc_size = entry.Size; if (enc_size > 1024) { enc_size = 1032; } using (var des = DES.Create()) { des.Key = arc.Key; des.Mode = CipherMode.ECB; des.Padding = PaddingMode.Zeros; using (var enc = arc.File.CreateStream(entry.Offset, enc_size)) using (var dec = new InputCryptoStream(enc, des.CreateDecryptor())) { var output = new byte[enc_size]; dec.Read(output, 0, output.Length); int header_size; if (!entry.IsSpecial) { header_size = output.ToInt32(output.Length - 4); if (header_size > entry.UnpackedSize) { throw new InvalidEncryptionScheme(); } } else { header_size = (int)entry.UnpackedSize; } if (!entry.IsSpecial && entry.Size > enc_size) { var header = new byte[header_size]; Buffer.BlockCopy(output, 0, header, 0, header_size); var input = arc.File.CreateStream(entry.Offset + enc_size, entry.Size - enc_size); return(new PrefixStream(header, input)); } else { return(new BinMemoryStream(output, 0, header_size, entry.Name)); } } } }
bool ReadBlock() { if (m_position >= m_length) { return(false); } m_block_start = m_position & ~0xFFFL; m_block_length = m_view.Read(m_block_start, m_block, 0, 0x1000); if (m_block_length != 0x1000) { return(false); } using (var decryptor = m_encryption.CreateDecryptor((int)(m_block_start >> 12))) using (var enc = new BinMemoryStream(m_block)) using (var dec = new InputCryptoStream(enc, decryptor)) dec.Read(m_block, 0, m_block_length); return(true); }
static byte[] CzDecryptData(byte[] data) { int padded_size = data.Length - 5; int original_size = padded_size - (data[padded_size+1] ^ data[padded_size]); uint iv_seed = data.ToUInt32 (padded_size+1) ^ CzIvSeed; using (var aes = Aes.Create()) { aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.Zeros; aes.Key = CzDefaultKey; aes.IV = CzCreateIV (iv_seed); using (var enc = new MemoryStream (data, 0, padded_size)) using (var dec = new InputCryptoStream (enc, aes.CreateDecryptor())) { var original = new byte[original_size]; dec.Read (original, 0, original_size); return original; } } }
public override ArcFile TryOpen(ArcView file) { uint flags = file.View.ReadUInt32(4); if ((flags & 0x7FFFFFFF) != 0x10000) { return(null); } int count = file.View.ReadInt32(8); if (!IsSaneCount(count)) { return(null); } bool is_encrypted = (flags >> 31) != 0; uint index_size = (uint)((count * 24 + 31) & -4096) + 0xFE0u; uint names_size = file.View.ReadUInt32(12); var arc_md5 = file.View.ReadBytes(0x10, 0x10); var index = new byte[index_size + names_size]; CsafEncryption enc = null; try { if (is_encrypted) { file.View.Read(0x20, index, 0, index_size); enc = new CsafEncryption(DefaultKey, DefaultIV); using (var decryptor = enc.CreateDecryptor(0)) using (var enc_names = file.CreateStream(0x20 + index_size, names_size)) using (var dec_names = new InputCryptoStream(enc_names, decryptor)) { dec_names.Read(index, (int)index_size, (int)names_size); } } else { file.View.Read(0x20, index, 0, index_size + names_size); } using (var md5 = MD5.Create()) { var hash = md5.ComputeHash(index); if (!hash.SequenceEqual(arc_md5)) { return(null); } int index_pos = 0x10; int name_pos = (int)index_size; var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { int j; for (j = name_pos; j + 1 < index.Length; j += 2) { if (index[j] == 0 && index[j + 1] == 0) { break; } } int name_length = j - name_pos; var name = Encoding.Unicode.GetString(index, name_pos, name_length); // hash = md5.ComputeHash (index, name_pos, name_length); // == [index_pos-0x10] name_pos += name_length + 10; var entry = Create <Entry> (name); entry.Offset = (long)index.ToUInt32(index_pos) << 12; entry.Size = index.ToUInt32(index_pos + 4); index_pos += 0x18; if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } dir.Add(entry); } if (!is_encrypted) { return(new ArcFile(file, this, dir)); } var arc = new CsafArchive(file, this, dir, enc); enc = null; return(arc); } } finally { if (enc != null) { enc.Dispose(); } } }