README
¶
kpjs: Katzenpost ThinClient Javascript bindings
Javascript bindings for Katzenpost thin clients allows to create Katzenpost clients that can run in a web browser.
License
Copyright (C) 2026-present, Bernd Fix >Y<
'kpjs' is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
'kpjs' is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see http:www.gnu.org/licenses/.
SPDX-License-Identifier: AGPL3.0-or-later
Caveat
THIS IS WORK-IN-PROGRESS AT A VERY EARLY STATE. DON'T EXPECT ANY COMPLETE DOCUMENTATION OR COMPILABLE, RUNNABLE OR EVEN OPERATIONAL SOURCE CODE.
Prerequisites
- Docker to run the
tinygocompiler (tinygo/tinygo-dev):
The WASM module is compiled from source with the mk command (run in the
repo folder):
docker run --rm -v $(realpath .):/src -w /src \
-e GOOS=js -e GOARCH=wasm \
-e GOFLAGS="-buildvcs=false" \
tinygo/tinygo-dev:latest \
tinygo build -o kpjs.wasm -tags=thinclient -target=wasm ./cmd/kpjs
If you use tinygo in a local installation, use your own custom build command.
- Running Katzenpost
kpclientd(v0.0.92+) with aclient.tomlfor websocket support:
[Listen]
[Listen.Ws]
Address = "ws://127.0.0.1:1984"
- Python3 to run the local web server.
Running the demo
- compile the
kpjs.wasmmodule:
./mk
If you want to customize the build process, copy mk to mk_local and apply the
changes in the new file.
- start a local web server and open page in Chromium:
./run
If you want to customize how the tests are run, copy run to run_local and apply the
changes in the new file - e.g. if you want to use a different local port and/or browser.
The script will automatically open the Chromium browser and show the test webpage.
Clicking the Run button will start the demo. Everything is logged to the
webpage as the demo steps proceed. It is recommended to open the console
(browser devtools) and look for messages there too.
Demo code explained
-
The WASM start-up code and the page layout are defined in
kpjs.html- nothing special... -
The demo code is in
kpjs.js(functionrunClient()). It works ike this:
Get client instance
// get new client connection
cons.log("Get client instance...",true)
client = await NewClient(addr.value);
if (client == null) {
cons.log("failed to get client instance.");
return;
}
The starting point for all Javascript-based clients is to create a new client instance that connects to a websocket specified by the address. The framework returns a Javascript client object with the following methods:
| method | return value | description |
|---|---|---|
| Ref() | short description/reference | |
| PKIDocument() | current PKI document | |
| GetService(name) | service descriptor | |
| AddEventHandler(fcn) | set event listener function | |
| BlockingSendMessage(srv,payl,timeout) | reply | |
| Close() | shutdown client |
Get the current PKI document and show mix topology
// get the current PKI document
cons.log("Get PKI document...",true);
doc = client.PKIDocument();
When a client is connected to a daemon, we can retreive the current PKI
document with the above code. doc is a Javascript object you can use directly.
It has (nested) attributes and the following methods:
| method | return value | description |
|---|---|---|
| Ref() | short description/reference |
The attributes can be used to inspect the document:
// list topology in console
cons.log("Topology:", true)
doc.Topology.forEach((layer, i) => {
layer.forEach((node, j) => {
log(cons, `Layer ${i+1}: #${j+1} = ${node.Name}`);
});
});
Get a service descriptor for "echo"
// communicate with an echo service
cons.log("Get echo service descriptor:", true);
srv = client.GetService("echo");
cons.log(srv.Ref());
cons.log(JSON.stringify(srv));
srv is a Javascript object you can use directly.
It has (nested) attributes and the following methods:
| method | return value | description |
|---|---|---|
| Ref() | short description/reference |
Send five pings to the echo service
// send five pings
count = 5;
cons.log(`Sending ${count} Sphinx packets to ${srv_obj.name}@${srv_obj.node}`, true);
await pingService(client,srv,10*60*1000,count,cons);
See the pingService() function in kpjs.js for further details.
Register a Javascript callback function to receive events
// handle events
client.AddEventHandler(function(ev) {
msg = JSON.stringify(ev)
log(cons, `Event: ${msg}`);
});
Clean-up
If the client is done it should run some clean-up:
// clean-up
client.Close();
TODO
- support for the
pigeonholeprotocol (chat)