| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
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.
The library supports a wide range of modern SSH algorithms, including:
For a complete list of supported algorithms and their respective RFCs, see docs/ALGORITHMS.md.
The defaults intentionally exclude SHA-1 key exchange and MACs, CBC/3DES ciphers, and ssh-rsa host-key signatures. These legacy algorithms remain available only through the explicit kexAlgorithms, hostKeyAlgorithms, encryptionAlgorithms, and macAlgorithms settings in SshClientConfig. RSA user authentication normally requires the server to advertise rsa-sha2-256 or rsa-sha2-512 through server-sig-algs. Explicitly including ssh-rsa in the configured host-key algorithm wishlist also permits the legacy RSA/SHA-1 signature when advertised, or as the base-key algorithm when that extension is absent.
./gradlew buildThere 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@hostval client = SshClient("example.com", port = 22, hostKeyVerifier = myVerifier)
check(client.connect() is ConnectResult.Success) { "SSH connection failed" }
check(client.authenticatePassword("user", "pass") is AuthResult.Success) {
"SSH authentication failed"
}
val session = checkNotNull(client.openSession()) { "Failed to open SSH session" }
check(session.requestPty()) { "Server rejected PTY request" }
check(session.requestShell()) { "Server rejected shell request" }
// 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()val sftp = when (val result = client.openSftp()) {
is SftpResult.Success -> result.value
else -> error("Failed to open SFTP: $result")
}
try {
// List a directory
when (val result = sftp.listdir("/home/user")) {
is SftpResult.Success -> result.value.forEach { println(it.filename) }
is SftpResult.ServerError -> println("Server error: ${result.message}")
else -> println("Error: $result")
}
// Read a file
val handle = sftp.open("/home/user/file.txt", setOf(SftpOpenFlag.READ)).getOrThrow()
try {
val data = sftp.read(handle, 0L, 4096).getOrThrow() // ByteArray? (null on EOF)
} finally {
sftp.close(handle).getOrThrow()
}
} finally {
sftp.close()
}The library supports authentication with sk-ssh-ed25519@openssh.com and sk-ecdsa-sha2-nistp256@openssh.com keys. Callers provide their own FIDO2 stack and surface the resulting assertion through the library's helpers.
See docs/SK_AUTH.md for detailed implementation details and examples.
Enable SSH agent forwarding to allow remote servers to use your keys:
// Implement an agent provider
class MyAgentProvider : AgentProvider {
override suspend fun getIdentities(): AgentResult<List<AgentIdentity>> {
val keyBlob = loadPublicKeyBlob()
return AgentResult.Success(listOf(AgentIdentity(keyBlob, "my-key")))
}
override suspend fun signData(context: AgentSigningContext): AgentResult<ByteArray?> {
// Show approval UI to user with session context
val approved = showSigningPrompt(
"Remote server ${context.serverHostKey.joinToString("") { "%02x".format(it) }} wants to use your key",
"Session bound: ${context.isBound}"
)
return AgentResult.Success(if (approved) {
signWithPrivateKey(context.publicKeyBlob, context.dataToSign)
} else {
null // Deny the request
})
}
}
// Enable agent forwarding
val client = SshClient("bastion.example.com", hostKeyVerifier = myVerifier)
check(client.connect() is ConnectResult.Success) { "SSH connection failed" }
check(client.authenticatePassword("user", "pass") is AuthResult.Success) {
"SSH authentication failed"
}
client.enableAgentForwarding(MyAgentProvider())
// Now remote servers can use your agent through forwarding
val session = checkNotNull(client.openSession()) { "Failed to open SSH session" }
check(session.requestShell()) { "Server rejected shell request" }
// When you SSH from bastion to another server, it can request signaturesThe library is tested against multiple SSH server implementations using Docker (via Testcontainers):
Run integration tests with: ./gradlew :sshlib:test (requires Docker).
Apache License 2.0 - See LICENSE file
Copyright 2019-2026, Kenny Root
| Back | FazBrowse Home | New Git URL |