Skip to content

Security Model

This page states what SSHClient protects against, what evidence backs that, and what it does not yet do. It reflects the 2026-08 security review, whose findings were either fixed (with regression tests) or are listed below as limitations.

Protections

Confidentiality & integrity of the session. After key exchange, all traffic is AES-128-CTR encrypted and HMAC-SHA-256 authenticated, with per-direction keys derived per RFC 4253 from a Diffie–Hellman group14 (2048-bit MODP) shared secret and SHA-256. Packets failing MAC verification abort the session.

Server authentication. The server's rsa-sha2-256 signature over the exchange hash is verified with PKCS#1 v1.5, and the host key is checked against known_hosts (policy details). A live man-in-the-middle — a second, fully functional server presenting a different key — is refused before authentication; this exact scenario is an automated test (Test_HostKey_MITM).

Credentials. The password (or the public-key signature) is only ever sent inside the encrypted, server-authenticated transport, after the host key has passed both checks.

Malformed input. The packet length word from the wire is capped at 256 KB before any allocation (a corrupt or malicious peer gets a clean error, not a memory blow-up), and MAC comparison examines every byte with no data-dependent early exit.

Randomness. The key-exchange cookie and the 256-bit DH private exponent are drawn under ⎕RL←⍬ 2 — Dyalog's operating-system RNG (/dev/urandom / CryptGenRandom), which is cryptographically appropriate. Packet padding uses the workspace RNG; padding is encrypted and is not key material.

Verification evidence

The test suite (50 tests, run in CI on every push) validates:

  • SHA-256 against NIST FIPS 180-2 vectors; HMAC-SHA-256 against RFC 4231; AES-128-CTR against NIST SP 800-38A, including counter continuity
  • modular exponentiation against known values plus a DH commutativity proof over the real group14 prime
  • RSA sign/verify cross-checked against OpenSSL in both directions, with bit-flipped / truncated / garbage / wrong-message signatures all refused
  • the full stack against real OpenSSH: password and key auth, exec, SFTP binary round-trips independently confirmed by remote sha256sum, TOFU pinning, strict mode, and the live-impostor MITM refusal

See Testing & CI.

Current limitations

Area Status
Rekeying not implemented; very long sessions do not renegotiate keys
Password in memory Password is a plain public field for the object's lifetime and appears in Config output
Algorithm agility small preference lists negotiated per RFC 4253 — see Algorithms & Limitations; a server offering none of a slot's list still fails (cleanly)

Reporting

If you find a security problem, please include the Debug output (bit 4 = packet trace) from a test server only — traces of real sessions contain sensitive material.