<PackageReference Include="BouncyCastle.Cryptography" Version="2.3.0" />

SshBuffer

class SshBuffer
using Org.BouncyCastle.Math; using Org.BouncyCastle.Utilities; using System; using System.Text; namespace Org.BouncyCastle.Crypto.Utilities { internal class SshBuffer { private readonly byte[] buffer; private int pos; internal SshBuffer(byte[] magic, byte[] buffer) { this.buffer = buffer; for (int i = 0; i != magic.Length; i++) { if (magic[i] != buffer[i]) throw new ArgumentException("magic-number incorrect"); } pos += magic.Length; } internal SshBuffer(byte[] buffer) { this.buffer = buffer; } public int ReadU32() { if (pos > buffer.Length - 4) throw new ArgumentOutOfRangeException("4 bytes for U32 exceeds buffer."); uint result = Pack.BE_To_UInt32(buffer, pos); pos += 4; return (int)result; } public string ReadStringAscii() { return Encoding.ASCII.GetString(ReadBlock()); } public string ReadStringUtf8() { return Encoding.UTF8.GetString(ReadBlock()); } public byte[] ReadBlock() { int num = ReadU32(); if (num == 0) return Arrays.EmptyBytes; if (pos > buffer.Length - num) throw new InvalidOperationException("not enough data for block"); int from = pos; pos += num; return Arrays.CopyOfRange(buffer, from, pos); } public void SkipBlock() { int num = ReadU32(); if (pos > buffer.Length - num) throw new InvalidOperationException("not enough data for block"); pos += num; } public byte[] ReadPaddedBlock() { return ReadPaddedBlock(8); } public byte[] ReadPaddedBlock(int blockSize) { int num = ReadU32(); if (num == 0) return Arrays.EmptyBytes; if (pos > buffer.Length - num) throw new InvalidOperationException("not enough data for block"); if (num % blockSize != 0) throw new InvalidOperationException("missing padding"); int from = pos; pos += num; int num2 = pos; if (num > 0) { int num3 = buffer[pos - 1] & 255; if (0 < num3 && num3 < blockSize) { int num4 = num3; num2 -= num4; int num5 = 1; int num6 = num2; while (num5 <= num4) { if (num5 != (buffer[num6] & 255)) throw new InvalidOperationException("incorrect padding"); num5++; num6++; } } } return Arrays.CopyOfRange(buffer, from, num2); } public BigInteger ReadMpint() { int num = ReadU32(); if (pos > buffer.Length - num) throw new InvalidOperationException("not enough data for big num"); switch (num) { case 0: return BigInteger.Zero; case 1: if (buffer[pos] == 0) throw new InvalidOperationException("Zero MUST be stored with length 0"); break; } if (num > 1 && buffer[pos] == (byte)(-(buffer[pos + 1] >> 7))) throw new InvalidOperationException("Unnecessary leading bytes MUST NOT be included"); int offset = pos; pos += num; return new BigInteger(buffer, offset, num); } public BigInteger ReadMpintPositive() { BigInteger bigInteger = ReadMpint(); if (bigInteger.SignValue < 0) throw new InvalidOperationException("Expected a positive mpint"); return bigInteger; } public bool HasRemaining() { return pos < buffer.Length; } } }