English | 简体中文
Status: Developing
qsh is a Go-based secure remote shell that mirrors an SSH login experience while relying on two research projects from the same author: HPPK for post-quantum-friendly authentication and QPP for stream encryption. The binary exposes both a server and client mode, plus a helper for generating compatible keypairs.
- Strong authentication – servers whitelist client IDs and verify HPPK signatures produced during the handshake.
- Encrypted tunnel – both directions derive unique pads via HKDF, feed them into QPP, and negotiate a random prime pad count (between 1024 and 2048) for each connection.
- Proto-framed control channel – all signaling (hello, challenges, resize notices, encrypted data) rides over a length-prefixed protobuf envelope defined in
protocol/. - True terminal UX – the server spawns a PTY via
/bin/sh, mirrors stdout/stderr, and honors window resize events. - Built-in key management – run
qsh genkey -o <path>to create JSON-encoded private/public key files (private halves are encrypted with a passphrase). - Memory Protection – uses
memguardto securely handle private keys and passphrases in memory, preventing swap leaks and core dump exposure.
-
Generate keys (run once):
# Generate server host key qsh genkey -o ./server_hppk # Generate client key qsh genkey -o ./id_hppk
Copy
id_hppk.pubto the server and reference it via-c client-1=/path/to/id_hppk.pub. -
Start the server:
qsh server -l :2323 --host-key ./server_hppk -c client-1=/etc/qsh/id_hppk.pub
Or use a clients configuration file:
qsh server -l :2323 --host-key ./server_hppk --clients-config /etc/qsh/clients.json
-
Connect from the client (client mode is the default when no subcommand is provided):
qsh -i ./id_hppk -P 2323 [email protected]
Omit
-Pto fall back to the default port2222, or provide-n/--idto override the client identifier when it is not embedded in theclient-id@hosttarget.
The copy subcommand reuses the same identity flags as the interactive client while accepting SCP-style targets in the form client-id@host:/remote/path. Exactly one endpoint must be remote.
-
Upload a local file to the server (defaults to TCP port 2222 when no
:portsuffix is present):qsh copy -i ./id_hppk ./notes.txt [email protected]:/tmp/notes.txt
-
Download a remote file to the current directory, overriding the port with
-P:qsh copy -i ./id_hppk -P 4242 [email protected]:/var/log/qsh.log ./qsh.log
Both commands authenticate as client-1 (taken either from the remote spec or via -n/--id) and automatically derive the encrypted file-transfer channel.
Instead of listing every --client flag on the command line, the server can load its allowlist from a JSON file via --clients-config:
{
"clients": [
{ "id": "xtaci", "public_key": "/home/xtaci/xtaci.pub" },
{ "id": "ops-admin", "public_key": "/etc/qsh/ops-admin.pub" }
]
}- Each entry must provide a unique
idplus the filesystem path of the corresponding HPPK public key. - Combine the JSON file with extra
--client id=/pathflags to layer temporary overrides. - Send
SIGUSR1to the running server process (e.g.,kill -USR1 <pid>) whenever the file changes to trigger an in-place reload of the registry.
- ClientHello – announces a client ID and embeds a fresh server challenge so the client can demand proof of identity in the next step.
- ServerHello – the server responds with its public key and signature; the client checks the fingerprint against
known_hosts(or accepts and records a new one) to confirm it is talking to the expected peer. - AuthChallenge – server returns a random challenge, KEM-wrapped session seed, and the negotiated prime pad count.
- AuthResponse – client signs the challenge with its HPPK private key and proves possession.
- AuthResult – server verifies the signature before both sides derive directional seeds (
qsh-c2s,qsh-s2c) via HKDF and instantiate QPP pads. - Secure streaming – plaintext PTY data and resize events are wrapped inside
PlainPayload, encrypted intoSecureData, and exchanged until either side disconnects.
- Requires Go 1.25.4+ (see
go.mod). - Run tests with
go test ./...to exercise the protobuf auth flow. - Key implementation files:
main.go– CLI entry point and command definitions.cmd_client.go,cmd_server.go,cmd_copy.go– command handlers for client, server, and copy operations.session.go– handshake protocol implementation for client and server.tty.go– PTY management and terminal I/O forwarding.transfer.go– file upload/download implementation.channel.go– encrypted communication channel with replay protection.protocol/– protobuf definitions plus length-prefixed codec helpers.crypto/– key generation, encrypted key storage, HPPK signatures, and HKDF derivation.
See LICENSE for the MIT terms that govern this project.
