All files / sshwire.ts

100.00% Branches 9/9
100.00% Functions 8/8
100.00% Lines 50/50
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
x1
 
 
x8
x8
x8
 
x8
x56
x56
 
x8
x149
x1
x1
x148
x148
x148
x148
x148
x148
x148
x149
 
x8
x149
x1
x1
x148
x148
x148
x149
 
 
x8
x135
x135
 
x8
x18
x18
x8
 
 
x8
x160
x160
x160
x160
x160
 
 
x8
x50
x50
x50
x50
x191
x191
x191
x50
x50




























































// Minimal SSH wire-format primitives (RFC 4251 ยง5): length-prefixed strings.

/** Sequential reader over an SSH wire buffer. */
export class Reader {
  #buf: Uint8Array;
  #off = 0;

  constructor(buf: Uint8Array) {
    this.#buf = buf;
  }

  readUint32(): number {
    if (this.#off + 4 > this.#buf.length) {
      throw new Error("ssh wire: truncated uint32");
    }
    const v = new DataView(
      this.#buf.buffer,
      this.#buf.byteOffset + this.#off,
      4,
    ).getUint32(0);
    this.#off += 4;
    return v;
  }

  readBytes(n: number): Uint8Array {
    if (this.#off + n > this.#buf.length) {
      throw new Error("ssh wire: truncated bytes");
    }
    const b = this.#buf.subarray(this.#off, this.#off + n);
    this.#off += n;
    return b;
  }

  /** Read a length-prefixed string's bytes. */
  readString(): Uint8Array {
    return this.readBytes(this.readUint32());
  }

  get done(): boolean {
    return this.#off === this.#buf.length;
  }
}

/** Encode bytes as a length-prefixed SSH wire string. */
export function writeString(bytes: Uint8Array): Uint8Array {
  const out = new Uint8Array(4 + bytes.length);
  new DataView(out.buffer).setUint32(0, bytes.length);
  out.set(bytes, 4);
  return out;
}

/** Concatenate byte arrays. */
export function concat(...arrays: Uint8Array[]): Uint8Array {
  const total = arrays.reduce((n, a) => n + a.length, 0);
  const out = new Uint8Array(total);
  let off = 0;
  for (const a of arrays) {
    out.set(a, off);
    off += a.length;
  }
  return out;
}