-
Notifications
You must be signed in to change notification settings - Fork 0
Transports and Security
The wire language is the same whatever carries it. A unix socket, plain TCP and TLS differ only in the endpoint you dial — every page in this wiki applies unchanged over all three.
conn, err := client.Dial("tls://host:9797", "My App", nil)| Endpoint | Transport |
|---|---|
/run/kittytk/display-0.sock |
unix socket — a bare path, and the default |
unix:/run/kittytk/display-0.sock |
the same, written explicitly |
tcp://host:port |
plain TCP — loopback or a trusted LAN only |
tls://host:port |
TLS — for anything else |
tcp:// and tls:// assume port 9797 when none is given.
A bare path is still a unix socket, so Dial, dial and kt_dial keep the
signatures they always had and existing code is unaffected.
$KITTYTK_DISPLAY — read by clients and hosts alike, so the two always
agree.
Unset, it defaults to $XDG_RUNTIME_DIR/kittytk/display-0.sock, falling back
to the system temporary directory when XDG_RUNTIME_DIR is not set.
On Windows the default is tcp://127.0.0.1:9797 instead, because
AF_UNIX is not dependable there.
Plain TCP carries the wire language in the clear, and the wire language is
your whole interface: captions, list contents, whatever a user types into a
TextInput. Use it on loopback, or on a network you already
trust for everything else. Otherwise use tls://.
There is no CA and nothing to buy. The host presents a persistent self-signed certificate; your client records its SHA-256 fingerprint the first time it connects and checks it on every reconnect afterwards — the same trust-on-first-use model as SSH.
The pins live in known_hosts. On a first connection the client stores the
fingerprint and says so:
kittytk: pinned new host host:9797 sha256:1f3a…
On a later connection to a host whose identity has changed, it refuses and tells you what to do:
host identity for host:9797 changed!
pinned sha256:1f3a…
got sha256:9b02…
if this is expected, remove that line from /home/you/.config/kittytk/known_hosts
That refusal is the point of the scheme — it is what stands between you and someone else answering on that address. Do not clear the line without knowing why it changed.
The first connection is the one TOFU cannot protect. To close that gap,
get the fingerprint by some other route — the host prints it at startup — and
write it into known_hosts before you connect.
tls:// is mutual: the client presents a persistent self-signed identity
of its own, generated once on first use and kept in identity.pem. It is
your client's long-lived key, like an SSH key, and there is nothing to
configure.
The host identifies you by that fingerprint together with the application
name you passed to Dial. Two consequences worth planning for:
- A connection may not be admitted immediately. The host asks its user, and your dial waits on a human. Handle a connection that takes a while, or is refused.
- Your application name is part of your identity. Being trusted once does not let you connect later under a different name — approval is remembered per name, so a client cannot quietly present an app it was never approved for. Pick a name and keep it.
Local connections — a unix socket, or loopback — are same-machine and are admitted without asking.
A host that has no user to ask may accept a shared token instead. Put it in
$KITTYTK_TOKEN and the client presents it in the handshake. Over
tls:// it cannot be sniffed; over tcp:// it can, so treat the two
differently. It never applies to local connections, which do not need it.
Per-user, in <config>/kittytk/, where <config> is $XDG_CONFIG_HOME,
else %APPDATA% on Windows, else ~/.config. The Go, Python and C clients
all use that same rule, so one machine has one store and they share it.
| Path | What |
|---|---|
identity.pem |
your client's key and certificate |
known_hosts |
fingerprints you have pinned |
| Variable | Purpose |
|---|---|
KITTYTK_DISPLAY |
the endpoint — path, or tcp:// / tls:// URL |
KITTYTK_TOKEN |
handshake token, where a host requires one |
KITTYTK_IDENTITY |
use a different client identity PEM |
KITTYTK_KNOWN_HOSTS |
use a different pin store |
KITTYTK_INSECURE |
1 turns pinning off — diagnostics only |
KITTYTK_INSECURE removes the protection this whole section is about. It is
for working out why a handshake fails, not for getting past one.
All of them run on Windows, Linux and macOS, and all speak the same transports.
Go — everything, everywhere.
Python — tls:// needs either the cryptography package or the
openssl command line, to mint the client identity on first use; without
either, point $KITTYTK_IDENTITY at a PEM you already have. AF_UNIX may
be missing on Windows, so use tcp:// there.
C — builds on Winsock2 and on POSIX. The default build needs only libc
and pthreads and speaks unix sockets and tcp://; tls:// is opt-in with
-DKT_TLS and links OpenSSL.
Protocol Overview — the language that travels over this · Application — the name you dial with · Introspection — asking a host what it supports
KittyTK — image/tty Trinket Kit · MIT licensed · alpha, 0.1.x
Repository · Issues · Support on ko-fi
Sibling projects: PurfecTerm (terminal emulator) · mew (text editor) · PawScript (language)
Getting Started
Installation Building from Source Running a Display Host Your First Application Examples
Protocol
Protocol Overview Object Model Properties and Values Events Templates and Aliases Common Properties Introspection Transports and Security
Clients
Go Client Python Client C Client
Application Objects
Application · MenuBar · Window · MessageBox
Output Trinkets
Label · ProgressBar · StatusBar
Input Trinkets
TextInput · Editor · Terminal
Button · CheckBox · RadioButton
ListView · ComboBox · TreeView
Layout Trinkets
TabTrinket · Panel
ScrollArea · MDIPane
Separator · Spacer · Splitter
Other Trinkets
Layout Helpers