using System; using System.IO; using System.Diagnostics; namespace TwlBackupBlock { /// /// 署名ブロック中のハッシュセット。 /// public class TwlBackupHashSet { public const int HASH_SIZE = 32; public const int NUM_OF_SECTION = 4; public readonly byte[] banner; public readonly byte[] header; public readonly byte[][] section; public TwlBackupHashSet() { banner = new byte[HASH_SIZE]; header = new byte[HASH_SIZE]; section = new byte[NUM_OF_SECTION][]; for (int i = 0; i < section.Length; i++) { section[i] = new byte[HASH_SIZE]; } } } /// /// 署名ブロックのデータ本体。 /// public class SignatureBody : AbstractBody { public const int SIGNATURE_SIZE = 1024; public const int ECC_SIGN_SIZE = 60; public const int ECC_CERT_SIZE = 384; public readonly TwlBackupHashSet digest; public readonly byte[] sign; public readonly byte[][] cert; public UInt32 reserved; public SignatureBody(byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } if (data.Length != SIGNATURE_SIZE) { string message = string.Format("data.Length % {0} != 0 (data.Length:{1})", SIGNATURE_SIZE, data.Length); throw new ArgumentException("data", message); } digest = new TwlBackupHashSet(); sign = new byte[ECC_SIGN_SIZE]; cert = new byte[2][]; for (int i = 0; i < cert.Length; i++) { cert[i] = new byte[ECC_CERT_SIZE]; } SetBytes(data); } public override byte this[int index] { get { if (index < 0 || index >= SIGNATURE_SIZE) { throw new ArgumentException("index"); } return ReadByte(index); } set { if (index < 0 || index >= SIGNATURE_SIZE) { throw new ArgumentException("index"); } WriteByte(index, value); } } public override int Length { get { return SIGNATURE_SIZE; } } /// /// 指定したバイトを取得します。 /// /// 取得したいバイトのインデックス。 /// で指定したバイト public byte ReadByte(int index) { if (index < 0 || index >= SIGNATURE_SIZE) { throw new ArgumentException("index"); } // TODO 処理が遅ければ効率化 byte[] bytes = GetBytes(); return bytes[index]; } /// /// 指定したバイトを書き換えます。 /// /// 書き換えたいバイトのインデックス。 /// 上書きに使うバイト。 public void WriteByte(int index, byte b) { if (index < 0 || index >= SIGNATURE_SIZE) { throw new ArgumentException("index"); } // TODO 処理が遅ければ効率化 byte[] bytes = GetBytes(); bytes[index] = b; SetBytes(bytes); } public override byte[] GetBytes() { byte[] bytes = new byte[SIGNATURE_SIZE]; using (var ms = new MemoryStream(bytes)) using (var bw = new BinaryWriter(ms)) { bw.Write(digest.banner); bw.Write(digest.header); foreach (var e in digest.section) { bw.Write(e); } bw.Write(sign); foreach (var e in cert) { bw.Write(e); } bw.Write(reserved); Debug.Assert(ms.Position == SIGNATURE_SIZE); } return bytes; } public override void SetBytes(byte[] bytes) { if (bytes == null) { throw new ArgumentNullException("bytes"); } if (bytes.Length != SIGNATURE_SIZE) { string message = string.Format("bytes.Length != {0} (bytes.Length:{1})", SIGNATURE_SIZE, bytes.Length); throw new ArgumentException("bytes", message); } using (var ms = new MemoryStream(bytes)) using (var br = new ExtBinaryReader(ms)) { br.Read(digest.banner); br.Read(digest.header); foreach (var e in digest.section) { br.Read(e); } br.Read(sign); foreach (var e in cert) { br.Read(e); } br.Read(ref reserved); Debug.Assert(ms.Position == SIGNATURE_SIZE); } } public override object Clone() { return new SignatureBody(GetBytes()); } } }