vipnet-extract-data/VipNetExtract2/VipNetContainer.cs

73 lines
2.8 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1;
namespace VipNetExtract
{
class VipNetContainer
{
private VipNetContainer(
string type, uint version, int headerSize,
byte[] header, IList<VipNetContainerEntry> entries)
{
Type = type;
Version = version;
HeaderSize = headerSize;
Header = header;
Entries = entries;
}
public string Type { get; }
public uint Version { get; }
public int HeaderSize { get; }
public byte[] Header { get; }
public IList<VipNetContainerEntry> Entries { get; }
public static VipNetContainer LoadFromStream(Stream strm)
{
using (var reader = new BinaryReader(strm)) {
var type = Encoding.ASCII.GetString(reader.ReadBytes(4));
if (type != "ITCS" && type != "PKEY" && type != "_CCK" && type != "_LCK")
throw new NotSupportedException($"Неподдерживаемый тип контейнера: {type}.");
var version = reader.ReadUInt32();
if (LoWord(version) > 0xFF || HiWord(version) > 2)
throw new NotSupportedException($"Неподдерживаемая версия контейнера: {version}.");
var headerSize = reader.ReadInt32();
var header = new byte[headerSize];
if (headerSize > 0)
header = reader.ReadBytes(headerSize);
var entries = new List<VipNetContainerEntry>();
while (strm.Position < strm.Length) {
var entrySize = reader.ReadInt32();
var entryStartPos = strm.Position;
var entrySeq = (Asn1Sequence)Asn1Object.FromStream(strm);
var keySize = reader.ReadInt32();
if (keySize < 0 || strm.Position + keySize - entryStartPos != entrySize)
throw new InvalidOperationException($"Некорректный размер блока с ключом: {keySize}.");
var key = reader.ReadBytes(keySize);
entries.Add(new VipNetContainerEntry(entrySeq, key));
}
if (entries.Count == 0)
throw new InvalidOperationException("Контейнер не содержит записей.");
return new VipNetContainer(type, version, headerSize, header, entries);
}
}
public static VipNetContainer LoadFromFile(string fileName)
{
using (var strm = File.OpenRead(fileName))
return LoadFromStream(strm);
}
static uint LoWord(uint x) => x & 0x0000FFFF;
static uint HiWord(uint x) => x >> 16;
}
}