Skip to content
/ qsh Public

A quantum-resistant remote shell built on QPP (encryption), HPPK (authentication), and HMAC (authenticity).

License

Notifications You must be signed in to change notification settings

xtaci/qsh

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

99 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

qsh

GoDoc Go Report Card CreatedAt

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.

Handshake Diagram

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

  1. 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.

  2. 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
  3. 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

  1. ClientHello – announces a client ID and embeds a fresh server challenge so the client can demand proof of identity in the next step.
  2. 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.
  3. AuthChallenge – server returns a random challenge, KEM-wrapped session seed, and the negotiated prime pad count.
  4. AuthResponse – client signs the challenge with its HPPK private key and proves possession.
  5. AuthResult – server verifies the signature before both sides derive directional seeds (qsh-c2s, qsh-s2c) via HKDF and instantiate QPP pads.
  6. 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.

About

A quantum-resistant remote shell built on QPP (encryption), HPPK (authentication), and HMAC (authenticity).

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages