| title | Interoperability |
|---|---|
| description | Tested compatibility and cross-implementation protocol evidence. |
The end-to-end interoperability suite uses OpenSSH rather than another JavaScript SSH library. It establishes real TCP connections in both directions:
- The system
/usr/bin/sshclient connects to amodernsshserver, verifies transport and user authentication behavior, opens a session, transfers stdin/stdout/stderr, receives an exit status, completes EOF/CLOSE handling, and separately establishes anssh -Rlistener whose data crosses a server-initiatedforwarded-tcpipchannel. It also exchanges data through bothssh -Ldirect andssh -Rremote UNIX-socket forwarding against themodernsshserver. It also forwards a real OpenSSH agent, which the server queries over a server-initiated agent channel and validates against the fixture key. Its X11 test replaces the SSH fake cookie with a realXauthoritycookie before delivering the setup packet to a local test display. - A
modernsshclient connects to an OpenSSH server built from the digest-pinned Debian fixture in__tests__/openssh/Dockerfile, authenticates with a password, executes a command, separates stdout/stderr, receives its exit status, establishes and cancels a remote TCP listener, exchanges data over the resultingforwarded-tcpipchannel, opens direct and remote OpenSSH stream-local forwarding channels, disables additional sessions withno-more-sessions@openssh.com, verifies OpenSSH's enforcement, exchanges SSH-level keepalives, explicitly rekeys the transport, and uses high-level environment and PTY session options, and handles the resulting disconnect without leaving a channel pending. It also opens a second authenticated SSH connection through an OpenSSHdirect-tcpipchannel to validate supplied-duplex connection hopping. The OpenSSH client initiates key re-exchange against the modern server under a deliberately low byte limit. The same test uses the public agent-forwarding API without an RFC 9987 advertisement, then runsssh-add -Lon OpenSSH to prove both safe compatibility-name fallback and that the remote process sees the modern client's local OpenSSH agent. It also requests X11 forwarding, connects to the display allocated by sshd, and exchanges data through the resultingx11channel. A Node subprocess also uses the packagedHTTPAgentwithhttp.get()to reach an HTTP endpoint through a forceddirect-tcpipchannel on the OpenSSH server.
The package suite separately builds the publishable archive, installs it into an empty consumer directory, and imports only the package root in a native Node.js process. That process starts a packaged server and client over TCP, completes key exchange and authentication, executes a command, checks stdout, stderr, and exit status, and closes both sides. This verifies that the generated ESM, declarations, dependency list, package exports, and actual Node transport runtime work together rather than relying on source imports or Bun's runtime compatibility.
The HTTP-agent integration also launches a native Node.js consumer of the built ESM entry point.
It uses SSHHTTPSAgent through Node's real https.get() agent contract, negotiates TLS with a
self-signed endpoint above an encrypted direct-tcpip channel, verifies the HTTPS response, and
asserts the exact forwarding destination and originator metadata observed by the SSH server.
The OpenSSH server test requires Docker. The image is tagged locally as
modernssh-openssh-test:bookworm; Docker reuses its build cache after the first run. The pinned base
image makes the operating-system fixture reproducible, while installing the distribution's
openssh-server package exercises the normal packaged daemon configuration.
RFC 4462 GSS-API authentication is covered by literal packet bytes for mechanism negotiation, every context-exchange message, canonical DER OID rejection, and the exact session-bound MIC input. An independent HMAC-backed test mechanism drives both library roles through multi-round context establishment, adjacent final-token/MIC delivery, integrity and no-integrity completion, mechanism status and error tokens, client abandonment followed by a fresh authentication request, context cleanup, and rejection of an invalid MIC before application policy. This validates the SSH state machine without claiming interoperability for any particular external GSS-API provider.
Wire codecs are tested independently of OpenSSH with fixed byte strings derived from the protocol
formats. The channel vector suites cover direct-tcpip, forwarded-tcpip, TCP forwarding global
requests, all four OpenSSH stream-local forwarding messages, allocated-port responses, PTY and
terminal modes, environment, window changes, signals, RFC 4254 xon-xoff, RFC 4335 BREAK,
subsystems, both RFC 9987 agent-forwarding request and channel-open name forms, X11 requests and
channel opens, session exit status and signal metadata,
no-more-sessions@openssh.com, window adjustment,
keepalive@openssh.com, standard data, stderr extended data, EOF, and CLOSE. Every vector is parsed
into asserted fields and serialized back to the exact original bytes.
The encrypted dual-role suite also applies no-more-sessions@openssh.com, attempts a forbidden
second session, and verifies the specified immediate disconnect rather than an ordinary channel
failure. Existing channel requests on both peers are required to reject during teardown.
Encrypted integration tests allocate channel number 0xffffffff in each peer role, wrap the next
allocation to zero, and prove that an identifier which remains active is skipped. Separate negative
tests reject peer reuse while an open is pending, duplicate remote identifiers, contradictory open
outcomes, and window overflow. Held server policy and client agent-provider decisions prove that
pending-open capacity rejects excess requests with resource shortage before invoking more
application work. Another held server policy proves that an independent later open can complete
first. Separate client/server cases fill the total simultaneous-channel allowance, reject excess
local and peer opens without disconnecting, and recover capacity after CLOSE.
Action-scheduler tests hold an awaited global-request hook, fill a deliberately small waiting allowance with one-way traffic, and prove that the next request reports capacity failure and closes the encrypted connection. Focused lifecycle tests verify independent keys still run, queued work rejects on close, and no overflowed action executes. A reconnect test releases an old async client decision only after the same instance authenticates again, proving the old generation cannot write into or close the new transport.
Generic global-request integration sends concurrent requests through an awaited server hook and
proves their opaque replies remain ordered, covers deny-by-default and one-way notification paths,
and exercises ordered server-initiated requests through the client's awaited hook using the public
ServerClient API, including a request queued across rekey and one rejected on close. Real OpenSSH
peers reject private unknown requests initiated in either direction, proving standards-compatible
failure handling for both public APIs.
Agent-forwarding integration also connects the library's client and server directly, verifies the
literal agent-forward version 0 advertisement, and proves that forwardAgent() selects
agent-req followed by agent-connect. Replacement-extension coverage proves that omitting the
advertisement clears the capability instead of retaining stale negotiation state.
Fixed public agent-protocol exchanges also prove that a contained later policy failure cannot
release an earlier identity list or cryptographic signature.
Management exchanges independently apply that failure ordering to identity and token additions,
individual and bulk identity removal, and token removal.
Stateful agent tests additionally prove that later failures cannot transition lock state, expose an
extension result or advertised list, or retain a proposed session binding.
RFC 8308 no-flow-control coverage checks the literal p and s values and every bilateral
preference outcome. In-process peers transfer data in both directions after their advertised
windows are exhausted, ignore otherwise overflowing window adjustments, refuse a second live
channel, permit another after complete close, and disable the capability when a replacement server
extension set omits it. Packet-size checks remain active while channel-window accounting is
disabled.
RFC 8308 elevation coverage fixes the complete extension packets for the registered y, n, and
d values and the exact post-authentication one-way global request. In-process peers prove that
authentication waits for asynchronous server policy, both boolean outcomes reach the client, and
an omitted advertisement uses server-default policy without sending an unsolicited result.
Malformed result framing is rejected through the encrypted connection. A real encrypted session
also proves that a later contained policy failure suppresses an earlier elevation result without
undoing otherwise successful authentication.
Session interoperability sends a BREAK from the modern client to a real OpenSSH PTY and delivers
an xon-xoff notification from the modern server to the system OpenSSH client. In-process peers
also prove that BREAK policy hooks are awaited, success and failure replies match the completed
operation, requested durations are preserved, and client notifications carry the exact boolean.
In-process forwarding tests additionally open server-initiated TCP and UNIX channels through the public connection APIs only after matching requests have been accepted. They assert every source and destination field, exchange data in both directions through the bounded channel streams, and reject attempts after cancellation.
Transport tests likewise use deterministic identification, binary framing, encryption-boundary,
MAC, AEAD, fragmentation, and maximum-size vectors. AES-GCM is checked against a published NIST
primitive vector. ChaCha20 and Poly1305 are checked against RFC 8439 vectors. Both AEAD packet
layouts have fixed SSH packets independent of the TypeScript codec, including the published
chacha20-poly1305 worked example. This keeps exact packet parsing failures local and diagnosable
instead of relying on an external implementation to reject malformed bytes.
RFC 5647 coverage also fixes the registered AEAD_AES_128_GCM packet ciphertext and tag for an
independently generated key, IV, payload, padding, and authenticated length. Negotiation tests
require ordinary SSH preference rules to select the same registered name in the cipher and MAC
lists for each direction and reject either kind of mismatched selection. In-process client and
server peers force both registered key sizes through authenticated traffic and rekey while checking
that handshake metadata reports the RFC MAC name.
RFC 8731 Curve448 coverage uses RFC 7748's literal Alice and Bob private keys, public values, and
shared secret. It also verifies the required reduction of a non-canonical field coordinate, exact
56-byte SSH-string framing, rejection of wrong-length and low-order peers, and defensive ownership
of ephemeral state. A forced in-process client/server connection exchanges authenticated traffic
before and after rekey with curve448-sha512, proving both SSH roles preserve the first session ID
while deriving a new exchange hash and transport keys.
RFC 9941 coverage reproduces the published SHA-512 combination of the sntrup761 KEM and X25519 secrets, including the exact 64-byte SSH-string encoding. KEM tests cover fixed object sizes, encapsulation, decapsulation, implicit rejection of a changed ciphertext, and defensive ownership of hybrid public values. In-process peers force both the standardized method and its deployed alias through protected traffic and rekey. The system OpenSSH client then forces the alias against the library server and initiates a low-limit rekey; a separate library client executes commands before and after an explicit rekey against the pinned OpenSSH server.
The registered ML-KEM hybrid coverage checks ML-KEM-768 and ML-KEM-1024 key generation against
fixed SHA-256 digests of NIST ACVP FIPS 203 test cases 26 and 51. Independent fixed inputs cover the
specified SHA-256 and SHA-384 K_PQ || K_CL combiners. Tests exercise exact client/server message
sizes, compressed and uncompressed NIST points, invalid ML-KEM and classical values, ciphertext
implicit rejection, and defensive buffer ownership. In-process peers force all three registered
method names through authenticated traffic and rekeys initiated by both roles. A digest-pinned
OpenSSH 10 fixture additionally forces mlkem768x25519-sha256 in both peer roles. Its client
exchanges channel traffic with the library server across a byte-limit rekey; the library client
executes commands before and after an explicit rekey against its server while preserving the first
session ID and changing the exchange hash.
Standalone ML-KEM coverage fixes all three FIPS 203 encapsulation-key parameter sets to NIST ACVP vectors and checks the SHA-256 digest of each published encapsulation key. It verifies exact 800/1184/1568 byte client keys, exact 768/1088/1568 byte server ciphertexts, non-canonical key rejection, same-length ciphertext implicit rejection, and the specification's distinct raw-string exchange-hash encoding. In-process client/server tests force each IANA name through authenticated traffic and rekeys initiated by both roles; SHA-256 and SHA-384 exchange-hash lengths are checked separately.
RFC 4250 name tests cover the 64-character boundary, extension-domain form, non-ASCII and control input, commas, empty entries, and duplicate name-list members. Packet tests separately prove that the validation is applied to services, extensions, channels, and requests rather than existing only as an unused utility.
Disconnect integration covers both peer directions over encrypted connections. It verifies the
typed event precedes close, preserves immutable RFC metadata, rejects a pending request with the
typed error, and interrupts connection setup immediately rather than waiting for the readiness
deadline. Graceful shutdown tests independently verify that both public connection roles report
transport EOF through end before terminal close cleanup. Real half-open injected TCP transports
also verify that EOF terminates both peer roles immediately rather than leaving setup pending until
a readiness or handshake deadline.
Server admission integration verifies that the public connection event receives an immutable
snapshot of both TCP endpoints and retains it after the peer closes. A separate real SSH handshake
proves that a rejected async preconnect chain fails closed even when an earlier handler allowed
the connection, while a silent admission hook is bounded by the handshake deadline and releases its
transport slot without publishing a connection. Encrypted client/server tests apply the same
multi-handler failure to host-key trust and user authentication, proving that a contained later
rejection cannot retain an earlier allow decision. The same real transport seam verifies channel
admission, TCP and stream-local listener creation, and application global requests in both peer
directions.
Private channel requests are exercised in both directions. Session tests separately prove that a
later policy failure cannot retain earlier approval for shell, exec, subsystem, PTY, environment,
BREAK, agent-forwarding, or X11 requests and cannot publish the corresponding accepted state or
event.
Server shell integration verifies RFC 4254 directional half-close semantics: ending stdout sends
EOF without CLOSE, the client sends additional stdin afterward, and explicit close then completes
the channel lifecycle.
An encrypted session also verifies the complete exit-signal result, including core-dump flag,
UTF-8 diagnostic text, and RFC 3066 language tag. The server API prevents a second exit result from
placing a peer-invalid duplicate on the same channel.
An independently written unknown message is also sent in both directions over an encrypted
in-process connection; each peer returns the exact rejected sequence in SSH_MSG_UNIMPLEMENTED and
continues with later traffic. The system OpenSSH client independently returns the same response to
an unknown server message.
RFC 4419 group-exchange request, group, init, and reply messages use independently written fixed frames, including the context-specific opcode 31. Primitive tests select RFC 8270-sized safe groups, prove both sides derive the same secret, and reject invalid ranges, composite groups, non-canonical mpints, and out-of-range public values.
Compression tests use independently generated RFC 1950 streams with the RFC 4253 partial flush at
each packet boundary. They prove dictionary continuity across packets, exact payload-only framing,
malformed-stream rejection, and bounded expansion. In-process peers exercise both immediate zlib
and delayed zlib@openssh.com through multi-packet bidirectional transfers and rekeying.
RFC 8308 delay-compression tests use the specification's literal two-name-list value, a complete
fixed extension packet, and the one-byte opcode-8 NEWCOMPRESS trigger. In-process peers begin with
none, activate each zlib direction at its distinct authentication trigger, exchange compressed
traffic, and prove that a subsequent rekey overrides the extension. Coverage also includes
bilateral gating, a server offer delayed until authentication policy, non-mutual negotiation,
locally blocked premature rekeys, the bounded trigger deadline, and wrong-direction or duplicate
triggers.
Transport ping coverage uses fixed opcode 192/193 packet vectors and exercises concurrent ordered
echoes plus a ping queued across rekey against the in-process server. The pinned OpenSSH fixture
used for legacy coverage predates ping@openssh.com; the client verifies that absence of its RFC
8308 advertisement rejects the API call before any extension packet is sent. The separate pinned
OpenSSH 10 server advertises version 0 and echoes an opaque ping whose caller-owned input is
mutated while the reply is pending.
The agent suite sends fixed RFC 9987 identity-list and signing frames through fragmented UNIX-socket
reads. It also sends the independently assembled revision-01 Ed25519 private-certificate fields in
both client and server roles, verifies the resulting private signature against the embedded
certificate, and rejects a mismatched certificate envelope before application policy. A separate
integration test starts the system OpenSSH ssh-agent, loads an independently generated Ed25519
key with ssh-add, lists it through modernssh, and verifies a delegated signature
cryptographically. That real agent also accepts a generated certificate-backed identity directly
from the library, lists its certificate, and signs through its matching private key.
Security-key coverage uses fixed Ed25519, P-256, and WebAuthn wire values derived independently from
the published FIDO/U2F format. Negative cases change the signed counter, WebAuthn challenge,
authenticator-data flag, origin, and extension-present state. The system ssh-keygen issues both
security-key certificate types; the library parses their exact vendor algorithm names and verifies
the certificate authority signature. An in-process non-interactive agent completes host-bound
public-key authentication with a security-key signature through the awaited server policy hook.
Fixed private containers cover both published key-handle layouts, including encrypted storage and
ownership checks. A literal sk-provider@openssh.com constrained-add frame is exercised in both
agent roles, and the system OpenSSH agent independently accepts, lists, and removes the synthetic
provider-backed identity without requiring the physical authenticator.
Legacy Cygwin transport coverage uses the socket descriptor and security exchange published by Cygwin's maintainers. A loopback TCP fixture verifies the exact per-uint32 byte order of the 16-byte socket secret, fragmented secret echoes, the zero-credential discovery connection, the second connection's process ID and discovered UID/GID, and subsequent RFC 9987 listing and signing. Negative cases cover non-ASCII, malformed, and oversized descriptors, a mismatched secret, an idle deadline, and destruction of the silent peer. This is deterministic protocol coverage and does not claim execution inside a Cygwin installation.
Private-key interoperability tests generate passphrase-protected Ed25519 keys with ssh-keygen
using every cipher accepted by OpenSSH 9.6 (3DES-CBC, AES-CBC, AES-CTR, AES-GCM, and OpenSSH
ChaCha20-Poly1305), then decrypt, sign, and verify each key. They also cover encrypted RSA keys,
missing and incorrect passphrases, authenticated-data tampering, and DiskAgent passphrase
resolution. No JavaScript SSH implementation supplies expected key data.
The inverse path serializes a generated key with every supported cipher and asks ssh-keygen -y
to decrypt and derive its public key. Those outputs must match the generated public key exactly.
Repeated encryption proves fresh salt generation, while incorrect passphrases, modified output,
empty secrets, and invalid bcrypt round counts are rejected.
Multi-key private-container tests combine Ed25519, ECDSA, and Ed448 entries in independently parsed raw and armored envelopes, with and without authenticated encryption. They verify order, comments, signing, public/private matching, singular-API rejection, strict cipher and KDF names, canonical armor, whole-input and count bounds, and padding.
PEM import interoperability uses OpenSSL to create Ed25519 and RSA PKCS#8, traditional PKCS#1 RSA,
SEC1 ECDSA, and encrypted ECDSA PKCS#8 inputs. Each imported key signs data and is converted to an
OpenSSH private-key container whose derived public key is checked by ssh-keygen. An unsupported
X25519 PKCS#8 key is rejected explicitly.
Public PEM interoperability covers generic SubjectPublicKeyInfo for Ed25519, RSA, and every RFC
5656 ECDSA curve, plus traditional PKCS#1 RSA public keys. Each converted key verifies a signature
from its independently imported private half, and ssh-keygen accepts and fingerprints the
canonical SSH public-key output. Unsupported X25519 public keys are rejected explicitly.
RFC 4716 public-key import, serialization, unknown-header preservation, and legacy MD5 fingerprint
display are checked against the document's literal RSA example and strict malformed framing,
continuation, line-length, UTF-8, and base64 cases. Generated Ed25519 files are exchanged in both
directions with ssh-keygen, including package-archive exports.
Detached signature coverage parses an independently assembled fixed SSHSIG blob, enforces
namespace binding, owns data across awaited agent signing, and rejects malformed armor and future
versions. Ed25519 and RSA signatures are exchanged in both directions with ssh-keygen -Y; the
command-line verifier accepts library output through an allowed-signers file, and the library
cryptographically verifies command-line output. RSA coverage proves SHA-2 signatures are used
instead of RSA-SHA1.
Allowed-signers coverage combines wildcard and negated principals, quoted namespace patterns,
inclusive policy validity, exact keys, certificate authorities, certificate principals and
validity, and KRL revocation. The system tool creates a certificate-backed detached signature and
accepts the same CA policy file that the library loads; both verifiers accept the authorized
principal, while the library rejects another principal and the revoked certificate.
Principal discovery and principal-pattern matching are compared against the corresponding system
operations, including byte-oriented ? matching for a multibyte UTF-8 identity.
Known-host wildcard evidence compares the same multibyte hostname against ssh-keygen -F, proving
that ? consumes an encoded byte and that only the two-byte pattern matches.
PPK import uses the RFC 8032 Ed25519 seed, public key, and empty-message signature as a fixed
private-key vector in both version 2 and version 3 envelopes. The system puttygen independently
accepts those fixtures, and generated version 3 fixtures cover RSA, DSA, Ed25519, Ed448, and every
supported ECDSA curve. Encrypted tests cover version 2 plus Argon2d, Argon2i, and Argon2id version 3
files, including incorrect passphrases, integrity failures, malformed framing, and resource bounds.
Every generated key signs through the library and is matched to puttygen's public output; key
families understood by the system OpenSSH build are also reserialized and checked with
ssh-keygen -y.
Ed448 coverage uses RFC 8032's empty-message key and signature vector, wrapped in the exact RFC 8709 SSH public-key and signature encodings. A native Node subprocess independently generates an Ed448 PKCS#8 and SubjectPublicKeyInfo pair, imports both, and verifies a signature; generated library keys also round-trip through the private-key container.
Legacy DSS coverage makes the signer reproduce the RFC 6979 DSA-1024/SHA-1 vector with RFC 4253's
literal four-mpint key blob and fixed 40-byte signature. OpenSSH-generated private, public, and PEM
containers are parsed, signed, serialized, and derived again with ssh-keygen. With the method
explicitly enabled, OpenSSH verifies the library server's DSS host signature; the library also
verifies OpenSSH's DSS host signature while OpenSSH verifies a library DSS user-authentication
signature. Default offers are separately checked to exclude DSS and the other legacy-only algorithm
families.
OpenSSH private-key tests also generate every required ECDSA curve and prove parsing, public-key matching, signing, and verification. The signer reproduces RFC 6979's P-256/SHA-256, P-384/SHA-384, and P-521/SHA-512 signatures, independently encoded as RFC 5656 pairs of SSH mpints.
Generated-key interoperability creates Ed25519, 2048-bit RSA, and every required ECDSA curve through
the public generateKeyPair() API. OpenSSH ssh-keygen derives and fingerprints each generated
private key, while independent signing checks prove that each returned public key matches. A
separate default-generation test verifies the documented 3072-bit RSA modulus.
Direct client private-key authentication loads the same RSA identity authorized by the OpenSSH
fixture, connects without a password or external agent, and executes a command. In-process coverage
also loads an encrypted key through privateKey and passphrase, exercises host-bound
authentication, and verifies that encoded secrets are not retained in client options.
Authentication interoperability covers RFC 4252 banners and password changes plus RFC 4256
keyboard-interactive exchanges. OpenSSH's client completes a two-prompt keyboard-interactive round
and a forced password change against the modern server. The modern client authenticates through
PAM-backed OpenSSH keyboard-interactive and records OpenSSH's banner. Fixed, independently written
wire vectors cover every new message layout, including the context-dependent reuse of opcode 60.
An in-process integration test proves that a partial password success can change the advertised
method set and cause an earlier failed keyboard-interactive method to be retried as the second
factor. It also verifies the RFC authentication-limit disconnect packet, proves that none and
partial success do not consume the failure ceiling, and holds an async policy hook past the server
deadline to ensure its late approval cannot authenticate the connection.
Separate encrypted client/server cases prove that contained later failures stop authentication
method selection and discard earlier password, password-change, and keyboard-interactive values
before those values cross the wire.
Host-based authentication is exercised in both peer roles with real OpenSSH machine keys. OpenSSH signs a request with the isolated container's Ed25519 host key and the modern server authorizes its claimed hostname, local user, target user, public key, and observed address through an awaited hook. The modern client then uses an OpenSSH host private key to authenticate to the containerized server, explicitly rekeys, and executes a command. A fixed RFC 4252 request and signature preimage cover the wire format, while an invalid signature is rejected before application policy runs.
RSA SHA-2 interoperability covers RFC 8332 host and user signatures in both peer roles. The system
OpenSSH client forces rsa-sha2-512, authenticates with an RSA key, and initiates rekeying against
the modern server. The modern client uses a real OpenSSH RSA agent and an explicitly forced RSA
SHA-512 host key against the containerized server; an invalid password prevents fallback. Fixed
vectors independently cover the RFC 8308 server-sig-algs message and the distinct RSA signature
algorithm and ssh-rsa key-format fields.
Host-key rotation interoperability verifies the server's hostkeys-00@openssh.com announcement by
requesting hostkeys-prove-00@openssh.com, checking each signature against the session-bound proof
message, and matching the resulting RSA key to the real containerized server key. Independent fixed
bytes cover that proof preimage. Separate encrypted role tests negotiate hostkeys=0, select the
standard hostkeys-prove request, verify the distinct hostkeys-prove-0 signed domain, accept a
standard hostkeys advertisement, bind RSA proofs to the initially negotiated RSA-SHA2 algorithm,
and reject RSA-SHA1, duplicates, empty requests, modified, truncated, and extra signatures.
Known-hosts interoperability hashes a real database with ssh-keygen -H and verifies that the
library finds its hidden hostname. In the other direction, ssh-keygen -F finds an independently
salted hashed entry written by the library. Certificate-authority coverage generates and signs a
host certificate with ssh-keygen, then exercises hostname principals, validity, authority trust,
and authority revocation through the public KnownHosts API.
Key-revocation-list interoperability generates explicit-key, authority-scoped certificate serial,
serial-range, serial-bitmap, and key-identifier records with ssh-keygen. The public
KeyRevocationList API checks revoked and non-revoked keys and certificates, including embedded
plain keys and revoked signing authorities. A fixed SHA-256 section and malformed serial-zero case
provide independent byte-level and failure evidence.
Public-key authentication also exercises the version-0 host-bound extension in both roles. Fixed wire bytes prove that the exact negotiated server host key is part of the signature preimage; live tests prove the unsigned key probe followed by a bound signed request and reject a mismatched host key before application authorization.
ECDSA host-key interoperability forces each RFC-required NIST curve in both peer roles. OpenSSH initiates low-limit rekeys against the modern server for P-256, P-384, and P-521; separate modern clients force each corresponding OpenSSH host key, explicitly rekey, authenticate, and execute a command.
Diffie-Hellman group-exchange interoperability forces both RFC 4419 SHA-256 and SHA-1 method names in both peer roles. OpenSSH initiates low-limit rekeys against the modern server; separate modern clients validate OpenSSH-selected safe groups, explicitly rekey, authenticate, and execute a command. SHA-1 coverage exists for legacy compatibility, while SHA-256 precedes fixed MODP methods in the default preference.
Fixed-group Diffie-Hellman evidence includes the legacy RFC 4253 group1/SHA-1 and group14/SHA-1 methods as well as the RFC 8268 SHA-2 methods. The legacy primitive tests use the published Oakley Group 2 prime and a fixed private scalar to prove the public value, shared secret, exchange hash, and rejection boundaries independently of a named-group lookup. In-process peers exchange protected requests across rekey for every method. The system OpenSSH client explicitly enables both legacy names, transfers enough data to initiate a low-limit rekey, and completes a command; the library client then forces those names and the three OpenSSH-supported RFC 8268 groups against the pinned server, executes commands before and after an explicit rekey, preserves its first session ID, and derives a different exchange hash. These opt-in tests are compatibility evidence rather than a deployment recommendation.
AEAD integration forces both the standardized and deployed ChaCha20-Poly1305 names through traffic and rekey. Independent-peer interoperability exercises the deployed name and both 128- and 256-bit AES-GCM variants in both peer roles. OpenSSH streams enough data to initiate low-limit rekeys against the modern server; separate modern clients force each supported cipher against the containerized server, explicitly rekey, and execute a command. Negotiated handshake details prove that both directions use implicit integrity rather than a separate MAC.
CBC interoperability forces AES-128, AES-192, AES-256, and three-key 3DES in both peer roles. OpenSSH initiates low-limit rekeys against the modern server; separate modern clients explicitly rekey and execute a command against the containerized server. Negotiated handshake details prove that every CBC direction uses a separate MAC. NIST SP 800-38A AES vectors and an independently generated OpenSSL 3DES vector verify the block primitives, while fragmented fixed packets verify that cipher chaining continues when the decoder receives the first block separately.
The optional RFC 4253 blowfish-cbc and cast128-cbc methods have separate in-process evidence
because current OpenSSH builds no longer offer them. The original published 128-bit-key Blowfish
CBC vector verifies four chained blocks exactly. RFC 2144's CAST-128 vector and an independent
two-block OpenSSL CBC value verify its primitive and chaining. Forced client/server exchanges then
verify protected traffic and rekey in both library roles. This is compatibility evidence, not a
recommendation to deploy a 64-bit block cipher.
Truncated HMAC-SHA1 interoperability forces both RFC 4253 hmac-sha1-96 and the deployed
hmac-sha1-96-etm@openssh.com method in both peer roles with AES-128-CTR. Each direction explicitly
rekeys and executes a command, while fixed RFC 2202 bytes independently verify that the tag is the
first 12 bytes of the complete HMAC-SHA1 result.
Legacy HMAC-MD5 interoperability similarly forces the full and 96-bit RFC 4253 methods and both deployed encrypt-then-MAC forms with AES-128-CTR. OpenSSH and the modern client each transfer data and rekey for every name in both peer roles. An RFC 2202 vector independently verifies the full digest and first-12-byte truncation; these methods remain last and are not recommended for new use.
Legacy HMAC-RIPEMD160 coverage forms RFC 2286's literal Hi There input through the SSH sequence
number and packet fields and checks its complete 20-byte digest. An in-process client and server
then force hmac-ripemd160 with AES-128-CTR, exchange authenticated traffic in both directions,
and rekey. The method remains an explicit compatibility choice; the system OpenSSH fixture does not
advertise it.
UMAC coverage checks the RFC 4418 messages from empty through 32 MiB, including verified erratum 3507 for the long-message polynomial transition, plus 32-, 64-, and 96-bit output iterations. The system SSH client then forces each deployed 64-/128-bit ordinary and encrypt-then-MAC variant and exchanges channel traffic in both directions across an explicit rekey.
End-of-write coverage uses the literal one-way channel-request frame, verifies awaited half-close state in both channel roles, and rejects replies, arguments, duplicates, and non-session use. The system client accepts a capability-gated server request, stops its input side, and still receives the server's remaining output before normal exit.
Delayed-compression interoperability runs in both peer roles. OpenSSH and the modern client each
force zlib@openssh.com, transfer repeated multi-packet data in both directions, and rekey while the
compression streams are active. Handshake details confirm the selected method before traffic is
accepted.
SFTP interoperability runs in both directions. The modern client uses OpenSSH's revision 3
subsystem for multi-packet upload and download, concurrent reads with request-id matching, file and
directory handles, attributes and timestamps, rename, canonicalization, directory scanning, and
OpenSSH's documented reversed SSH_FXP_SYMLINK arguments. It also negotiates OpenSSH limits and
executes advertised fsync, statvfs, POSIX rename, hard-link, path expansion, server-side copy, home
directory, and identity lookup extensions. Whole-file helpers are exercised for encoded reads,
write, append, size limits, and existence checks; parallel upload and download use deliberately
uneven chunks against the real server. Writable and inclusive-range readable Node streams are also
round-tripped through OpenSSH, and returned mode bits are checked through SFTPStats file-type
predicates. The system OpenSSH sftp client uploads, flushes, lists, renames, creates a hard link,
copies data server-side, queries filesystem space, downloads, and removes files through a
policy-controlled modern server. The copied and linked contents are downloaded independently and
compared byte-for-byte. The observed requests prove negotiation and use of
the limits, fsync, statvfs, POSIX-rename, hard-link, copy-data, and identity-lookup
extensions in the server role. Independent literal vectors cover every baseline request and
response layout and every extension payload; malformed framing, counts, flags, handles, response
types, request identifiers, and extension replies are rejected without relying on another
JavaScript SSH implementation. In-process write control proves that awaited server responses settle
only after channel output completes and reject on output failure. A separate encrypted connection
proves that a later pipelined request can complete while an earlier async server hook remains
pending; focused engine tests cover the configurable concurrency bound, out-of-order replies,
request-identifier reuse, and independent handler failures.
Together, the OpenSSH tests and known vectors exercise identification exchange, KEXINIT
negotiation, exchange-hash and signature verification, NEWKEYS, encrypted and authenticated
packet framing, OpenSSH encrypt-then-MAC ordering, RFC 8731 Curve25519 and RFC 5656 ECDH in both
peer roles, RFC 5647 AES-GCM and OpenSSH ChaCha20-Poly1305 packet protection, bidirectional key
re-exchange, immediate and delayed zlib compression, service negotiation, authentication, session
streams, client- and server-side
remote forwarding, and graceful disconnect behavior. Passing these tests proves the covered
algorithms and features; it does not imply that every OpenSSH algorithm or extension has been
implemented.