Skip to content

SSH library for Kotlin written with Kaitai Struct and KStateMachine

License

Notifications You must be signed in to change notification settings

kruton/ssh-proto

Repository files navigation

ConnectBot SSH Client Library (IN PROGRESS)

This is currently a work-in-progress and not meant to be used for production.

This is ConnectBot SSH library built with Kotlin. Internally it uses coroutines, protocol definition files, and a state machine to run the SSH protocol. It currently connects to SSH servers, authenticates, and provide interactive shell sessions.

The protocol parsing uses declarative Kaitai Struct specifications that auto-generate code from .ksy definitions. The internal state machine is defined in KStateMachine for clear separation of protocol states from the code that runs in reaction to state changes.

Features

  • SSH Client: Connect, authenticate, open shell sessions, read/write data
  • Protocol Parsing: Complete SSH wire protocol coverage (RFCs 4250-4256, 4419, 5656, 8308, 8709, 8731, 9142)
  • Channel I/O: Interactive shells with PTY, stdout/stderr streams, flow control
  • Port Forwarding: Local, remote, and dynamic (SOCKS5) port forwarding
  • Agent Forwarding: Forward SSH agent requests with session binding support
  • Transport: Pluggable transport layer (TCP via Ktor, or custom)

Algorithm Support

Authentication

  • keyboard-interactive
  • password
  • publickey

Host Keys

Key Exchange

Encryption

MACs

Quick Start

Build

./gradlew build

Use the Test CLI Client

There is a "testapp" that allows you to try the library from a test client app. You can use it by running the following commands:

./gradlew :testapp:installDist
./testapp/build/install/testapp/bin/testapp user@host
./testapp/build/install/testapp/bin/testapp user@host -p 2222

# Enable more debug logging:
./testapp/build/install/testapp/bin/testapp -d user@host

Library API

val client = SshClient("example.com", 22)
client.connect()
client.authenticatePassword("user", "pass")

val session = client.openSession()
session.requestPty()
session.requestShell()

// Read/write
session.write("ls\n".toByteArray())
val output = session.read()  // ByteArray? (null on EOF)

// Or use coroutine channels directly
session.stdout  // ReceiveChannel<ByteArray>
session.stderr  // ReceiveChannel<ByteArray>

// Clean up
session.close()
client.disconnect()

SSH Agent Forwarding

Enable SSH agent forwarding to allow remote servers to use your keys:

// Implement an agent provider
class MyAgentProvider : AgentProvider {
    override suspend fun getIdentities(): List<AgentIdentity> {
        val keyBlob = loadPublicKeyBlob()
        return listOf(AgentIdentity(keyBlob, "my-key"))
    }

    override suspend fun signData(context: AgentSigningContext): ByteArray? {
        // Show approval UI to user with session context
        val approved = showSigningPrompt(
            "Remote server ${context.serverHostKey.toHex()} wants to use your key",
            "Session bound: ${context.isBound}"
        )

        return if (approved) {
            signWithPrivateKey(context.publicKeyBlob, context.dataToSign)
        } else {
            null  // Deny the request
        }
    }
}

// Enable agent forwarding
val client = SshClient("bastion.example.com")
client.connect()
client.authenticatePassword("user", "pass")
client.enableAgentForwarding(MyAgentProvider())

// Now remote servers can use your agent through forwarding
val session = client.openSession()
session.requestShell()
// When you SSH from bastion to another server, it can request signatures

Compatibility Testing

The library is tested against multiple SSH server implementations using Docker (via Testcontainers):

  • OpenSSH 9.9p2 — full integration tests including port forwarding
  • AsyncSSH (Python) — compatibility tests for ciphers, key exchange, MACs, and public key auth
  • Dropbear — compatibility tests including ML-KEM post-quantum key exchange

Run integration tests with: ./gradlew :sshlib:test (requires Docker).

Current Limitations

  • No SFTP
  • Client-only (no server implementation)

License

Apache License 2.0 - See LICENSE file

Copyright

Copyright 2019-2025, Kenny Root

About

SSH library for Kotlin written with Kaitai Struct and KStateMachine

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •