puressh 0.0.6

A pure-Rust SSH (Secure Shell) protocol library, in the spirit of libssh, built on purecrypto.
Documentation

puressh

CI Crates.io Docs.rs License: MIT

A pure-Rust SSH (Secure Shell) protocol library and CLI suite, in the spirit of libssh, built on purecrypto for every cryptographic primitive. No C dependencies, no FFI in the dependency tree, and no unsafe in the library itself (the optional ffi feature is the only place unsafe appears, for the C ABI surface).

Status: functional, pre-1.0. Client, server, SFTP, SCP, port/agent/X11 forwarding, known_hosts, and ssh_config parsing are all implemented and tested against OpenSSH. The crate is 0.0.x; the public API may still change before 1.0. See Implementation status.

What's in the box

  • Library — sans-I/O protocol core plus high-level client / server APIs.
  • CLI suite — drop-in ssh, sftp, scp, sshd, and ssh-keygen binaries built on the library.
  • C ABI — optional ffi feature exposing a pcssh_* C interface (staticlib / cdylib), with bytes-path SFTP variants for non-UTF-8 paths.

Goals

  • Pure Rust, no FFI deps. Crypto comes from purecrypto; networking comes from std::net. Nothing links C.
  • no_std friendly. The protocol core (packet codec, KEX, cipher/MAC adapters, key parsing) builds without std; only the convenience I/O and the client/server/CLI layers require it.
  • Modern algorithms first, including a post-quantum hybrid KEX (mlkem768x25519-sha256). Legacy algorithms are present only where they remain useful for interop.
  • Auditable surface. Small modules, narrow public types, every algorithm identifier tracked back to its RFC.

Supported algorithms

Category Algorithm
KEX (PQ) mlkem768x25519-sha256 (ML-KEM-768 + X25519 hybrid)
KEX curve25519-sha256, curve25519-sha256@libssh.org
KEX ecdh-sha2-nistp{256,384,521}
KEX diffie-hellman-group{14,16,18}-sha{256,512}
KEX diffie-hellman-group-exchange-sha256
Host key ssh-ed25519
Host key ecdsa-sha2-nistp{256,384,521}
Host key rsa-sha2-256, rsa-sha2-512, ssh-rsa (with auto-upgrade via server-sig-algs)
Cipher chacha20-poly1305@openssh.com
Cipher aes{128,256}-gcm@openssh.com
Cipher aes{128,192,256}-ctr
MAC hmac-sha2-{256,512} (+ -etm@openssh.com variants)
Compression none, zlib, zlib@openssh.com (delayed)
Auth none, password, publickey, keyboard-interactive, hostbased
Extensions RFC 8308 ext-info / server-sig-algs

Cargo features

Feature Default Description
std yes I/O helpers, OS RNG, std::error::Error
alloc yes Heap-backed types (implied by std)
client yes High-level client API
server yes High-level server API
compress yes zlib compression via compcol
pam yes PAM session integration for sshd (Linux only)
multichannel yes Concurrent multi-channel client (SharedClient, SftpSession)
ffi no C ABI surface (pcssh_*); implies client + multichannel

Disable defaults for no_std:

puressh = { version = "0.0.5", default-features = false, features = ["alloc"] }

Quick start

use puressh::client::{Client, Config};

fn main() -> Result<(), puressh::Error> {
    // `Config::insecure()` trusts any host key — fine for a throwaway example.
    // Use `Config::with_known_hosts(store)` for OpenSSH-style strict checking.
    let mut c = Client::connect("example.com:22", Config::insecure())?;
    c.authenticate_password("alice", "hunter2")?;

    let out = c.exec("uname -a")?;
    println!("{}", String::from_utf8_lossy(&out.stdout));
    println!("exit: {:?}", out.exit_status);
    Ok(())
}

For concurrent channels (several SFTP / exec / shell / tunnel handles on one connection), use the multichannel layer's SharedClient and its sftp() / exec_stream() / shell() / open_direct_tcpip() helpers.

CLI binaries

Built with the default features:

cargo build --release
Binary Purpose
ssh Interactive shell / exec, port forwarding (-L/-R), agent & X11 forwarding
sftp Interactive SFTP client
scp File copy over SSH
sshd SSH server daemon (PTY, PAM sessions on Linux)
ssh-keygen Key generation and OpenSSH key-file management

All of them understand ssh_config (including Match blocks and Include), known_hosts, and bracketed-IPv6 host syntax ([2001:db8::1]:22).

Module layout

src/
├── lib.rs           public re-exports
├── error.rs         Error / Result
├── format/          SSH wire format (Reader, Writer, mpint, name-list)
├── transport/       binary packet protocol, version exchange, KEX runner
├── kex/             curve25519, ecdh-nistp*, group-DH, GEX, mlkem768x25519
├── cipher/          aes-ctr, aes-gcm, chacha20-poly1305
├── mac/             hmac-sha2-* (incl. -etm)
├── hostkey/         ed25519, ecdsa-*, rsa-*
├── auth/            userauth state machine (RFC 4252)
├── channel/         RFC 4254 channels
├── key/             OpenSSH public/private key files
├── known_hosts/     known_hosts store + verification
├── config/          ssh_config / sshd_config parsing (Match, Include)
├── compress/        zlib / zlib@openssh.com
├── forwarding/      direct-tcpip, reverse, agent, X11
├── sftp/            SFTP client + server (with OpenSSH @openssh.com extensions)
├── scp/             SCP protocol
├── agent/           ssh-agent client protocol
├── shared.rs        SharedClient (multichannel layer)
├── ffi/             C ABI surface (feature `ffi`)
├── client.rs        high-level client API (feature `client`)
├── server.rs        high-level server API (feature `server`)
└── bin/             ssh, sftp, scp, sshd, ssh-keygen

MSRV

puressh follows purecrypto's MSRV: Rust 1.95. If cargo check fails with "rustc X is not supported … requires rustc 1.95", upgrade your toolchain.

Implementation status

Layer Status
Wire format (format/) ✅ reader, writer, mpint, name-list
Binary packet codec ✅ encrypt/decrypt, ETM, rekey
Version exchange
KEX (all algorithms above) ✅ incl. PQ hybrid + GEX
Ciphers / MACs
Host keys (ed25519/ecdsa/rsa) ✅ incl. server-sig-algs upgrade
OpenSSH key file parsing ✅ incl. encrypted keys (bcrypt_pbkdf)
Userauth (RFC 4252) ✅ password / publickey / kbd-int / hostbased
OpenSSH certificates ✅ host + user certs, @cert-authority, TrustedUserCAKeys, KRL (RevokedKeys)
Channels / sessions
Client API
Server API
SFTP client + server ✅ incl. OpenSSH extensions
SCP
Port / agent / X11 forwarding
known_hosts
ssh_config (Match/Include)
C ABI (ffi) ✅ optional

Non-goals. A few OpenSSH directives are intentionally unsupported and are rejected (strict mode) rather than silently ignored: PermitTunnel (tun/tap device forwarding) and external-command Subsystem entries.

Security

This is pre-1.0 software that has not had an independent third-party audit. It is built on purecrypto and has been the subject of internal security-review passes (host-key trust handling, forwarding default-deny policies, SFTP jail hardening, secret zeroization, DoS caps). Use the strict known_hosts policy (Config::with_known_hosts) in anything that matters, and review before deploying in a security-sensitive context.

License

Dual-licensed under either of

at your option.