From ae66e668da98ed3ceac7fa28bb2e9f92a220e595 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 17 Nov 2023 10:09:10 +0700 Subject: Refactor LMS parsing --- .../src/pqc/crypto/lms/HSSPrivateKeyParameters.cs | 67 ++++++++------------ .../src/pqc/crypto/lms/HSSPublicKeyParameters.cs | 41 +++++-------- crypto/src/pqc/crypto/lms/HSSSignature.cs | 68 +++++++++++---------- crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs | 59 ++++++++---------- crypto/src/pqc/crypto/lms/LMOtsSignature.cs | 54 +++++++--------- .../src/pqc/crypto/lms/LMSPrivateKeyParameters.cs | 71 +++++++++------------- .../src/pqc/crypto/lms/LMSPublicKeyParameters.cs | 55 +++++++---------- crypto/src/pqc/crypto/lms/LMSSignature.cs | 56 ++++++++--------- crypto/src/util/io/BinaryReaders.cs | 9 +++ 9 files changed, 210 insertions(+), 270 deletions(-) diff --git a/crypto/src/pqc/crypto/lms/HSSPrivateKeyParameters.cs b/crypto/src/pqc/crypto/lms/HSSPrivateKeyParameters.cs index 447dbad27..676da3db4 100644 --- a/crypto/src/pqc/crypto/lms/HSSPrivateKeyParameters.cs +++ b/crypto/src/pqc/crypto/lms/HSSPrivateKeyParameters.cs @@ -64,60 +64,47 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms public static HssPrivateKeyParameters GetInstance(object src) { if (src is HssPrivateKeyParameters hssPrivateKeyParameters) - { return hssPrivateKeyParameters; - } - else if (src is BinaryReader binaryReader) - { - int version = BinaryReaders.ReadInt32BigEndian(binaryReader); - if (version != 0) - throw new Exception("unknown version for HSS private key"); - int d = BinaryReaders.ReadInt32BigEndian(binaryReader); + if (src is BinaryReader binaryReader) + return Parse(binaryReader); - long index = BinaryReaders.ReadInt64BigEndian(binaryReader); + if (src is Stream stream) + return BinaryReaders.Parse(Parse, stream, leaveOpen: true); - long maxIndex = BinaryReaders.ReadInt64BigEndian(binaryReader); + if (src is byte[] bytes) + return BinaryReaders.Parse(Parse, new MemoryStream(bytes, false), leaveOpen: false); - bool limited = binaryReader.ReadBoolean(); + throw new ArgumentException($"cannot parse {src}"); + } - var keys = new List(); - var signatures = new List(); + internal static HssPrivateKeyParameters Parse(BinaryReader binaryReader) + { + int version = BinaryReaders.ReadInt32BigEndian(binaryReader); + if (version != 0) + throw new Exception("unknown version for HSS private key"); - for (int t = 0; t < d; t++) - { - keys.Add(LmsPrivateKeyParameters.GetInstance(src)); - } + int d = BinaryReaders.ReadInt32BigEndian(binaryReader); - for (int t = 0; t < d - 1; t++) - { - signatures.Add(LmsSignature.GetInstance(src)); - } + long index = BinaryReaders.ReadInt64BigEndian(binaryReader); - return new HssPrivateKeyParameters(d, keys, signatures, index, maxIndex, limited); - } - else if (src is byte[] bytes) + long maxIndex = BinaryReaders.ReadInt64BigEndian(binaryReader); + + bool limited = binaryReader.ReadBoolean(); + + var keys = new List(d); + for (int t = 0; t < d; t++) { - BinaryReader input = null; - try // 1.5 / 1.6 compatibility - { - input = new BinaryReader(new MemoryStream(bytes)); - return GetInstance(input); - } - finally - { - if (input != null) - { - input.Close(); - } - } + keys.Add(LmsPrivateKeyParameters.Parse(binaryReader)); } - else if (src is MemoryStream memoryStream) + + var signatures = new List(d - 1); + for (int t = 1; t < d; t++) { - return GetInstance(Streams.ReadAll(memoryStream)); + signatures.Add(LmsSignature.Parse(binaryReader)); } - throw new Exception($"cannot parse {src}"); + return new HssPrivateKeyParameters(d, keys, signatures, index, maxIndex, limited); } public int L => l; diff --git a/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs b/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs index 01bac93b8..d3bc697d9 100644 --- a/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs +++ b/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Text; using Org.BouncyCastle.Utilities.IO; @@ -21,37 +22,27 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms public static HssPublicKeyParameters GetInstance(object src) { if (src is HssPublicKeyParameters hssPublicKeyParameters) - { return hssPublicKeyParameters; - } - else if (src is BinaryReader binaryReader) - { - int L = BinaryReaders.ReadInt32BigEndian(binaryReader); - LmsPublicKeyParameters lmsPublicKey = LmsPublicKeyParameters.GetInstance(src); - return new HssPublicKeyParameters(L, lmsPublicKey); - } - else if (src is byte[] bytes) - { - BinaryReader input = null; - try // 1.5 / 1.6 compatibility - { - input = new BinaryReader(new MemoryStream(bytes)); - return GetInstance(input); - } - finally - { - if (input != null) input.Close(); - } - } - else if (src is MemoryStream memoryStream) - { - return GetInstance(Streams.ReadAll(memoryStream)); - } + if (src is BinaryReader binaryReader) + return Parse(binaryReader); + + if (src is Stream stream) + return BinaryReaders.Parse(Parse, stream, leaveOpen: true); + + if (src is byte[] bytes) + return BinaryReaders.Parse(Parse, new MemoryStream(bytes, false), leaveOpen: false); throw new ArgumentException($"cannot parse {src}"); } + internal static HssPublicKeyParameters Parse(BinaryReader binaryReader) + { + int L = BinaryReaders.ReadInt32BigEndian(binaryReader); + LmsPublicKeyParameters lmsPublicKey = LmsPublicKeyParameters.Parse(binaryReader); + return new HssPublicKeyParameters(L, lmsPublicKey); + } + public int L => m_l; public LmsPublicKeyParameters LmsPublicKey => m_lmsPublicKey; diff --git a/crypto/src/pqc/crypto/lms/HSSSignature.cs b/crypto/src/pqc/crypto/lms/HSSSignature.cs index 21f0397c8..bbf0c6f0f 100644 --- a/crypto/src/pqc/crypto/lms/HSSSignature.cs +++ b/crypto/src/pqc/crypto/lms/HSSSignature.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Text; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.IO; @@ -13,6 +14,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms private readonly LmsSignedPubKey[] m_signedPubKey; private readonly LmsSignature m_signature; + // TODO[api] signedPubKeys public HssSignature(int lMinus1, LmsSignedPubKey[] signedPubKey, LmsSignature signature) { m_lMinus1 = lMinus1; @@ -29,48 +31,48 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms public static HssSignature GetInstance(object src, int L) { if (src is HssSignature hssSignature) - { return hssSignature; - } - else if (src is BinaryReader binaryReader) - { - int lminus = BinaryReaders.ReadInt32BigEndian(binaryReader); - if (lminus != L - 1) - throw new Exception("nspk exceeded maxNspk"); - LmsSignedPubKey[] signedPubKeys = new LmsSignedPubKey[lminus]; - if (lminus != 0) - { - for (int t = 0; t < signedPubKeys.Length; t++) - { - signedPubKeys[t] = new LmsSignedPubKey(LmsSignature.GetInstance(src), - LmsPublicKeyParameters.GetInstance(src)); - } - } + if (src is BinaryReader binaryReader) + return Parse(L, binaryReader); - LmsSignature sig = LmsSignature.GetInstance(src); + if (src is Stream stream) + return Parse(L, stream, leaveOpen: true); - return new HssSignature(lminus, signedPubKeys, sig); - } - else if (src is byte[] bytes) + if (src is byte[] bytes) + return Parse(L, new MemoryStream(bytes, false), leaveOpen: false); + + throw new ArgumentException($"cannot parse {src}"); + } + + internal static HssSignature Parse(int L, BinaryReader binaryReader) + { + int lMinus1 = BinaryReaders.ReadInt32BigEndian(binaryReader); + if (lMinus1 != L - 1) + throw new Exception("nspk exceeded maxNspk"); + + var signedPubKeys = new LmsSignedPubKey[lMinus1]; + for (int t = 0; t < lMinus1; t++) { - BinaryReader input = null; - try // 1.5 / 1.6 compatibility - { - input = new BinaryReader(new MemoryStream(bytes)); - return GetInstance(input, L); - } - finally - { - if (input != null) input.Close(); - } + var signature = LmsSignature.Parse(binaryReader); + var publicKey = LmsPublicKeyParameters.Parse(binaryReader); + + signedPubKeys[t] = new LmsSignedPubKey(signature, publicKey); } - else if (src is MemoryStream memoryStream) + { - return GetInstance(Streams.ReadAll(memoryStream), L); + var signature = LmsSignature.Parse(binaryReader); + + return new HssSignature(lMinus1, signedPubKeys, signature); } + } - throw new ArgumentException($"cannot parse {src}"); + private static HssSignature Parse(int L, Stream stream, bool leaveOpen) + { + using (var binaryReader = new BinaryReader(stream, Encoding.UTF8, leaveOpen)) + { + return Parse(L, binaryReader); + } } public int GetLMinus1() diff --git a/crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs b/crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs index ef3d4aced..5be482e25 100644 --- a/crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs +++ b/crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs @@ -25,42 +25,33 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms public static LMOtsPublicKey GetInstance(object src) { - //todo if (src is LMOtsPublicKey lmOtsPublicKey) - { return lmOtsPublicKey; - } - else if (src is BinaryReader binaryReader) - { - int index = BinaryReaders.ReadInt32BigEndian(binaryReader); - LMOtsParameters parameter = LMOtsParameters.GetParametersByID(index); - - byte[] I = BinaryReaders.ReadBytesFully(binaryReader, 16); - - int q = BinaryReaders.ReadInt32BigEndian(binaryReader); - - byte[] K = BinaryReaders.ReadBytesFully(binaryReader, parameter.N); - - return new LMOtsPublicKey(parameter, I, q, K); - } - else if (src is byte[] bytes) - { - BinaryReader input = null; - try // 1.5 / 1.6 compatibility - { - input = new BinaryReader(new MemoryStream(bytes, false)); - return GetInstance(input); - } - finally - { - if (input != null) input.Close();//todo Platform Dispose - } - } - else if (src is MemoryStream memoryStream) - { - return GetInstance(Streams.ReadAll(memoryStream)); - } - throw new Exception ($"cannot parse {src}"); + + if (src is BinaryReader binaryReader) + return Parse(binaryReader); + + if (src is Stream stream) + return BinaryReaders.Parse(Parse, stream, leaveOpen: true); + + if (src is byte[] bytes) + return BinaryReaders.Parse(Parse, new MemoryStream(bytes, false), leaveOpen: false); + + throw new ArgumentException($"cannot parse {src}"); + } + + internal static LMOtsPublicKey Parse(BinaryReader binaryReader) + { + int index = BinaryReaders.ReadInt32BigEndian(binaryReader); + LMOtsParameters parameter = LMOtsParameters.GetParametersByID(index); + + byte[] I = BinaryReaders.ReadBytesFully(binaryReader, 16); + + int q = BinaryReaders.ReadInt32BigEndian(binaryReader); + + byte[] K = BinaryReaders.ReadBytesFully(binaryReader, parameter.N); + + return new LMOtsPublicKey(parameter, I, q, K); } public LMOtsParameters Parameters => m_parameters; diff --git a/crypto/src/pqc/crypto/lms/LMOtsSignature.cs b/crypto/src/pqc/crypto/lms/LMOtsSignature.cs index c55866661..afc309be6 100644 --- a/crypto/src/pqc/crypto/lms/LMOtsSignature.cs +++ b/crypto/src/pqc/crypto/lms/LMOtsSignature.cs @@ -23,38 +23,30 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms public static LMOtsSignature GetInstance(object src) { if (src is LMOtsSignature lmOtsSignature) - { return lmOtsSignature; - } - else if (src is BinaryReader binaryReader) - { - int index = BinaryReaders.ReadInt32BigEndian(binaryReader); - LMOtsParameters parameter = LMOtsParameters.GetParametersByID(index); - - byte[] C = BinaryReaders.ReadBytesFully(binaryReader, parameter.N); - - byte[] sig = BinaryReaders.ReadBytesFully(binaryReader, parameter.P * parameter.N); - - return new LMOtsSignature(parameter, C, sig); - } - else if (src is byte[] bytes) - { - BinaryReader input = null; - try // 1.5 / 1.4 compatibility - { - input = new BinaryReader(new MemoryStream(bytes, false)); - return GetInstance(input); - } - finally - { - if (input != null) input.Close(); - } - } - else if (src is MemoryStream memoryStream) - { - return GetInstance(Streams.ReadAll(memoryStream)); - } - throw new Exception ($"cannot parse {src}"); + + if (src is BinaryReader binaryReader) + return Parse(binaryReader); + + if (src is Stream stream) + return BinaryReaders.Parse(Parse, stream, leaveOpen: true); + + if (src is byte[] bytes) + return BinaryReaders.Parse(Parse, new MemoryStream(bytes, false), leaveOpen: false); + + throw new ArgumentException($"cannot parse {src}"); + } + + internal static LMOtsSignature Parse(BinaryReader binaryReader) + { + int index = BinaryReaders.ReadInt32BigEndian(binaryReader); + LMOtsParameters parameter = LMOtsParameters.GetParametersByID(index); + + byte[] C = BinaryReaders.ReadBytesFully(binaryReader, parameter.N); + + byte[] sig = BinaryReaders.ReadBytesFully(binaryReader, parameter.P * parameter.N); + + return new LMOtsSignature(parameter, C, sig); } public LMOtsParameters ParamType => m_paramType; diff --git a/crypto/src/pqc/crypto/lms/LMSPrivateKeyParameters.cs b/crypto/src/pqc/crypto/lms/LMSPrivateKeyParameters.cs index 278cbb04b..c5a188748 100644 --- a/crypto/src/pqc/crypto/lms/LMSPrivateKeyParameters.cs +++ b/crypto/src/pqc/crypto/lms/LMSPrivateKeyParameters.cs @@ -91,59 +91,46 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms public static LmsPrivateKeyParameters GetInstance(object src) { if (src is LmsPrivateKeyParameters lmsPrivateKeyParameters) - { return lmsPrivateKeyParameters; - } - else if (src is BinaryReader binaryReader) - { - int version = BinaryReaders.ReadInt32BigEndian(binaryReader); - if (version != 0) - throw new Exception("unknown version for LMS private key"); - int sigParamType = BinaryReaders.ReadInt32BigEndian(binaryReader); - LMSigParameters sigParameter = LMSigParameters.GetParametersByID(sigParamType); + if (src is BinaryReader binaryReader) + return Parse(binaryReader); - int otsParamType = BinaryReaders.ReadInt32BigEndian(binaryReader); - LMOtsParameters otsParameter = LMOtsParameters.GetParametersByID(otsParamType); + if (src is Stream stream) + return BinaryReaders.Parse(Parse, stream, leaveOpen: true); - byte[] I = BinaryReaders.ReadBytesFully(binaryReader, 16); + if (src is byte[] bytes) + return BinaryReaders.Parse(Parse, new MemoryStream(bytes, false), leaveOpen: false); - int q = BinaryReaders.ReadInt32BigEndian(binaryReader); + throw new ArgumentException($"cannot parse {src}"); + } - int maxQ = BinaryReaders.ReadInt32BigEndian(binaryReader); + internal static LmsPrivateKeyParameters Parse(BinaryReader binaryReader) + { + int version = BinaryReaders.ReadInt32BigEndian(binaryReader); + if (version != 0) + throw new Exception("unknown version for LMS private key"); - int l = BinaryReaders.ReadInt32BigEndian(binaryReader); - if (l < 0) - throw new Exception("secret length less than zero"); + int sigParamType = BinaryReaders.ReadInt32BigEndian(binaryReader); + LMSigParameters sigParameter = LMSigParameters.GetParametersByID(sigParamType); - byte[] masterSecret = BinaryReaders.ReadBytesFully(binaryReader, l); + int otsParamType = BinaryReaders.ReadInt32BigEndian(binaryReader); + LMOtsParameters otsParameter = LMOtsParameters.GetParametersByID(otsParamType); - return new LmsPrivateKeyParameters(sigParameter, otsParameter, q, I, maxQ, masterSecret); - } - else if (src is byte[] bytes) - { - BinaryReader input = null; - try // 1.5 / 1.6 compatibility - { - input = new BinaryReader(new MemoryStream(bytes, false)); - return GetInstance(input); - } - finally - { - if (input != null) - { - input.Close(); - } - } - } - else if (src is MemoryStream memoryStream) - { - return GetInstance(Streams.ReadAll(memoryStream)); - } + byte[] I = BinaryReaders.ReadBytesFully(binaryReader, 16); - throw new ArgumentException($"cannot parse {src}"); - } + int q = BinaryReaders.ReadInt32BigEndian(binaryReader); + + int maxQ = BinaryReaders.ReadInt32BigEndian(binaryReader); + + int l = BinaryReaders.ReadInt32BigEndian(binaryReader); + if (l < 0) + throw new Exception("secret length less than zero"); + byte[] masterSecret = BinaryReaders.ReadBytesFully(binaryReader, l); + + return new LmsPrivateKeyParameters(sigParameter, otsParameter, q, I, maxQ, masterSecret); + } internal LMOtsPrivateKey GetCurrentOtsKey() { diff --git a/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs b/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs index e8c5d07e5..37fa76e2d 100644 --- a/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs +++ b/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs @@ -26,44 +26,33 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms public static LmsPublicKeyParameters GetInstance(object src) { if (src is LmsPublicKeyParameters lmsPublicKeyParameters) - { return lmsPublicKeyParameters; - } - else if (src is BinaryReader binaryReader) - { - int pubType = BinaryReaders.ReadInt32BigEndian(binaryReader); - LMSigParameters lmsParameter = LMSigParameters.GetParametersByID(pubType); - int index = BinaryReaders.ReadInt32BigEndian(binaryReader); - LMOtsParameters ostTypeCode = LMOtsParameters.GetParametersByID(index); + if (src is BinaryReader binaryReader) + return Parse(binaryReader); - byte[] I = BinaryReaders.ReadBytesFully(binaryReader, 16); + if (src is Stream stream) + return BinaryReaders.Parse(Parse, stream, leaveOpen: true); - byte[] T1 = BinaryReaders.ReadBytesFully(binaryReader, lmsParameter.M); + if (src is byte[] bytes) + return BinaryReaders.Parse(Parse, new MemoryStream(bytes, false), leaveOpen: false); - return new LmsPublicKeyParameters(lmsParameter, ostTypeCode, T1, I); - } - else if (src is byte[] bytes) - { - BinaryReader input = null; - try // 1.5 / 1.6 compatibility - { - input = new BinaryReader(new MemoryStream(bytes, false)); - return GetInstance(input); - } - finally - { - if (input != null) - { - input.Close(); - } - } - } - else if (src is MemoryStream memoryStream) - { - return GetInstance(Streams.ReadAll(memoryStream)); - } - throw new Exception ($"cannot parse {src}"); + throw new ArgumentException($"cannot parse {src}"); + } + + internal static LmsPublicKeyParameters Parse(BinaryReader binaryReader) + { + int pubType = BinaryReaders.ReadInt32BigEndian(binaryReader); + LMSigParameters lmsParameter = LMSigParameters.GetParametersByID(pubType); + + int index = BinaryReaders.ReadInt32BigEndian(binaryReader); + LMOtsParameters ostTypeCode = LMOtsParameters.GetParametersByID(index); + + byte[] I = BinaryReaders.ReadBytesFully(binaryReader, 16); + + byte[] T1 = BinaryReaders.ReadBytesFully(binaryReader, lmsParameter.M); + + return new LmsPublicKeyParameters(lmsParameter, ostTypeCode, T1, I); } public override byte[] GetEncoded() diff --git a/crypto/src/pqc/crypto/lms/LMSSignature.cs b/crypto/src/pqc/crypto/lms/LMSSignature.cs index a1ae475c1..d25a498ea 100644 --- a/crypto/src/pqc/crypto/lms/LMSSignature.cs +++ b/crypto/src/pqc/crypto/lms/LMSSignature.cs @@ -25,45 +25,37 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms public static LmsSignature GetInstance(object src) { if (src is LmsSignature lmsSignature) - { return lmsSignature; - } - else if (src is BinaryReader binaryReader) - { - int q = BinaryReaders.ReadInt32BigEndian(binaryReader); - LMOtsSignature otsSignature = LMOtsSignature.GetInstance(src); + if (src is BinaryReader binaryReader) + return Parse(binaryReader); - int index = BinaryReaders.ReadInt32BigEndian(binaryReader); - LMSigParameters type = LMSigParameters.GetParametersByID(index); + if (src is Stream stream) + return BinaryReaders.Parse(Parse, stream, leaveOpen: true); - byte[][] path = new byte[type.H][]; - for (int h = 0; h < path.Length; h++) - { - path[h] = new byte[type.M]; - binaryReader.Read(path[h], 0, path[h].Length); - } + if (src is byte[] bytes) + return BinaryReaders.Parse(Parse, new MemoryStream(bytes, false), leaveOpen: false); - return new LmsSignature(q, otsSignature, type, path); - } - else if (src is byte[] bytes) - { - BinaryReader input = null; - try // 1.5 / 1.6 compatibility - { - input = new BinaryReader(new MemoryStream(bytes, false)); - return GetInstance(input); - } - finally - { - if (input != null) input.Close();// todo platform dispose - } - } - else if (src is MemoryStream memoryStream) + throw new ArgumentException($"cannot parse {src}"); + } + + internal static LmsSignature Parse(BinaryReader binaryReader) + { + int q = BinaryReaders.ReadInt32BigEndian(binaryReader); + + LMOtsSignature otsSignature = LMOtsSignature.Parse(binaryReader); + + int index = BinaryReaders.ReadInt32BigEndian(binaryReader); + LMSigParameters type = LMSigParameters.GetParametersByID(index); + + byte[][] path = new byte[type.H][]; + for (int h = 0; h < path.Length; h++) { - return GetInstance(Streams.ReadAll(memoryStream)); + path[h] = new byte[type.M]; + binaryReader.Read(path[h], 0, path[h].Length); } - throw new Exception ($"cannot parse {src}"); + + return new LmsSignature(q, otsSignature, type, path); } public override bool Equals(Object o) diff --git a/crypto/src/util/io/BinaryReaders.cs b/crypto/src/util/io/BinaryReaders.cs index c5f99a712..ed4b57d0a 100644 --- a/crypto/src/util/io/BinaryReaders.cs +++ b/crypto/src/util/io/BinaryReaders.cs @@ -1,10 +1,19 @@ using System; using System.IO; +using System.Text; namespace Org.BouncyCastle.Utilities.IO { public static class BinaryReaders { + internal static T Parse(Func parse, Stream stream, bool leaveOpen) + { + using (var binaryReader = new BinaryReader(stream, Encoding.UTF8, leaveOpen)) + { + return parse(binaryReader); + } + } + public static byte[] ReadBytesFully(BinaryReader binaryReader, int count) { byte[] bytes = binaryReader.ReadBytes(count); -- cgit 1.4.1