qsh

English | 简体中文
Status: Developing
Overview
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.

Key Features
- 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
memguard to securely handle private keys and passphrases in memory, preventing swap leaks and core dump exposure.
Quick Start
-
Generate keys (run once):
# Generate server host key
qsh genkey -o ./server_hppk
# Generate client key
qsh genkey -o ./id_hppk
Copy id_hppk.pub to 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 -P to fall back to the default port 2222, or provide -n/--id to override the client identifier when it is not embedded in the client-id@host target.
Copying Files
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 :port suffix 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.
Client Registry Configuration
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
id plus the filesystem path of the corresponding HPPK public key.
- Combine the JSON file with extra
--client id=/path flags to layer temporary overrides.
- Send
SIGUSR1 to the running server process (e.g., kill -USR1 <pid>) whenever the file changes to trigger an in-place reload of the registry.
Protocol Highlights
- 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 into SecureData, and exchanged until either side disconnects.
Development Notes
- 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.
License
See LICENSE for the MIT terms that govern this project.