├── python ├── klutshnik │ ├── __init__.py │ └── cfg.py ├── MANIFEST.in ├── .gitignore ├── README.org └── setup.py ├── test ├── servers │ ├── 0 │ │ ├── ltsig.key │ │ ├── noise.key │ │ ├── rtoken.key │ │ ├── server.der │ │ ├── ltsig.key.pub │ │ ├── noise.key.pub │ │ ├── cert.pem │ │ └── klutshnikd.cfg │ ├── 1 │ │ ├── ltsig.key │ │ ├── noise.key │ │ ├── rtoken.key │ │ ├── server.der │ │ ├── ltsig.key.pub │ │ ├── noise.key.pub │ │ ├── cert.pem │ │ └── klutshnikd.cfg │ ├── 2 │ │ ├── ltsig.key │ │ ├── noise.key │ │ ├── rtoken.key │ │ ├── server.der │ │ ├── ltsig.key.pub │ │ ├── noise.key.pub │ │ ├── cert.pem │ │ └── klutshnikd.cfg │ ├── 3 │ │ ├── ltsig.key │ │ ├── noise.key │ │ ├── rtoken.key │ │ ├── server.der │ │ ├── ltsig.key.pub │ │ ├── noise.key.pub │ │ ├── cert.pem │ │ └── klutshnikd.cfg │ ├── 4 │ │ ├── ltsig.key │ │ ├── noise.key │ │ ├── rtoken.key │ │ ├── server.der │ │ ├── ltsig.key.pub │ │ ├── noise.key.pub │ │ ├── cert.pem │ │ └── klutshnikd.cfg │ ├── drei.pub │ ├── eins.pub │ ├── vier.pub │ ├── zero.pub │ ├── zwei.pub │ ├── authorized_keys │ └── start-servers.sh ├── client.key ├── client.pub ├── kltsk ├── otherclient │ ├── client.key │ └── klutshnik.cfg ├── easy-test.sh ├── klutshnik.cfg └── test.sh ├── images └── klutshnik-sbox-rpi │ ├── input │ ├── klutshnik-rev │ ├── test │ │ ├── servers │ │ │ ├── 0 │ │ │ │ ├── ltsig.key │ │ │ │ ├── noise.key │ │ │ │ ├── server.der │ │ │ │ ├── ltsig.key.pub │ │ │ │ ├── noise.key.pub │ │ │ │ ├── cert.pem │ │ │ │ └── klutshnik.cfg │ │ │ ├── 1 │ │ │ │ ├── ltsig.key │ │ │ │ ├── noise.key │ │ │ │ ├── server.der │ │ │ │ ├── ltsig.key.pub │ │ │ │ ├── noise.key.pub │ │ │ │ ├── cert.pem │ │ │ │ └── klutshnik.cfg │ │ │ ├── 2 │ │ │ │ ├── ltsig.key │ │ │ │ ├── noise.key │ │ │ │ ├── server.der │ │ │ │ ├── ltsig.key.pub │ │ │ │ ├── noise.key.pub │ │ │ │ ├── cert.pem │ │ │ │ └── klutshnik.cfg │ │ │ ├── 3 │ │ │ │ ├── ltsig.key │ │ │ │ ├── noise.key │ │ │ │ ├── server.der │ │ │ │ ├── ltsig.key.pub │ │ │ │ ├── noise.key.pub │ │ │ │ ├── cert.pem │ │ │ │ └── klutshnik.cfg │ │ │ ├── 4 │ │ │ │ ├── ltsig.key │ │ │ │ ├── noise.key │ │ │ │ ├── server.der │ │ │ │ ├── ltsig.key.pub │ │ │ │ ├── noise.key.pub │ │ │ │ ├── cert.pem │ │ │ │ └── klutshnik.cfg │ │ │ ├── drei.pub │ │ │ ├── eins.pub │ │ │ ├── vier.pub │ │ │ ├── zero.pub │ │ │ ├── zwei.pub │ │ │ ├── start-servers.sh │ │ │ └── authorized_keys_template │ │ ├── kltsk │ │ ├── client.key │ │ ├── client.pub │ │ ├── otherclient │ │ │ ├── client.key │ │ │ └── klutshnik.cfg │ │ ├── klutshnik.cfg │ │ └── test.sh │ ├── klutshnikd │ ├── setup_init.sh │ ├── stages │ │ ├── 60 │ │ │ └── 02-hardware.sh │ │ └── 90 │ │ │ └── 50-compress.sh │ ├── init.sh │ ├── klutshnik.cfg_template │ ├── sbox.sh │ ├── image.sh │ └── setup.sh │ ├── build.env │ ├── build_image.sh │ └── README.md ├── server ├── seccomp │ ├── sbox.sh │ ├── musl-1.2.5.bpf │ └── makefile ├── src │ ├── utils.zig │ ├── workaround.h │ ├── workaround.c │ └── secret_allocator.zig ├── build.zig.zon └── build.zig ├── man ├── klutshnikd.head ├── klutshnik.head ├── klutshnik.cfg.head ├── klutshnikd.cfg.head ├── makefile ├── klutshnikd.md ├── klutshnikd.cfg.md ├── klutshnik.cfg.md └── klutshnik.md ├── website ├── keeper7keys.jpg ├── makefile ├── code.org ├── servers.org ├── docs.org ├── faq.org ├── index.org ├── client_install.org └── device_install.org ├── .gitmodules ├── utils.h ├── .gitignore ├── libklutshnik.pc0 ├── streamcrypt.h ├── utils.c ├── tuokms.h ├── .github └── workflows │ └── build-test-publish.yml ├── makefile ├── streamcrypt.c ├── tuokms.c ├── README.md └── whitepaper.org /python/klutshnik/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test/servers/drei.pub: -------------------------------------------------------------------------------- 1 | 3/ltsig.key.pub -------------------------------------------------------------------------------- /test/servers/eins.pub: -------------------------------------------------------------------------------- 1 | 1/ltsig.key.pub -------------------------------------------------------------------------------- /test/servers/vier.pub: -------------------------------------------------------------------------------- 1 | 4/ltsig.key.pub -------------------------------------------------------------------------------- /test/servers/zero.pub: -------------------------------------------------------------------------------- 1 | 0/ltsig.key.pub -------------------------------------------------------------------------------- /test/servers/zwei.pub: -------------------------------------------------------------------------------- 1 | 2/ltsig.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/klutshnik-rev: -------------------------------------------------------------------------------- 1 | c25fb7f 2 | -------------------------------------------------------------------------------- /python/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.org 2 | include *.py 3 | -------------------------------------------------------------------------------- /python/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | dist 3 | klutshnik.egg-info 4 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/drei.pub: -------------------------------------------------------------------------------- 1 | 3/ltsig.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/eins.pub: -------------------------------------------------------------------------------- 1 | 1/ltsig.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/vier.pub: -------------------------------------------------------------------------------- 1 | 4/ltsig.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/zero.pub: -------------------------------------------------------------------------------- 1 | 0/ltsig.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/zwei.pub: -------------------------------------------------------------------------------- 1 | 2/ltsig.key.pub -------------------------------------------------------------------------------- /server/seccomp/sbox.sh: -------------------------------------------------------------------------------- 1 | ../../images/klutshnik-sbox-rpi/input/sbox.sh -------------------------------------------------------------------------------- /man/klutshnikd.head: -------------------------------------------------------------------------------- 1 | .TH "klutshnikd" "1" "" "" "klutshnik KMS server" 2 | -------------------------------------------------------------------------------- /man/klutshnik.head: -------------------------------------------------------------------------------- 1 | .TH "klutshnik" "1" "" "" "Klutshnik command-line client" 2 | -------------------------------------------------------------------------------- /test/client.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/client.key -------------------------------------------------------------------------------- /test/client.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/client.pub -------------------------------------------------------------------------------- /man/klutshnik.cfg.head: -------------------------------------------------------------------------------- 1 | .TH "klutshnik.cfg" "5" "" "" "klutshnik client configuration" 2 | -------------------------------------------------------------------------------- /man/klutshnikd.cfg.head: -------------------------------------------------------------------------------- 1 | .TH "klutshnikd.cfg" "5" "" "" "Klutshnik KMS server configuration" 2 | -------------------------------------------------------------------------------- /website/keeper7keys.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/website/keeper7keys.jpg -------------------------------------------------------------------------------- /test/servers/0/ltsig.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/0/ltsig.key -------------------------------------------------------------------------------- /test/servers/0/noise.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/0/noise.key -------------------------------------------------------------------------------- /test/servers/0/rtoken.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/0/rtoken.key -------------------------------------------------------------------------------- /test/servers/0/server.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/0/server.der -------------------------------------------------------------------------------- /test/servers/1/ltsig.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/1/ltsig.key -------------------------------------------------------------------------------- /test/servers/1/noise.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/1/noise.key -------------------------------------------------------------------------------- /test/servers/1/rtoken.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/1/rtoken.key -------------------------------------------------------------------------------- /test/servers/1/server.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/1/server.der -------------------------------------------------------------------------------- /test/servers/2/ltsig.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/2/ltsig.key -------------------------------------------------------------------------------- /test/servers/2/noise.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/2/noise.key -------------------------------------------------------------------------------- /test/servers/2/rtoken.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/2/rtoken.key -------------------------------------------------------------------------------- /test/servers/2/server.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/2/server.der -------------------------------------------------------------------------------- /test/servers/3/ltsig.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/3/ltsig.key -------------------------------------------------------------------------------- /test/servers/3/noise.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/3/noise.key -------------------------------------------------------------------------------- /test/servers/3/rtoken.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/3/rtoken.key -------------------------------------------------------------------------------- /test/servers/3/server.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/3/server.der -------------------------------------------------------------------------------- /test/servers/4/ltsig.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/4/ltsig.key -------------------------------------------------------------------------------- /test/servers/4/noise.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/4/noise.key -------------------------------------------------------------------------------- /test/servers/4/rtoken.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/4/rtoken.key -------------------------------------------------------------------------------- /test/servers/4/server.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/4/server.der -------------------------------------------------------------------------------- /test/kltsk: -------------------------------------------------------------------------------- 1 | kltsk-eJ/iA0ow1jZxpFyVzE6ZNQ6Fz7+sD9ic+UCixQGwAnuzaHViYh06c0KCToEh2tuCHSN14X9DCdpfO8cMsvKlsw== -------------------------------------------------------------------------------- /test/otherclient/client.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/otherclient/client.key -------------------------------------------------------------------------------- /test/servers/0/ltsig.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/0/ltsig.key.pub -------------------------------------------------------------------------------- /test/servers/0/noise.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/0/noise.key.pub -------------------------------------------------------------------------------- /test/servers/1/ltsig.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/1/ltsig.key.pub -------------------------------------------------------------------------------- /test/servers/1/noise.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/1/noise.key.pub -------------------------------------------------------------------------------- /test/servers/2/ltsig.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/2/ltsig.key.pub -------------------------------------------------------------------------------- /test/servers/2/noise.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/2/noise.key.pub -------------------------------------------------------------------------------- /test/servers/3/ltsig.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/3/ltsig.key.pub -------------------------------------------------------------------------------- /test/servers/3/noise.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/3/noise.key.pub -------------------------------------------------------------------------------- /test/servers/4/ltsig.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/4/ltsig.key.pub -------------------------------------------------------------------------------- /test/servers/4/noise.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/test/servers/4/noise.key.pub -------------------------------------------------------------------------------- /server/seccomp/musl-1.2.5.bpf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/server/seccomp/musl-1.2.5.bpf -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "server/cc-runtime"] 2 | path = server/cc-runtime 3 | url = https://codeberg.org/osdev/cc-runtime 4 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/klutshnikd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/klutshnikd -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/kltsk: -------------------------------------------------------------------------------- 1 | kltsk-eJ/iA0ow1jZxpFyVzE6ZNQ6Fz7+sD9ic+UCixQGwAnuzaHViYh06c0KCToEh2tuCHSN14X9DCdpfO8cMsvKlsw== -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/client.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/client.key -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/client.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/client.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/0/ltsig.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/0/ltsig.key -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/0/noise.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/0/noise.key -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/0/server.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/0/server.der -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/1/ltsig.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/1/ltsig.key -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/1/noise.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/1/noise.key -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/1/server.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/1/server.der -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/2/ltsig.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/2/ltsig.key -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/2/noise.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/2/noise.key -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/2/server.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/2/server.der -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/3/ltsig.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/3/ltsig.key -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/3/noise.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/3/noise.key -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/3/server.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/3/server.der -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/4/ltsig.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/4/ltsig.key -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/4/noise.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/4/noise.key -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/4/server.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/4/server.der -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/otherclient/client.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/otherclient/client.key -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/0/ltsig.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/0/ltsig.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/0/noise.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/0/noise.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/1/ltsig.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/1/ltsig.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/1/noise.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/1/noise.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/2/ltsig.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/2/ltsig.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/2/noise.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/2/noise.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/3/ltsig.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/3/ltsig.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/3/noise.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/3/noise.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/4/ltsig.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/4/ltsig.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/4/noise.key.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stef/klutshnik/master/images/klutshnik-sbox-rpi/input/test/servers/4/noise.key.pub -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/setup_init.sh: -------------------------------------------------------------------------------- 1 | #!/sbin/openrc-run 2 | # shellcheck shell=ash 3 | 4 | depend() { 5 | need localmount 6 | need networking 7 | } 8 | 9 | start() { 10 | klutshnik-setup 11 | } 12 | -------------------------------------------------------------------------------- /utils.h: -------------------------------------------------------------------------------- 1 | #ifndef KLUTSHNIK_UTILS_H 2 | #define KLUTSHNIK_UTILS_H 3 | 4 | #include 5 | #include 6 | 7 | void dump(const uint8_t *p, const size_t len, const char* msg, ...); 8 | void fail(char* msg, ...); 9 | 10 | #endif // KLUTSHNIK_UTILS_H 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | .arch 3 | *.pdf 4 | .zshhistory 5 | libklutshnik.so 6 | libklutshnik.a 7 | libklutshnik.pc 8 | __pycache__ 9 | *.org 10 | prez/ 11 | server/.zig-cache/ 12 | server/zig-out/ 13 | todo 14 | urls 15 | docs/ 16 | test/servers/*/log 17 | man/*.1 18 | man/*.5 19 | test/otherclient/keystore 20 | man/*.html 21 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/stages/90/50-compress.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | colour_echo ">> Compress images" 4 | # copy final image 5 | mkdir -p ${OUTPUT_PATH} 6 | zstd --ultra -22 -c ${IMAGE_PATH}/sdcard.img >${OUTPUT_PATH}/${IMG_NAME}.img.zst 7 | zstd --ultra -22 -c ${IMAGE_PATH}/rootfs.ext4 >${OUTPUT_PATH}/${IMG_NAME}_update.img.gz 8 | -------------------------------------------------------------------------------- /libklutshnik.pc0: -------------------------------------------------------------------------------- 1 | includedir=${prefix}/include 2 | 3 | Name: liboprf 4 | Description: implementation of OPRF (RFC9497) including (updatable) threshold variant 5 | Version: 0.7.1 6 | Cflags: -I${includedir}/oprf -I${includedir}/oprf/noiseXK/ -I${includedir}/oprf/noiseXK/karmel -I${includedir}/oprf/noiseXK/karmel/minimal 7 | Libs: -loprf 8 | -------------------------------------------------------------------------------- /test/easy-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd servers || exit 1 4 | rm -rf ./*/data/[0-9a-f]* 5 | ORACLE_STRACE=1 ./start-servers.sh & 6 | SERVERS_PID=$! 7 | cd .. 8 | ./test.sh 9 | klutshnik delete "keyid1" 5 | 6 | int stream_encrypt(const int infd, 7 | const int outfd, 8 | const uint8_t dek[crypto_secretbox_KEYBYTES]); 9 | int stream_decrypt(const int infd, 10 | const int outfd, 11 | const uint8_t dek[crypto_secretbox_KEYBYTES]); 12 | #endif // STREAMCRYPT_H 13 | -------------------------------------------------------------------------------- /test/servers/authorized_keys: -------------------------------------------------------------------------------- 1 | 8uH0+rR5KNdbJPr7+ARObHPEu4V/d6qqqDxhesjl2cihAAjmVMwvcbB+LhQvO7AF7BQW92p+xQPbFhqCoX8vNA== 2 | zy9ceExzhXB8zK9FQwv7joZsVXTfI2p+DEMZYyG96ukLdq7mJMyZk5lje0WF6OYaHC/CCJdABfh8rbGe3JtqBQ== 3 | zQTzmBGRHQEBhOfOBN3QYcs2qLCoU4F3zwrwTeBsDFTFjYU8r9y8MWMPOtBc8U995bACnP/JQy4l2/Ioh/IlIA== 4 | 4cBhEnYZOKcacdAHyjgU57wdGAWi2WCx0cnNmrjYb4DbBdVPrm6mEwtCZN2RvTlQcUmG5+F06X3H9K0nbjTYZA== 5 | 7i1i4coNfEuagd6liQ5mXPPzgUdMlEQs3w7Yf12/WN5BS+LPpwP+99nD4yjXkpEBrHX7EeQso9jABAR3ujW1Aw== 6 | -------------------------------------------------------------------------------- /server/src/utils.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const warn = std.debug.print; 3 | 4 | pub fn hexdump(buf: []const u8) void { 5 | for (buf) |C| { 6 | warn("{x:0>2}", .{C}); 7 | } 8 | warn("\n", .{}); 9 | } 10 | 11 | 12 | pub fn dir_exists(path: []const u8) bool { 13 | var cwd = std.fs.cwd(); 14 | const args: std.fs.Dir.OpenOptions = undefined; 15 | var dir = cwd.openDir(path, args) catch return false; 16 | dir.close(); 17 | return true; 18 | } 19 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/init.sh: -------------------------------------------------------------------------------- 1 | #!/sbin/openrc-run 2 | # shellcheck shell=ash 3 | # shellcheck disable=SC2034 4 | 5 | command="/usr/bin/sbox.sh" 6 | command_args="/usr/bin/klutshnikd /etc/klutshnik/config /etc/klutshnik/klutshnikd.bpf" 7 | pidfile="/var/run/klutshnikd.pid" 8 | command_background=true 9 | command_user="klutshnik:klutshnik" 10 | output_log="/data/klutshnik/log" 11 | error_log="/data/klutshnik/err" 12 | 13 | depend() { 14 | use logger 15 | need net 16 | need klutshnik-setup 17 | } 18 | -------------------------------------------------------------------------------- /website/makefile: -------------------------------------------------------------------------------- 1 | HTMLS=index.html code.html docs.html servers.html client_install.html server_install.html device_install.html faq.html 2 | 3 | all: $(HTMLS) manpages 4 | 5 | man: 6 | make -C ../man/ html 7 | cp ../man/*.html manpages 8 | 9 | upload: $(HTMLS) 10 | rsync -WPvr $(HTMLS) manpages ltximg keeper7keys.jpg klutshnik.info:/var/www/klutshnik.info 11 | 12 | clean: 13 | rm $(HTMLS) manpages/*.html 14 | 15 | %.html: %.org 16 | emacs -l ~/.emacs -Q --visit $< --batch --eval "(org-html-export-to-html)" 17 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/start-servers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | 3 | ORACLE=${ORACLE:-klutshnikd} 4 | PIDS="" 5 | 6 | cleanup() { 7 | echo killing klutshnikds ${PIDS} 8 | kill ${PIDS} 9 | exit 10 | } 11 | 12 | function start_server() { 13 | printf "starting klutshnikd %s\n" "$1" 14 | cd "$1" 15 | "$ORACLE" >log 2>&1 & 16 | PIDS="$PIDS $!" 17 | sleep 0.1 18 | cd - >/dev/null 19 | } 20 | 21 | #start_server 0 22 | start_server 1 23 | start_server 2 24 | start_server 3 25 | start_server 4 26 | 27 | trap "cleanup" INT TERM 28 | #tail -f 1/log 29 | while true; do sleep 1 ;done 30 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/stages/60/02-hardware.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo 'cdc_ether' >"$ROOTFS_PATH"/etc/modules-load.d/cdc_ether.conf 4 | echo "cdc_ether" >>"$ROOTFS_PATH"/etc/modules 5 | 6 | sed "/ttyAMA0/ittyAMA0 root:dialout 0660" -i "$ROOTFS_PATH"/etc/mdev.conf 7 | # enable hardware serial console 8 | echo 'dtoverlay=disable-bt' >>"$BOOTFS_PATH"/config.txt 9 | #echo 'dtoverlay=miniuart-bt' >>"$BOOTFS_PATH"/config.txt 10 | echo 'enable_uart=1' >>"$BOOTFS_PATH"/config.txt 11 | 12 | # start a login terminal on the serial port 13 | sed -e "s/#ttyS0/ttyAMA0/" -e "s/ttyS0/ttyAMA0/" -i "$ROOTFS_PATH"/etc/inittab 14 | -------------------------------------------------------------------------------- /python/README.org: -------------------------------------------------------------------------------- 1 | * klutshnik cli frontend 2 | 3 | Klutshnik is a system which encrypts data-at-rest: backups, files, 4 | archives - for you or your group. Yawn, even PGP^WAge can do 5 | that. Yes, but it cannot do regular key updates on an untrusted 6 | storage, providing post-compromise security (PCS) or forward secrecy 7 | (FS). And the best part is, the encryption key is shared in a 8 | threshold setup, and never ever assembled, so chances of accidental 9 | leakage are 0. 10 | 11 | This package provides the CLI client for this system. For more information, pls 12 | see the man page at https://klutshnik.info/manpages/klutshnik.html 13 | -------------------------------------------------------------------------------- /test/servers/0/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBhTCCASugAwIBAgIURt1h20rXWGwyV5nuLDp2NBaXsgkwCgYIKoZIzj0EAwIw 3 | GDEWMBQGA1UEAwwNc3BoaW54IG9yYWNsZTAeFw0yMDA5MjkyMTI5MDBaFw0yMTA5 4 | MjQyMTI5MDBaMBgxFjAUBgNVBAMMDXNwaGlueCBvcmFjbGUwWTATBgcqhkjOPQIB 5 | BggqhkjOPQMBBwNCAATPl01K0Nuxm4wZaYzS4AvaXy4pIG96Zk5XC1o0TmkdnNPb 6 | kgSUm6dx1OVvx3u8kVGRHYfgC7C4I414W2v41Hb4o1MwUTAdBgNVHQ4EFgQUtpha 7 | TRgMR7SeM7gYPKoq8L874tcwHwYDVR0jBBgwFoAUtphaTRgMR7SeM7gYPKoq8L87 8 | 4tcwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAnN1Y9WDfVW6f 9 | slgOnPs8eQdyoqA7S/rFf9wE/ZxR4tECICfCYMKpIRMYPEk2C+kqoJueB/JVdGKh 10 | pYxdMvjx8bsj 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /test/servers/1/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBhTCCASugAwIBAgIURt1h20rXWGwyV5nuLDp2NBaXsgkwCgYIKoZIzj0EAwIw 3 | GDEWMBQGA1UEAwwNc3BoaW54IG9yYWNsZTAeFw0yMDA5MjkyMTI5MDBaFw0yMTA5 4 | MjQyMTI5MDBaMBgxFjAUBgNVBAMMDXNwaGlueCBvcmFjbGUwWTATBgcqhkjOPQIB 5 | BggqhkjOPQMBBwNCAATPl01K0Nuxm4wZaYzS4AvaXy4pIG96Zk5XC1o0TmkdnNPb 6 | kgSUm6dx1OVvx3u8kVGRHYfgC7C4I414W2v41Hb4o1MwUTAdBgNVHQ4EFgQUtpha 7 | TRgMR7SeM7gYPKoq8L874tcwHwYDVR0jBBgwFoAUtphaTRgMR7SeM7gYPKoq8L87 8 | 4tcwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAnN1Y9WDfVW6f 9 | slgOnPs8eQdyoqA7S/rFf9wE/ZxR4tECICfCYMKpIRMYPEk2C+kqoJueB/JVdGKh 10 | pYxdMvjx8bsj 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /test/servers/2/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBhTCCASugAwIBAgIURt1h20rXWGwyV5nuLDp2NBaXsgkwCgYIKoZIzj0EAwIw 3 | GDEWMBQGA1UEAwwNc3BoaW54IG9yYWNsZTAeFw0yMDA5MjkyMTI5MDBaFw0yMTA5 4 | MjQyMTI5MDBaMBgxFjAUBgNVBAMMDXNwaGlueCBvcmFjbGUwWTATBgcqhkjOPQIB 5 | BggqhkjOPQMBBwNCAATPl01K0Nuxm4wZaYzS4AvaXy4pIG96Zk5XC1o0TmkdnNPb 6 | kgSUm6dx1OVvx3u8kVGRHYfgC7C4I414W2v41Hb4o1MwUTAdBgNVHQ4EFgQUtpha 7 | TRgMR7SeM7gYPKoq8L874tcwHwYDVR0jBBgwFoAUtphaTRgMR7SeM7gYPKoq8L87 8 | 4tcwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAnN1Y9WDfVW6f 9 | slgOnPs8eQdyoqA7S/rFf9wE/ZxR4tECICfCYMKpIRMYPEk2C+kqoJueB/JVdGKh 10 | pYxdMvjx8bsj 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /test/servers/3/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBhTCCASugAwIBAgIURt1h20rXWGwyV5nuLDp2NBaXsgkwCgYIKoZIzj0EAwIw 3 | GDEWMBQGA1UEAwwNc3BoaW54IG9yYWNsZTAeFw0yMDA5MjkyMTI5MDBaFw0yMTA5 4 | MjQyMTI5MDBaMBgxFjAUBgNVBAMMDXNwaGlueCBvcmFjbGUwWTATBgcqhkjOPQIB 5 | BggqhkjOPQMBBwNCAATPl01K0Nuxm4wZaYzS4AvaXy4pIG96Zk5XC1o0TmkdnNPb 6 | kgSUm6dx1OVvx3u8kVGRHYfgC7C4I414W2v41Hb4o1MwUTAdBgNVHQ4EFgQUtpha 7 | TRgMR7SeM7gYPKoq8L874tcwHwYDVR0jBBgwFoAUtphaTRgMR7SeM7gYPKoq8L87 8 | 4tcwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAnN1Y9WDfVW6f 9 | slgOnPs8eQdyoqA7S/rFf9wE/ZxR4tECICfCYMKpIRMYPEk2C+kqoJueB/JVdGKh 10 | pYxdMvjx8bsj 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /test/servers/4/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBhTCCASugAwIBAgIURt1h20rXWGwyV5nuLDp2NBaXsgkwCgYIKoZIzj0EAwIw 3 | GDEWMBQGA1UEAwwNc3BoaW54IG9yYWNsZTAeFw0yMDA5MjkyMTI5MDBaFw0yMTA5 4 | MjQyMTI5MDBaMBgxFjAUBgNVBAMMDXNwaGlueCBvcmFjbGUwWTATBgcqhkjOPQIB 5 | BggqhkjOPQMBBwNCAATPl01K0Nuxm4wZaYzS4AvaXy4pIG96Zk5XC1o0TmkdnNPb 6 | kgSUm6dx1OVvx3u8kVGRHYfgC7C4I414W2v41Hb4o1MwUTAdBgNVHQ4EFgQUtpha 7 | TRgMR7SeM7gYPKoq8L874tcwHwYDVR0jBBgwFoAUtphaTRgMR7SeM7gYPKoq8L87 8 | 4tcwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAnN1Y9WDfVW6f 9 | slgOnPs8eQdyoqA7S/rFf9wE/ZxR4tECICfCYMKpIRMYPEk2C+kqoJueB/JVdGKh 10 | pYxdMvjx8bsj 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/0/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBhTCCASugAwIBAgIURt1h20rXWGwyV5nuLDp2NBaXsgkwCgYIKoZIzj0EAwIw 3 | GDEWMBQGA1UEAwwNc3BoaW54IG9yYWNsZTAeFw0yMDA5MjkyMTI5MDBaFw0yMTA5 4 | MjQyMTI5MDBaMBgxFjAUBgNVBAMMDXNwaGlueCBvcmFjbGUwWTATBgcqhkjOPQIB 5 | BggqhkjOPQMBBwNCAATPl01K0Nuxm4wZaYzS4AvaXy4pIG96Zk5XC1o0TmkdnNPb 6 | kgSUm6dx1OVvx3u8kVGRHYfgC7C4I414W2v41Hb4o1MwUTAdBgNVHQ4EFgQUtpha 7 | TRgMR7SeM7gYPKoq8L874tcwHwYDVR0jBBgwFoAUtphaTRgMR7SeM7gYPKoq8L87 8 | 4tcwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAnN1Y9WDfVW6f 9 | slgOnPs8eQdyoqA7S/rFf9wE/ZxR4tECICfCYMKpIRMYPEk2C+kqoJueB/JVdGKh 10 | pYxdMvjx8bsj 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/1/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBhTCCASugAwIBAgIURt1h20rXWGwyV5nuLDp2NBaXsgkwCgYIKoZIzj0EAwIw 3 | GDEWMBQGA1UEAwwNc3BoaW54IG9yYWNsZTAeFw0yMDA5MjkyMTI5MDBaFw0yMTA5 4 | MjQyMTI5MDBaMBgxFjAUBgNVBAMMDXNwaGlueCBvcmFjbGUwWTATBgcqhkjOPQIB 5 | BggqhkjOPQMBBwNCAATPl01K0Nuxm4wZaYzS4AvaXy4pIG96Zk5XC1o0TmkdnNPb 6 | kgSUm6dx1OVvx3u8kVGRHYfgC7C4I414W2v41Hb4o1MwUTAdBgNVHQ4EFgQUtpha 7 | TRgMR7SeM7gYPKoq8L874tcwHwYDVR0jBBgwFoAUtphaTRgMR7SeM7gYPKoq8L87 8 | 4tcwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAnN1Y9WDfVW6f 9 | slgOnPs8eQdyoqA7S/rFf9wE/ZxR4tECICfCYMKpIRMYPEk2C+kqoJueB/JVdGKh 10 | pYxdMvjx8bsj 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/2/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBhTCCASugAwIBAgIURt1h20rXWGwyV5nuLDp2NBaXsgkwCgYIKoZIzj0EAwIw 3 | GDEWMBQGA1UEAwwNc3BoaW54IG9yYWNsZTAeFw0yMDA5MjkyMTI5MDBaFw0yMTA5 4 | MjQyMTI5MDBaMBgxFjAUBgNVBAMMDXNwaGlueCBvcmFjbGUwWTATBgcqhkjOPQIB 5 | BggqhkjOPQMBBwNCAATPl01K0Nuxm4wZaYzS4AvaXy4pIG96Zk5XC1o0TmkdnNPb 6 | kgSUm6dx1OVvx3u8kVGRHYfgC7C4I414W2v41Hb4o1MwUTAdBgNVHQ4EFgQUtpha 7 | TRgMR7SeM7gYPKoq8L874tcwHwYDVR0jBBgwFoAUtphaTRgMR7SeM7gYPKoq8L87 8 | 4tcwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAnN1Y9WDfVW6f 9 | slgOnPs8eQdyoqA7S/rFf9wE/ZxR4tECICfCYMKpIRMYPEk2C+kqoJueB/JVdGKh 10 | pYxdMvjx8bsj 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/3/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBhTCCASugAwIBAgIURt1h20rXWGwyV5nuLDp2NBaXsgkwCgYIKoZIzj0EAwIw 3 | GDEWMBQGA1UEAwwNc3BoaW54IG9yYWNsZTAeFw0yMDA5MjkyMTI5MDBaFw0yMTA5 4 | MjQyMTI5MDBaMBgxFjAUBgNVBAMMDXNwaGlueCBvcmFjbGUwWTATBgcqhkjOPQIB 5 | BggqhkjOPQMBBwNCAATPl01K0Nuxm4wZaYzS4AvaXy4pIG96Zk5XC1o0TmkdnNPb 6 | kgSUm6dx1OVvx3u8kVGRHYfgC7C4I414W2v41Hb4o1MwUTAdBgNVHQ4EFgQUtpha 7 | TRgMR7SeM7gYPKoq8L874tcwHwYDVR0jBBgwFoAUtphaTRgMR7SeM7gYPKoq8L87 8 | 4tcwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAnN1Y9WDfVW6f 9 | slgOnPs8eQdyoqA7S/rFf9wE/ZxR4tECICfCYMKpIRMYPEk2C+kqoJueB/JVdGKh 10 | pYxdMvjx8bsj 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/4/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBhTCCASugAwIBAgIURt1h20rXWGwyV5nuLDp2NBaXsgkwCgYIKoZIzj0EAwIw 3 | GDEWMBQGA1UEAwwNc3BoaW54IG9yYWNsZTAeFw0yMDA5MjkyMTI5MDBaFw0yMTA5 4 | MjQyMTI5MDBaMBgxFjAUBgNVBAMMDXNwaGlueCBvcmFjbGUwWTATBgcqhkjOPQIB 5 | BggqhkjOPQMBBwNCAATPl01K0Nuxm4wZaYzS4AvaXy4pIG96Zk5XC1o0TmkdnNPb 6 | kgSUm6dx1OVvx3u8kVGRHYfgC7C4I414W2v41Hb4o1MwUTAdBgNVHQ4EFgQUtpha 7 | TRgMR7SeM7gYPKoq8L874tcwHwYDVR0jBBgwFoAUtphaTRgMR7SeM7gYPKoq8L87 8 | 4tcwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAnN1Y9WDfVW6f 9 | slgOnPs8eQdyoqA7S/rFf9wE/ZxR4tECICfCYMKpIRMYPEk2C+kqoJueB/JVdGKh 10 | pYxdMvjx8bsj 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/authorized_keys_template: -------------------------------------------------------------------------------- 1 | 8uH0+rR5KNdbJPr7+ARObHPEu4V/d6qqqDxhesjl2cihAAjmVMwvcbB+LhQvO7AF7BQW92p+xQPbFhqCoX8vNA== 2 | zy9ceExzhXB8zK9FQwv7joZsVXTfI2p+DEMZYyG96ukLdq7mJMyZk5lje0WF6OYaHC/CCJdABfh8rbGe3JtqBQ== 3 | zQTzmBGRHQEBhOfOBN3QYcs2qLCoU4F3zwrwTeBsDFTFjYU8r9y8MWMPOtBc8U995bACnP/JQy4l2/Ioh/IlIA== 4 | 4cBhEnYZOKcacdAHyjgU57wdGAWi2WCx0cnNmrjYb4DbBdVPrm6mEwtCZN2RvTlQcUmG5+F06X3H9K0nbjTYZA== 5 | 7i1i4coNfEuagd6liQ5mXPPzgUdMlEQs3w7Yf12/WN5BS+LPpwP+99nD4yjXkpEBrHX7EeQso9jABAR3ujW1Aw== 6 | xY8hDROTNIhOczJTCt7+2o4+O387/w9iJjtz0yJKf5m6cHF5M/ampdApSyr/FRsK+3vW91p50MUYqxmIxw8pLw== 7 | iMo2mePzGBtTKXEEVnMEwXkr2bXkpRfZKFuzW0EOJlka7+f9va5KO+akyg7w9I+4g3elkTnsMfXtXzhSRK2OVw== 8 | -------------------------------------------------------------------------------- /server/src/workaround.h: -------------------------------------------------------------------------------- 1 | #ifndef workaround_h 2 | #define workaround_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | STP_DKG_PeerState* new_stp_dkg_peerstate(void); 10 | void extract_stp_dkg_share(const STP_DKG_PeerState *ctx, uint8_t share[TOPRF_Share_BYTES*2]); 11 | void del_stp_dkg_peerstate(STP_DKG_PeerState **peer); 12 | 13 | TOPRF_Update_PeerState* new_toprf_update_peerstate(void); 14 | void toprf_update_peerstate_set_n(TOPRF_Update_PeerState *peer, const uint8_t n); 15 | void toprf_update_peerstate_set_t(TOPRF_Update_PeerState *peer, const uint8_t t); 16 | void del_toprf_update_peerstate(TOPRF_Update_PeerState **peer); 17 | #endif // workaround_h 18 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/build.env: -------------------------------------------------------------------------------- 1 | DEFAULT_HOSTNAME=klutshnik-rpi 2 | DEFAULT_ROOT_PASSWORD=klutshnik 3 | OVERLAY=true 4 | #ARCH=armv7 5 | #ARCH=aarch64 6 | SIZE_ROOT_FS=250M 7 | SIZE_ROOT_PART=250M 8 | SIZE_DATA=500M 9 | #UBOOT_PACKAGE=silent 10 | # keep all modules with * 11 | #DEFAULT_KERNEL_MODULES=* 12 | ADDITIONAL_KERNEL_MODULES=cdc_ether usbnet mii nft_chain_nat xt_REDIRECT nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 xt_tcpudp nft_compat x_tables nf_tables nfnetlink overlay 13 | # default command line has console on serial0 14 | #CMDLINE=console=tty1 root=/dev/root rootfstype=ext4 fsck.repair=yes ro rootwait quiet 15 | CMDLINE=console=serial0,115200 console=tty1 root=/dev/root rootfstype=ext4 fsck.repair=yes ro rootwait 16 | CACHE_PATH=/input/build_cache 17 | -------------------------------------------------------------------------------- /utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int debug = 0; 7 | FILE* log_file=NULL; 8 | 9 | void dump(const uint8_t *p, const size_t len, const char* msg, ...) { 10 | FILE* lf = stderr; 11 | if(!debug) return; 12 | if(log_file!=NULL) lf = log_file; 13 | va_list args; 14 | va_start(args, msg); 15 | vfprintf(lf, msg, args); 16 | va_end(args); 17 | fprintf(lf," "); 18 | for(size_t i=0;ilog 2>&1 & 17 | else 18 | "$ORACLE" >log 2>&1 & 19 | fi 20 | PIDS="$PIDS $!" 21 | cd .. 22 | sleep 0.1 23 | } 24 | 25 | start_server 0 26 | start_server 1 27 | start_server 2 28 | start_server 3 29 | start_server 4 30 | 31 | trap "cleanup" INT TERM QUIT 32 | if [ -n "$ORACLE_TAIL" ]; then 33 | tail -f "$ORACLE_TAIL"/log 34 | else 35 | while true; do sleep 1 ;done 36 | fi 37 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | if [ ! -d klutshnik ]; then 4 | git clone https://github.com/stef/klutshnik 5 | else 6 | cd klutshnik 7 | git pull origin master 8 | cd .. 9 | fi 10 | cd klutshnik/server 11 | if [ "$ARCH" = "armv7" ]; then 12 | zig build -Doptimize=ReleaseSafe -freference-trace -Dpie=true -Drelro=true -Dsystem_libs=false -Dtarget=arm-linux 13 | else 14 | if [ "$ARCH" != "aarch64" ]; then 15 | echo 'please set $ARCH to either armv7 or aarch64' 16 | exit 1 17 | fi 18 | zig build -Doptimize=ReleaseSafe -freference-trace -Dpie=true -Drelro=true -Dsystem_libs=false -Dtarget=aarch64-linux 19 | fi 20 | cp zig-out/bin/klutshnikd ../../input 21 | git rev-parse --short HEAD >../../input/klutshnik-rev 22 | cd ../../ 23 | 24 | docker run --rm -it -v "$PWD"/input:/input -v "$PWD"/output:/output -e ARCH --env-file build.env ghcr.io/raspi-alpine/builder 25 | -------------------------------------------------------------------------------- /server/seccomp/makefile: -------------------------------------------------------------------------------- 1 | PWD=$(shell pwd) 2 | 3 | target.bpf: constants.json target.seccomp 4 | minijail/tools/compile_seccomp_policy.py target.seccomp target.bpf 5 | 6 | minijail: 7 | git clone https://android.googlesource.com/platform/external/minijail/ minijail 8 | 9 | constants.json: minijail 10 | make OUT=${PWD}/minijail -C minijail constants.json 11 | cp minijail/constants.json . 12 | 13 | target.strace: ../zig-out/bin/klutshnikd 14 | cd ../../test && ORACLE_STRACE=1 ./easy-test.sh 15 | cp ../../test/servers/1/strace.log ./target.strace 16 | 17 | target.seccomp: target.strace 18 | minijail/tools/generate_seccomp_policy.py target.strace >target.seccomp 19 | 20 | ../zig-out/bin/klutshnikd: 21 | cd .. && zig build -Doptimize=Debug -freference-trace=11 -Dpie=true -Drelro=true -Dsystem_libs=false 22 | 23 | clean: 24 | rm -rf minijail constants.json target.strace target.seccomp target.bpf ../../test/servers/1/strace.log 25 | -------------------------------------------------------------------------------- /python/klutshnik/cfg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # SPDX-FileCopyrightText: 2023, Marsiske Stefan 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | import os, tomlkit 6 | 7 | def split_by_n(obj, n): 8 | # src https://stackoverflow.com/questions/9475241/split-string-every-nth-character 9 | return [obj[i:i+n] for i in range(0, len(obj), n)] 10 | 11 | def getcfg(name, cwd="."): 12 | paths=[ 13 | # read global cfg 14 | f'/etc/{name}/config', 15 | # update with per-user configs 16 | os.path.expanduser(f"~/.{name}rc"), 17 | os.path.expanduser(f"~/.config/{name}/config"), 18 | # over-ride with local directory config 19 | os.path.expanduser('/'.join([cwd,f"{name}.cfg"])) 20 | ] 21 | config = tomlkit.toml_document.TOMLDocument() 22 | for path in paths: 23 | try: 24 | with open(path, "rb") as f: 25 | data = tomlkit.load(f) 26 | except FileNotFoundError: 27 | continue 28 | config.update(data) 29 | return config 30 | -------------------------------------------------------------------------------- /man/makefile: -------------------------------------------------------------------------------- 1 | all: klutshnik.1 klutshnikd.1 klutshnik.cfg.5 klutshnikd.cfg.5 2 | 3 | html: klutshnik.html klutshnikd.html klutshnik.cfg.html klutshnikd.cfg.html 4 | 5 | install: $(DESTDIR)$(PREFIX)/share/man/man1/klutshnik.1 $(DESTDIR)$(PREFIX)/share/man/man1/klutshnikd.1 \ 6 | $(DESTDIR)$(PREFIX)/share/man/man5/klutshnik.cfg.5 $(DESTDIR)$(PREFIX)/share/man/man5/klutshnikd.cfg.5 \ 7 | 8 | clean: 9 | rm -f *.1 *.5 10 | 11 | %.html: %.md 12 | cmark -t html $< >>$@ 13 | 14 | %.1: %.md 15 | cp $(@:.1=.head) $@ 16 | cmark -t man $< >>$@ 17 | 18 | %.5: %.md 19 | cp $(@:.5=.head) $@ 20 | cmark -t man $< >>$@ 21 | 22 | $(DESTDIR)$(PREFIX)/share/man/man1/klutshnik.1: 23 | mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1/ 24 | cp $< $@ 25 | $(DESTDIR)$(PREFIX)/share/man/man1/klutshnikd.1: 26 | mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1/ 27 | cp $< $@ 28 | $(DESTDIR)$(PREFIX)/share/man/man5/klutshnik.cfg.5: 29 | mkdir -p $(DESTDIR)$(PREFIX)/share/man/man5/ 30 | cp $< $@ 31 | $(DESTDIR)$(PREFIX)/share/man/man5/klutshnikd.cfg.5: 32 | mkdir -p $(DESTDIR)$(PREFIX)/share/man/man5/ 33 | cp $< $@ 34 | 35 | -------------------------------------------------------------------------------- /test/servers/2/klutshnikd.cfg: -------------------------------------------------------------------------------- 1 | # config is read in this order from the following locations, later ones 2 | # overriding settings from the earlier ones: 3 | # - /etc/klutshnikd/config 4 | # - ~/.config/klutshnikd/config 5 | # - ~/.klutshnikdrc 6 | # - ./klutshnikd.cfg 7 | 8 | [server] 9 | # the ipv4 address the server is listening on 10 | #address="127.0.0.1" 11 | 12 | # ssl key 13 | ssl_key="server.der" 14 | 15 | # ssl cert 16 | ssl_cert="cert.pem" 17 | 18 | # the port on which the server is listening, use 443 if available, so that 19 | # the oracle can be accessed from behind tight firewalls, default: 8080 20 | port=23002 21 | 22 | # tcp connection timeouts, increase in case you have bad networks, with the 23 | # caveat that this might lead to easier resource exhaustion - blocking all 24 | # workers. 25 | timeout=300 26 | 27 | # the root directory where all data is stored, default: /var/lib/sphinx 28 | datadir="data" 29 | 30 | # how many worker processes can run in parallel 31 | # max_kids=5 32 | 33 | # whether to produce some output 34 | verbose=true 35 | 36 | record_salt = "some nacl some chilli" 37 | authorized_keys="../authorized_keys" 38 | -------------------------------------------------------------------------------- /test/servers/3/klutshnikd.cfg: -------------------------------------------------------------------------------- 1 | # config is read in this order from the following locations, later ones 2 | # overriding settings from the earlier ones: 3 | # - /etc/klutshnikd/config 4 | # - ~/.config/klutshnikd/config 5 | # - ~/.klutshnikdrc 6 | # - ./klutshnikd.cfg 7 | 8 | [server] 9 | # the ipv4 address the server is listening on 10 | #address="127.0.0.1" 11 | 12 | # ssl key 13 | ssl_key="server.der" 14 | 15 | # ssl cert 16 | ssl_cert="cert.pem" 17 | 18 | # the port on which the server is listening, use 443 if available, so that 19 | # the oracle can be accessed from behind tight firewalls, default: 8080 20 | port=23003 21 | 22 | # tcp connection timeouts, increase in case you have bad networks, with the 23 | # caveat that this might lead to easier resource exhaustion - blocking all 24 | # workers. 25 | timeout=300 26 | 27 | # the root directory where all data is stored, default: /var/lib/sphinx 28 | datadir="data" 29 | 30 | # how many worker processes can run in parallel 31 | # max_kids=5 32 | 33 | # whether to produce some output 34 | verbose=true 35 | 36 | record_salt = "some nacl some chilli" 37 | authorized_keys="../authorized_keys" 38 | -------------------------------------------------------------------------------- /test/servers/4/klutshnikd.cfg: -------------------------------------------------------------------------------- 1 | # config is read in this order from the following locations, later ones 2 | # overriding settings from the earlier ones: 3 | # - /etc/klutshnikd/config 4 | # - ~/.config/klutshnikd/config 5 | # - ~/.klutshnikdrc 6 | # - ./klutshnikd.cfg 7 | 8 | [server] 9 | # the ipv4 address the server is listening on 10 | #address="127.0.0.1" 11 | 12 | # ssl key 13 | ssl_key="server.der" 14 | 15 | # ssl cert 16 | ssl_cert="cert.pem" 17 | 18 | # the port on which the server is listening, use 443 if available, so that 19 | # the oracle can be accessed from behind tight firewalls, default: 8080 20 | port=23004 21 | 22 | # tcp connection timeouts, increase in case you have bad networks, with the 23 | # caveat that this might lead to easier resource exhaustion - blocking all 24 | # workers. 25 | timeout=300 26 | 27 | # the root directory where all data is stored, default: /var/lib/sphinx 28 | datadir="data" 29 | 30 | # how many worker processes can run in parallel 31 | # max_kids=5 32 | 33 | # whether to produce some output 34 | verbose=true 35 | 36 | record_salt = "some nacl some chilli" 37 | authorized_keys="../authorized_keys" 38 | -------------------------------------------------------------------------------- /test/servers/1/klutshnikd.cfg: -------------------------------------------------------------------------------- 1 | # config is read in this order from the following locations, later ones 2 | # overriding settings from the earlier ones: 3 | # - /etc/klutshnikd/config 4 | # - ~/.config/klutshnikd/config 5 | # - ~/.klutshnikdrc 6 | # - ./klutshnikd.cfg 7 | 8 | [server] 9 | # the ipv4 address the server is listening on 10 | #address="127.0.0.1" 11 | 12 | # ssl key 13 | ssl_key="server.der" 14 | 15 | # ssl cert 16 | ssl_cert="cert.pem" 17 | 18 | # the port on which the server is listening, use 443 if available, so that 19 | # the oracle can be accessed from behind tight firewalls, default: 8080 20 | port=23001 21 | 22 | # tcp connection timeouts, increase in case you have bad networks, with the 23 | # caveat that this might lead to easier resource exhaustion - blocking all 24 | # workers. 25 | timeout=300 26 | 27 | # the root directory where all data is stored, default: /var/lib/sphinx 28 | datadir="data" 29 | 30 | # how many worker processes can run in parallel 31 | # max_kids=5 32 | 33 | # whether to produce some output 34 | verbose=true 35 | 36 | record_salt = "some natrium-chloride and some chilli" 37 | authorized_keys="../authorized_keys" 38 | -------------------------------------------------------------------------------- /test/servers/0/klutshnikd.cfg: -------------------------------------------------------------------------------- 1 | # config is read in this order from the following locations, later ones 2 | # overriding settings from the earlier ones: 3 | # - /etc/klutshnikd/config 4 | # - ~/.config/klutshnikd/config 5 | # - ~/.klutshnikdrc 6 | # - ./klutshnikd.cfg 7 | 8 | [server] 9 | # the ipv4 address the server is listening on 10 | #address="127.0.0.1" 11 | 12 | # ssl key 13 | ssl_key="server.der" 14 | 15 | # ssl cert 16 | ssl_cert="cert.pem" 17 | 18 | # the port on which the server is listening, use 443 if available, so that 19 | # the oracle can be accessed from behind tight firewalls, default: 8080 20 | port=23000 21 | 22 | # tcp connection timeouts, increase in case you have bad networks, with the 23 | # caveat that this might lead to easier resource exhaustion - blocking all 24 | # workers. 25 | timeout=300 26 | 27 | # the root directory where all data is stored, default: /var/lib/sphinx 28 | datadir="data" 29 | 30 | # how many worker processes can run in parallel 31 | # max_kids=5 32 | 33 | # whether to produce some output 34 | verbose=true 35 | 36 | record_salt = "some natrium-chloride and some chilli" 37 | 38 | authorized_keys="../authorized_keys" 39 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/2/klutshnik.cfg: -------------------------------------------------------------------------------- 1 | # config is read in this order from the following locations, later ones 2 | # overriding settings from the earlier ones: 3 | # - /etc/klutshnikd/config 4 | # - ~/.config/klutshnikd/config 5 | # - ~/.klutshnikdrc 6 | # - ./klutshnikd.cfg 7 | 8 | [server] 9 | # the ipv4 address the server is listening on 10 | #address="127.0.0.1" 11 | 12 | # ssl key 13 | ssl_key="server.der" 14 | 15 | # ssl cert 16 | ssl_cert="cert.pem" 17 | 18 | # the port on which the server is listening, use 443 if available, so that 19 | # the oracle can be accessed from behind tight firewalls, default: 8080 20 | port=23002 21 | 22 | # tcp connection timeouts, increase in case you have bad networks, with the 23 | # caveat that this might lead to easier resource exhaustion - blocking all 24 | # workers. 25 | timeout=100 26 | 27 | # the root directory where all data is stored, default: /var/lib/sphinx 28 | datadir="data" 29 | 30 | # how many worker processes can run in parallel 31 | # max_kids=5 32 | 33 | # whether to produce some output 34 | verbose=true 35 | 36 | record_salt = "some nacl some chilli" 37 | authorized_keys="../authorized_keys" 38 | ts_epsilon=300 39 | ltsigkey="ltsig.key" 40 | noisekey="noise.key" 41 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/3/klutshnik.cfg: -------------------------------------------------------------------------------- 1 | # config is read in this order from the following locations, later ones 2 | # overriding settings from the earlier ones: 3 | # - /etc/klutshnikd/config 4 | # - ~/.config/klutshnikd/config 5 | # - ~/.klutshnikdrc 6 | # - ./klutshnikd.cfg 7 | 8 | [server] 9 | # the ipv4 address the server is listening on 10 | #address="127.0.0.1" 11 | 12 | # ssl key 13 | ssl_key="server.der" 14 | 15 | # ssl cert 16 | ssl_cert="cert.pem" 17 | 18 | # the port on which the server is listening, use 443 if available, so that 19 | # the oracle can be accessed from behind tight firewalls, default: 8080 20 | port=23003 21 | 22 | # tcp connection timeouts, increase in case you have bad networks, with the 23 | # caveat that this might lead to easier resource exhaustion - blocking all 24 | # workers. 25 | timeout=100 26 | 27 | # the root directory where all data is stored, default: /var/lib/sphinx 28 | datadir="data" 29 | 30 | # how many worker processes can run in parallel 31 | # max_kids=5 32 | 33 | # whether to produce some output 34 | verbose=true 35 | 36 | record_salt = "some nacl some chilli" 37 | authorized_keys="../authorized_keys" 38 | ts_epsilon=300 39 | ltsigkey="ltsig.key" 40 | noisekey="noise.key" 41 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/4/klutshnik.cfg: -------------------------------------------------------------------------------- 1 | # config is read in this order from the following locations, later ones 2 | # overriding settings from the earlier ones: 3 | # - /etc/klutshnikd/config 4 | # - ~/.config/klutshnikd/config 5 | # - ~/.klutshnikdrc 6 | # - ./klutshnikd.cfg 7 | 8 | [server] 9 | # the ipv4 address the server is listening on 10 | #address="127.0.0.1" 11 | 12 | # ssl key 13 | ssl_key="server.der" 14 | 15 | # ssl cert 16 | ssl_cert="cert.pem" 17 | 18 | # the port on which the server is listening, use 443 if available, so that 19 | # the oracle can be accessed from behind tight firewalls, default: 8080 20 | port=23004 21 | 22 | # tcp connection timeouts, increase in case you have bad networks, with the 23 | # caveat that this might lead to easier resource exhaustion - blocking all 24 | # workers. 25 | timeout=100 26 | 27 | # the root directory where all data is stored, default: /var/lib/sphinx 28 | datadir="data" 29 | 30 | # how many worker processes can run in parallel 31 | # max_kids=5 32 | 33 | # whether to produce some output 34 | verbose=true 35 | 36 | record_salt = "some nacl some chilli" 37 | authorized_keys="../authorized_keys" 38 | ts_epsilon=300 39 | ltsigkey="ltsig.key" 40 | noisekey="noise.key" 41 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/1/klutshnik.cfg: -------------------------------------------------------------------------------- 1 | # config is read in this order from the following locations, later ones 2 | # overriding settings from the earlier ones: 3 | # - /etc/klutshnikd/config 4 | # - ~/.config/klutshnikd/config 5 | # - ~/.klutshnikdrc 6 | # - ./klutshnikd.cfg 7 | 8 | [server] 9 | # the ipv4 address the server is listening on 10 | #address="127.0.0.1" 11 | 12 | # ssl key 13 | ssl_key="server.der" 14 | 15 | # ssl cert 16 | ssl_cert="cert.pem" 17 | 18 | # the port on which the server is listening, use 443 if available, so that 19 | # the oracle can be accessed from behind tight firewalls, default: 8080 20 | port=23001 21 | 22 | # tcp connection timeouts, increase in case you have bad networks, with the 23 | # caveat that this might lead to easier resource exhaustion - blocking all 24 | # workers. 25 | timeout=100 26 | 27 | # the root directory where all data is stored, default: /var/lib/sphinx 28 | datadir="data" 29 | 30 | # how many worker processes can run in parallel 31 | # max_kids=5 32 | 33 | # whether to produce some output 34 | verbose=true 35 | 36 | record_salt = "some natrium-chloride and some chilli" 37 | authorized_keys="../authorized_keys" 38 | ts_epsilon=300 39 | ltsigkey="ltsig.key" 40 | noisekey="noise.key" 41 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/servers/0/klutshnik.cfg: -------------------------------------------------------------------------------- 1 | # config is read in this order from the following locations, later ones 2 | # overriding settings from the earlier ones: 3 | # - /etc/klutshnikd/config 4 | # - ~/.config/klutshnikd/config 5 | # - ~/.klutshnikdrc 6 | # - ./klutshnikd.cfg 7 | 8 | [server] 9 | # the ipv4 address the server is listening on 10 | #address="127.0.0.1" 11 | 12 | # ssl key 13 | ssl_key="server.der" 14 | 15 | # ssl cert 16 | ssl_cert="cert.pem" 17 | 18 | # the port on which the server is listening, use 443 if available, so that 19 | # the oracle can be accessed from behind tight firewalls, default: 8080 20 | port=23000 21 | 22 | # tcp connection timeouts, increase in case you have bad networks, with the 23 | # caveat that this might lead to easier resource exhaustion - blocking all 24 | # workers. 25 | timeout=100 26 | 27 | # the root directory where all data is stored, default: /var/lib/sphinx 28 | datadir="data" 29 | 30 | # how many worker processes can run in parallel 31 | # max_kids=5 32 | 33 | # whether to produce some output 34 | verbose=true 35 | 36 | record_salt = "some natrium-chloride and some chilli" 37 | 38 | authorized_keys="../authorized_keys" 39 | ts_epsilon=300 40 | ltsigkey="ltsig.key" 41 | noisekey="noise.key" 42 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/klutshnik.cfg_template: -------------------------------------------------------------------------------- 1 | # config is read in this order from the following locations, later ones 2 | # overriding settings from the earlier ones: 3 | # - /etc/klutshnikd/config 4 | # - ~/.config/klutshnikd/config 5 | # - ~/.klutshnikdrc 6 | # - ./klutshnikd.cfg 7 | 8 | [server] 9 | # the ipv4 address the server is listening on 10 | address="0.0.0.0" 11 | 12 | # ssl key 13 | ssl_key="/etc/klutshnik/key.pem" 14 | 15 | # ssl cert 16 | ssl_cert="/etc/klutshnik/cert.pem" 17 | 18 | # the port on which the server is listening, use 443 if available, so that 19 | # the oracle can be accessed from behind tight firewalls, default: 8080 20 | port=2323 21 | 22 | # tcp connection timeouts, increase in case you have bad networks, with the 23 | # caveat that this might lead to easier resource exhaustion - blocking all 24 | # workers. 25 | #timeout=3 26 | 27 | # the root directory where all data is stored, default: /var/lib/klutshnik 28 | datadir="/data/klutshnik" 29 | 30 | # how many worker processes can run in parallel 31 | # max_kids=5 32 | 33 | verbose=true 34 | record_salt = "some natrium-chloride and some chilli" 35 | authorized_keys="/etc/klutshnik/authorized_keys" 36 | ltsigkey="/etc//klutshnik/ltsig.key" 37 | noisekey="/etc/klutshnik/noise.key" 38 | -------------------------------------------------------------------------------- /server/src/workaround.c: -------------------------------------------------------------------------------- 1 | #include "oprf/stp-dkg.h" 2 | #include "oprf/toprf.h" 3 | #include "oprf/toprf-update.h" 4 | #include 5 | #include 6 | 7 | // zig cannot align data at 64Byte (or anything beyond 16 bytes really) 8 | // see https://github.com/ziglang/zig/issues/8452 9 | 10 | // thus we have to workaround this by allocating/freeing and accessing 11 | // the data in c which the zig cc backend (clang) handles correctly. 12 | STP_DKG_PeerState* new_stp_dkg_peerstate(void) { 13 | return aligned_alloc(64,sizeof(STP_DKG_PeerState)); 14 | } 15 | 16 | void extract_stp_dkg_share(const STP_DKG_PeerState *ctx, uint8_t share[TOPRF_Share_BYTES*2]) { 17 | memcpy(share, &ctx->share, TOPRF_Share_BYTES*2); 18 | } 19 | 20 | void del_stp_dkg_peerstate(STP_DKG_PeerState **peer) { 21 | if(*peer!=NULL) free(*peer); 22 | *peer = NULL; 23 | } 24 | 25 | TOPRF_Update_PeerState* new_toprf_update_peerstate(void) { 26 | return aligned_alloc(64,sizeof(TOPRF_Update_PeerState)); 27 | } 28 | 29 | void toprf_update_peerstate_set_n(TOPRF_Update_PeerState *peer, const uint8_t n) { 30 | peer->n = n; 31 | } 32 | 33 | void toprf_update_peerstate_set_t(TOPRF_Update_PeerState *peer, const uint8_t t) { 34 | peer->t = t; 35 | } 36 | 37 | void del_toprf_update_peerstate(TOPRF_Update_PeerState **peer) { 38 | if(*peer!=NULL) free(*peer); 39 | *peer = NULL; 40 | } 41 | -------------------------------------------------------------------------------- /test/otherclient/klutshnik.cfg: -------------------------------------------------------------------------------- 1 | [client] 2 | debug=true 3 | verbose=true 4 | threshold=2 5 | ltsigkey_path="client.key" 6 | ltsigpub="LTSIGPK-13lty/jQszJ1Xn5krTC2kltvPJDMqb4bqk3jgZxR430=" 7 | id_salt="some sodium and chilli" 8 | ts_epsilon=3 9 | keystore="keystore" 10 | 11 | [servers] 12 | [servers.zero] 13 | # address of server 14 | host="127.0.0.1" 15 | # port where server is running 16 | port=23000 17 | # public key of the server 18 | ssl_cert = "../servers/0/cert.pem" 19 | ltsigkey_path="../servers/zero.pub" 20 | [servers.eins] 21 | # address of server 22 | host="127.0.0.1" 23 | # port where server is running 24 | port=23001 25 | # public key of the server 26 | ssl_cert = "../servers/1/cert.pem" 27 | ltsigkey_path="../servers/eins.pub" 28 | [servers.zwei] 29 | # address of server 30 | host="127.0.0.1" 31 | # port where server is running 32 | port=23002 33 | # public key of the server 34 | ssl_cert = "../servers/2/cert.pem" 35 | ltsigkey_path="../servers/zwei.pub" 36 | [servers.drei] 37 | # address of server 38 | host="127.0.0.1" 39 | # port where server is running 40 | port=23003 41 | # public key of the server 42 | ssl_cert = "../servers/3/cert.pem" 43 | ltsigkey_path="../servers/drei.pub" 44 | [servers.vier] 45 | # address of server 46 | host="127.0.0.1" 47 | # port where server is running 48 | port=23004 49 | # public key of the server 50 | ssl_cert = "../servers/4/cert.pem" 51 | ltsigkey_path="../servers/vier.pub" 52 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/klutshnik.cfg: -------------------------------------------------------------------------------- 1 | [client] 2 | debug=true 3 | verbose=true 4 | threshold=2 5 | #ltsigkey_path="client.key" 6 | ltsigpub="LTSIGPK-s2h1YmIdOnNCgk6BIdrbgh0jdeF/QwnaXzvHDLLypbM=" 7 | id_salt="some salt and peppar" 8 | ts_epsilon=300 9 | keystore="keystore" 10 | timeout=100 11 | 12 | [servers] 13 | [servers.zero] 14 | # address of server 15 | host="127.0.0.1" 16 | # port where server is running 17 | port=2323 18 | # public key of the server 19 | ssl_cert = "/etc/klutshnik/cert.pem" 20 | ltsigkey_path="/etc/klutshnik/ltsig.key.pub" 21 | [servers.eins] 22 | # address of server 23 | host="127.0.0.1" 24 | # port where server is running 25 | port=23001 26 | # public key of the server 27 | ssl_cert = "servers/1/cert.pem" 28 | ltsigkey_path="servers/eins.pub" 29 | [servers.zwei] 30 | # address of server 31 | host="127.0.0.1" 32 | # port where server is running 33 | port=23002 34 | # public key of the server 35 | ssl_cert = "servers/2/cert.pem" 36 | ltsigkey_path="servers/zwei.pub" 37 | [servers.drei] 38 | # address of server 39 | host="127.0.0.1" 40 | # port where server is running 41 | port=23003 42 | # public key of the server 43 | ssl_cert = "servers/3/cert.pem" 44 | ltsigkey_path="servers/drei.pub" 45 | [servers.vier] 46 | # address of server 47 | host="127.0.0.1" 48 | # port where server is running 49 | port=23004 50 | # public key of the server 51 | ssl_cert = "servers/4/cert.pem" 52 | ltsigkey_path="servers/vier.pub" 53 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/test/otherclient/klutshnik.cfg: -------------------------------------------------------------------------------- 1 | [client] 2 | debug=true 3 | verbose=true 4 | threshold=2 5 | ltsigkey_path="client.key" 6 | ltsigpub="LTSIGPK-13lty/jQszJ1Xn5krTC2kltvPJDMqb4bqk3jgZxR430=" 7 | id_salt="some sodium and chilli" 8 | ts_epsilon=3 9 | keystore="keystore" 10 | 11 | [servers] 12 | [servers.zero] 13 | # address of server 14 | host="127.0.0.1" 15 | # port where server is running 16 | port=2323 17 | # public key of the server 18 | ssl_cert = "servers/qemucert.pem" 19 | ltsigkey_path="servers/qemu.pub" 20 | [servers.eins] 21 | # address of server 22 | host="127.0.0.1" 23 | # port where server is running 24 | port=23001 25 | # public key of the server 26 | ssl_cert = "../servers/1/cert.pem" 27 | ltsigkey_path="../servers/eins.pub" 28 | [servers.zwei] 29 | # address of server 30 | host="127.0.0.1" 31 | # port where server is running 32 | port=23002 33 | # public key of the server 34 | ssl_cert = "../servers/2/cert.pem" 35 | ltsigkey_path="../servers/zwei.pub" 36 | [servers.drei] 37 | # address of server 38 | host="127.0.0.1" 39 | # port where server is running 40 | port=23003 41 | # public key of the server 42 | ssl_cert = "../servers/3/cert.pem" 43 | ltsigkey_path="../servers/drei.pub" 44 | [servers.vier] 45 | # address of server 46 | host="127.0.0.1" 47 | # port where server is running 48 | port=23004 49 | # public key of the server 50 | ssl_cert = "../servers/4/cert.pem" 51 | ltsigkey_path="../servers/vier.pub" 52 | -------------------------------------------------------------------------------- /test/klutshnik.cfg: -------------------------------------------------------------------------------- 1 | [client] 2 | debug=true 3 | verbose=true 4 | threshold=2 5 | #ltsigkey_path="client.key" 6 | ltsigpub="LTSIGPK-s2h1YmIdOnNCgk6BIdrbgh0jdeF/QwnaXzvHDLLypbM=" 7 | id_salt="some salt and peppar" 8 | ts_epsilon=3 9 | keystore="keystore" 10 | timeout=300 11 | 12 | [servers] 13 | [servers.zero] 14 | # address of server 15 | host="127.0.0.1" 16 | # port where server is running 17 | port=23000 18 | # public key of the server 19 | ssl_cert = "servers/0/cert.pem" 20 | ltsigkey_path="servers/zero.pub" 21 | timeout=300 22 | [servers.eins] 23 | # address of server 24 | host="127.0.0.1" 25 | # port where server is running 26 | port=23001 27 | # public key of the server 28 | ssl_cert = "servers/1/cert.pem" 29 | ltsigkey_path="servers/eins.pub" 30 | timeout=300 31 | [servers.zwei] 32 | # address of server 33 | host="127.0.0.1" 34 | # port where server is running 35 | port=23002 36 | # public key of the server 37 | ssl_cert = "servers/2/cert.pem" 38 | ltsigkey_path="servers/zwei.pub" 39 | timeout=300 40 | [servers.drei] 41 | # address of server 42 | host="127.0.0.1" 43 | # port where server is running 44 | port=23003 45 | # public key of the server 46 | ssl_cert = "servers/3/cert.pem" 47 | ltsigkey_path="servers/drei.pub" 48 | timeout=300 49 | [servers.vier] 50 | # address of server 51 | host="127.0.0.1" 52 | # port where server is running 53 | port=23004 54 | # public key of the server 55 | ssl_cert = "servers/4/cert.pem" 56 | ltsigkey_path="servers/vier.pub" 57 | timeout=300 58 | -------------------------------------------------------------------------------- /tuokms.h: -------------------------------------------------------------------------------- 1 | #ifndef TUOKMS_H 2 | #define TUOKMS_H 3 | 4 | #include 5 | #include 6 | 7 | int klutshnik_stream_encrypt(const uint8_t yc[crypto_core_ristretto255_BYTES], 8 | const int infd, 9 | const int outfd); 10 | 11 | int klutshnik_decrypt_get_dek(const uint8_t r[crypto_core_ristretto255_SCALARBYTES], 12 | const uint8_t c[crypto_core_ristretto255_SCALARBYTES], 13 | const uint8_t d[crypto_core_ristretto255_SCALARBYTES], 14 | const uint8_t yc[crypto_core_ristretto255_BYTES], 15 | const uint8_t beta[crypto_core_ristretto255_BYTES], 16 | const uint8_t verifier_beta[crypto_core_ristretto255_BYTES], 17 | uint8_t dek[crypto_secretbox_KEYBYTES]); 18 | 19 | int klutshnik_verify_zk_proof(const uint8_t r[crypto_core_ristretto255_SCALARBYTES], 20 | const uint8_t c[crypto_core_ristretto255_SCALARBYTES], 21 | const uint8_t d[crypto_core_ristretto255_SCALARBYTES], 22 | const uint8_t yc[crypto_core_ristretto255_BYTES], 23 | const uint8_t beta[crypto_core_ristretto255_BYTES], 24 | const uint8_t verifier_beta[crypto_core_ristretto255_BYTES], 25 | uint8_t gk[crypto_core_ristretto255_BYTES]); 26 | #endif // TUOKMS_H 27 | -------------------------------------------------------------------------------- /python/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # SPDX-FileCopyrightText: 2023-25, Marsiske Stefan 4 | # SPDX-License-Identifier: GPL-3.0-or-later 5 | 6 | import os 7 | from setuptools import setup 8 | 9 | # Utility function to read the README file. 10 | # Used for the long_description. It's nice, because now 1) we have a top level 11 | # README file and 2) it's easier to type in the README file than to put a raw 12 | # string in below ... 13 | def read(fname): 14 | return open(os.path.join(os.path.dirname(__file__), fname)).read() 15 | 16 | setup(name = 'klutshnik', 17 | version = '0.3.0', 18 | description = 'Klutshnik CLI client', 19 | license = "GPLv3", 20 | author = 'Stefan Marsiske', 21 | author_email = 'klutshnik@ctrlc.hu', 22 | url = 'https://klutshnik.info/', 23 | long_description=read('README.org'), 24 | long_description_content_type="text/markdown", 25 | packages = ['klutshnik'], 26 | install_requires = ("pysodium", "pyoprf", "tomlkit"), 27 | extras_require={ 28 | 'devices': ['esptool', 'pyserial', 'pyudev'], 29 | 'esp': ['esptool'], 30 | 'usb': ['pyudev', "pyserial"], 31 | }, 32 | classifiers = ["Development Status :: 4 - Beta", 33 | "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", 34 | "Topic :: Security :: Cryptography", 35 | "Topic :: Security", 36 | ], 37 | entry_points = { 38 | 'console_scripts': [ 39 | 'klutshnik = klutshnik.klutshnik:main', 40 | #'genkey25519 = klutshnik.klutshnik:genkey' 41 | ], 42 | }, 43 | ) 44 | -------------------------------------------------------------------------------- /website/code.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Code - Klutshnik Key-Management System 2 | #+AUTHOR: klutshnik 3 | #+OPTIONS: H:2 num:t toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t 4 | #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc 5 | 6 | #+BEGIN_EXPORT html 7 | 8 | 18 |
19 | #+END_EXPORT 20 | 21 | * Code Repositories 22 | 23 | The Klutshnik ecosystem is open source and maintained across several repositories. 24 | Below are links to the main components: 25 | 26 | - **Main Client/Server:** 27 | https://github.com/stef/klutshnik or alternatively on radicle: rad:zogkw4qiTrH7rKVa89BrKo8z5miA 28 | 29 | - **Klutshnik Zephyr:** - for running a klutshnik server locally on a small embedded device: 30 | https://github.com/stef/klutshnik-zephyr or alternatively on radicle: rad:z2EBBi4vui98QV8Mk8DT3c25yZbJ4 31 | 32 | - **Core OPRF library (RFC9497[fn:0] compliant):** 33 | https://github.com/stef/liboprf or alternatively on radicle: rad:z3P9keM4KFAMp8wZuULi71VS7cWwp 34 | 35 | [fn:0] [[https://datatracker.ietf.org/doc/rfc9497/][RFC 9497: Oblivious Pseudorandom Functions (OPRFs) Using Prime-Order Groups]] 36 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/sbox.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # invoke with 4 | # su klutshnik -c "./sbox.sh /usr/bin/klutshnikd /etc/klutshnik/config klutshnik.bpf" 5 | # 6 | # notice: wordexp will not work in the jail, since at least musl actually exec /bin/sh to eval a printf 7 | # also important the cfg file must not use spaces around the = signs, otherwise sourcing it will fail 8 | # during sourcing the cfg file there is one error/warning regarding [server] which can be ignored 9 | # seccomp.bpf can be generated by following the steps in seccomp/README.md 10 | 11 | libs=$(ldd "$1" | fgrep -v linux-vdso.so | sed 's;.*\s\(/[^ ]*\) (0x[0-9a-f]*)$;\1;' | sort -u) 12 | libdirs=$(echo "$libs" | sed 's;\(/.*/\).*;\1;' | sort -u) 13 | mkdirs=$(echo "$libdirs" | sed 's;\(.*\);--dir \1;') 14 | libinds=$(echo "$libs" | sed 's;\(.*\);--ro-bind \1 \1;') 15 | 16 | source "$2" 2>/dev/null 17 | 18 | ulimit -s 196600 19 | 20 | # clear environment 21 | env -i \ 22 | bwrap --unshare-all \ 23 | --share-net \ 24 | --hostname klutshnik-rpi \ 25 | --die-with-parent \ 26 | --ro-bind "$1" /klutshnikd \ 27 | --file 0 /klutshnik.cfg \ 28 | --bind "$datadir" /data \ 29 | --ro-bind "$ssl_cert" /cert.pem \ 30 | --ro-bind "$ssl_key" /key.pem \ 31 | --ro-bind "$ltsigkey" /ltsig.key \ 32 | --ro-bind "$noisekey" /noise.key \ 33 | --ro-bind "$authorized_keys" /authorized_keys \ 34 | $mkdirs $libinds \ 35 | --dev /dev \ 36 | --seccomp 11 11<$3 \ 37 | --chdir / \ 38 | /klutshnikd < 8 | 18 |
19 | #+END_EXPORT 20 | 21 | * Public Servers 22 | 23 | List of public Klutshnik servers 24 | 25 | |----------------+------+------------------------------------------------------------------+------------------------------------------------+-----------------------------| 26 | | hostname | port | onion url | long-term signature pubkey | website | 27 | |----------------+------+------------------------------------------------------------------+------------------------------------------------+-----------------------------| 28 | |----------------+------+------------------------------------------------------------------+------------------------------------------------+-----------------------------| 29 | 30 | * Contributing to the Public Server Network 31 | 32 | If you operate a reliable Klutshnik server and want to make it available 33 | to the community, consider reaching out to the project maintainers and 34 | we can add it here. Community-operated servers strengthen the 35 | overall KPHINX ecosystem by providing more options for threshold configurations 36 | and reducing centralization. 37 | -------------------------------------------------------------------------------- /server/build.zig.zon: -------------------------------------------------------------------------------- 1 | .{ 2 | // This is the default name used by packages depending on this one. For 3 | // example, when a user runs `zig fetch --save `, this field is used 4 | // as the key in the `dependencies` table. Although the user can choose a 5 | // different name, most users will stick with this provided value. 6 | // 7 | // It is redundant to include "zig" in this name because it is already 8 | // within the Zig package namespace. 9 | .name = .klutshnik, 10 | 11 | // This is a [Semantic Version](https://semver.org/). 12 | // In a future version of Zig it will be used for package deduplication. 13 | .version = "0.1.0", 14 | 15 | .minimum_zig_version = "0.15.1", 16 | 17 | .fingerprint = 0xfd6ec59f28d4dd4e, 18 | 19 | // This field is optional. 20 | // Each dependency must either provide a `url` and `hash`, or a `path`. 21 | // `zig build --fetch` can be used to fetch all dependencies of a package, recursively. 22 | // Once all dependencies are fetched, `zig build` no longer requires 23 | // internet connectivity. 24 | .dependencies = .{ 25 | .zig_toml = .{ 26 | .url = "git+https://github.com/stef/zig-toml.git#016674a73bb23dc07f5ba0aa9971d16727a24dc6", 27 | .hash = "zig_toml-0.1.0-ngd9hwSxAAAvD39GxGG1qy6V2Y9M8N8zbeYSsNi98Ghr", 28 | }, 29 | .zig_bearssl = .{ 30 | .url = "git+https://github.com/stef/zig-bearssl.git#b871fe4b6556a04e7839f047a80787db54fa2b70", 31 | .hash = "zig_bearssl-0.1.0-CB7xTPKkAAAON7lowLylrsZXLkCdwkQdT_IHY7ZjlStt", 32 | }, 33 | .libsodium = .{ 34 | .url = "git+https://github.com/jedisct1/libsodium.git#09e995c0c85a0026510704b8ce7f5867a09a3841", 35 | .hash = "N-V-__8AAONJYQCM2EvfTRcbTy_p9_e6hTjX34KAk0MItmwe", 36 | }, 37 | .liboprf = .{ 38 | .url = "git+https://github.com/stef/liboprf.git#86ed6dac5c41aca2d9391180f6fb576f39e57cb7", 39 | .hash = "liboprf-0.9.1-2NAwiIPDEADWQI2XGdOpTU2WkOCFJabSXFJjIa8sNUDa", 40 | }, 41 | }, 42 | .paths = .{ 43 | "build.zig", 44 | "build.zig.zon", 45 | "src", 46 | // For example... 47 | //"LICENSE", 48 | //"README.md", 49 | }, 50 | } 51 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | chroot_exec adduser -D -g "klutshnik daemon" -h "/data/klutshnik" "klutshnik" "klutshnik" 4 | 5 | cp "$INPUT_PATH/klutshnikd" "$ROOTFS_PATH/usr/bin/klutshnikd" 6 | cp "$INPUT_PATH/init.sh" "$ROOTFS_PATH/etc/init.d/klutshnik" 7 | 8 | mkdir "$ROOTFS_PATH/etc/klutshnik" 9 | cp "$INPUT_PATH/klutshnik.cfg_template" "$ROOTFS_PATH/data/klutshnik/klutshnik.cfg_template" 10 | cp "$INPUT_PATH/setup_init.sh" "$ROOTFS_PATH/etc/init.d/klutshnik-setup" 11 | cp "$INPUT_PATH/setup.sh" "$ROOTFS_PATH/usr/bin/klutshnik-setup" 12 | cp "$INPUT_PATH/klutshnik-rev" "$ROOTFS_PATH/data/klutshnik/klutshnik-rev" 13 | cp "$INPUT_PATH/sbox.sh" "$ROOTFS_PATH/usr/bin/sbox.sh" 14 | cp -a "$INPUT_PATH/test" "$ROOTFS_PATH/data/klutshnik/test" 15 | 16 | chroot_exec rc-update add klutshnik default 17 | chroot_exec rc-update add klutshnik-setup default 18 | chroot_exec apk add openssl acme.sh acme-tiny certbot libsodium strace git make netcat-openbsd linux-headers g++ gcc libsodium-dev py3-virtualenv py3-pip python3-dev openssl-dev bubblewrap nginx iptables tor 19 | 20 | chroot_exec virtualenv --system-site-packages /data/klutshnik/env 21 | 22 | ab_git -r https://github.com/stef/liboprf/ -p "$ROOTFS_PATH/data/klutshnik/liboprf" 23 | chroot_exec make PREFIX=/usr -C /data/klutshnik/liboprf/src install 24 | chroot_exec /data/klutshnik/env/bin/pip install /data/klutshnik/liboprf/python 25 | rm -rf "$ROOTFS_PATH/data/klutshnik/liboprf" 26 | 27 | ab_git -r https://github.com/stef/klutshnik -p "$ROOTFS_PATH/data/klutshnik/klutshnik" 28 | chroot_exec /data/klutshnik/env/bin/pip install /data/klutshnik/klutshnik/python 29 | chroot_exec make PREFIX=/usr -C /data/klutshnik/klutshnik install 30 | rm -rf "$ROOTFS_PATH/data/klutshnik/klutshnik" 31 | 32 | ab_git -r https://android.googlesource.com/platform/external/minijail/ -p "$ROOTFS_PATH/data/klutshnik/minijail" 33 | chroot_exec make OUT=/data/klutshnik/minijail -C /data/klutshnik/minijail constants.json 34 | mv "$ROOTFS_PATH/data/klutshnik/minijail/constants.json" "$ROOTFS_PATH/data/klutshnik/" 35 | 36 | chroot_exec apk del git netcat-openbsd linux-headers g++ gcc libsodium-dev py3-virtualenv py3-pip python3-dev openssl-dev make 37 | chroot_exec apk add gcompat 38 | 39 | cp -a "$ROOTFS_PATH/data/klutshnik" "$DATAFS_PATH"/ 40 | rm -rf "$ROOTFS_PATH/data/klutshnik" 41 | 42 | -------------------------------------------------------------------------------- /test/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | echo create keyid1 4 | pk=$(klutshnik create "keyid1" /tmp/klutshniked 9 | 10 | echo decrypt 11 | cat kltsk /tmp/klutshniked | klutshnik decrypt 12 | 13 | echo rotate keyid1 14 | out=$(klutshnik rotate "keyid1" /tmp/klutshniked 9 | 10 | echo decrypt 11 | cat kltsk /tmp/klutshniked | klutshnik decrypt 12 | 13 | echo rotate keyid1 14 | out=$(klutshnik rotate "keyid1" . 86 | This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. 87 | 88 | # SEE ALSO 89 | 90 | `https://klutshnik.info` 91 | 92 | `klutshnik(1)`, `klutshnikd.cfg(5)` 93 | -------------------------------------------------------------------------------- /website/docs.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Docs - Klutshnik Key-Management System 2 | #+AUTHOR: klutshnik 3 | #+OPTIONS: H:2 num:t toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t 4 | #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc 5 | 6 | #+BEGIN_EXPORT html 7 | 8 | 18 |
19 | #+END_EXPORT 20 | 21 | Klutshnik uses a client-threshold-server architecture where servers 22 | perform cryptographic operations on blinded input. The Klutshnik 23 | protocol only makes sense if the key-management server is located 24 | somewhere other than where you store your ciphertext or operate on 25 | your plaintext. The client is a command-line tool that provides access 26 | to all operations to help manage your passwords. 27 | 28 | * Operations 29 | 30 | The Klutshnik client provides the following operations: ~create~, 31 | ~encrypt~, ~decrypt~, ~rotate~, ~refresh~, ~update~, ~adduser~, 32 | ~deluser~, ~listusers~, ~import~, ~provision~, and ~delete~. See the 33 | [[./manpages/klutshnik.html][klutshnik(1) manpage]] for how to use these operations. 34 | 35 | * Man pages 36 | 37 | - Server: [[./manpages/klutshnikd.html][klutshnikd(1)]] 38 | - CLI client: [[./manpages/klutshnik.html][klutshnik(1)]] 39 | 40 | * Designed by Established Cryptographers 41 | 42 | The main functionality is based on the UOKMS construction of the 43 | [[https://eprint.iacr.org/2019/1275][Updatable Oblivious Key Management for Storage Systems]] by Stanislaw 44 | Jarecki, Hugo Krawczyk, and Jason Resch 45 | 46 | The Threshold OPRF is based on: [[https://eprint.iacr.org/2017/363][TOPPSS: Cost-minimal 47 | Password-Protected Secret Sharing based on Threshold OPRF]] by Stanislaw 48 | Jarecki, Aggelos Kiayias, Hugo Krawczyk, and Jiayu Xu 49 | 50 | Within this, the DKG is based on /R. Gennaro, M. O. Rabin, and 51 | T. Rabin/. "Simplified VSS and fact-track multiparty computations with 52 | applications to threshold cryptography" In B. A. Coan and Y. Afek, 53 | editors, 17th ACM PODC, pages 101–111. ACM, June / July 1998 and is 54 | fully [[https://github.com/stef/liboprf/tree/master/docs/stp-dkg.txt][specified in liboprf]]. 55 | 56 | The key-update is based on: Fig. 2 from "Simplified VSS and fact-track 57 | multiparty computations with applications to threshold cryptography" 58 | by R. Gennaro, M. O. Rabin, and T. Rabin. This is fully 59 | [[https://github.com/stef/liboprf/tree/master/docs/stp-update.txt][specified in liboprf]]. 60 | 61 | The files are encrypted using ~crypto_secretbox()~ by [[https://github.com/jedisct1/libsodium][libsodium]], using 62 | the STREAM construction of [[https://eprint.iacr.org/2015/189]["Online Authenticated-Encryption and its 63 | Nonce-Reuse Misuse-Resistance"]] by Viet Tung Hoang, Reza Reyhanitabar, 64 | Phillip Rogaway, and Damian Vizár 65 | 66 | * Whitepaper 67 | 68 | We have a [[https://github.com/stef/klutshnik/blob/master/whitepaper.org][whitepaper]] documenting how we extended the original UOKMS 69 | paper mentioned above to make it work in a real world setup. 70 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | INCLUDES=$(shell pkgconf --cflags liboprf) 2 | CFLAGS?=-march=native -Wall -O2 -g \ 3 | -fstack-protector-strong -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 \ 4 | -Wformat=2 -Wconversion -Wimplicit-fallthrough \ 5 | -fasynchronous-unwind-tables -fpic -fstack-clash-protection \ 6 | -Werror=format-security -Werror=implicit-function-declaration -Wl,-z,defs -Wl,-z,relro \ 7 | -ftrapv -Wl,-z,noexecstack -D_BSD_SOURCE -D_DEFAULT_SOURCE 8 | 9 | #LDFLAGS?=/usr/lib/liboprf.a /usr/lib/liboprf-noiseXK.a -lsodium 10 | LIBS=-loprf -lsodium 11 | CC?=gcc 12 | SOEXT?=so 13 | STATICEXT?=a 14 | SOVER=0 15 | 16 | UNAME := $(shell uname -s) 17 | ARCH := $(shell uname -m) 18 | ifeq ($(UNAME),Darwin) 19 | SOEXT=dylib 20 | SOFLAGS=-Wl,-install_name,$(DESTDIR)$(PREFIX)/lib/libklutshnik.$(SOEXT) 21 | else 22 | CFLAGS+=-Wl,-z,defs -Wl,-z,relro -Wl,-z,noexecstack -Wl,-z,now -Wtrampolines \ 23 | -fsanitize=signed-integer-overflow -fsanitize-undefined-trap-on-error 24 | #-fstrict-flex-arrays=3 -mbranch-protection=standard 25 | SOEXT=so 26 | SOFLAGS=-Wl,-soname,libklutshnik.$(SOEXT).$(SOVER) 27 | ifeq ($(ARCH),x86_64) 28 | CFLAGS+=-fcf-protection=full 29 | endif 30 | 31 | ifeq ($(ARCH),parisc64) 32 | else ifeq ($(ARCH),parisc64) 33 | else 34 | CFLAGS+=-fstack-clash-protection 35 | endif 36 | endif 37 | 38 | 39 | all: libklutshnik.so libklutshnik.pc 40 | 41 | asan: CFLAGS=-fsanitize=address -static-libasan -g -march=native -Wall -O2 \ 42 | -g -fstack-protector-strong -fpic -fstack-clash-protection -fcf-protection=full \ 43 | -Werror=format-security -Werror=implicit-function-declaration -Wl, -z,noexecstack 44 | asan: LDFLAGS+= -fsanitize=address -static-libasan 45 | asan: all 46 | 47 | SOURCES=streamcrypt.c tuokms.c utils.c 48 | OBJECTS=$(patsubst %.c,%.o,$(SOURCES)) 49 | 50 | libklutshnik.$(SOEXT): $(SOURCES) 51 | $(CC) -fPIC -shared $(CPPFLAGS) $(CFLAGS) $(INCLUDES) $(SOFLAGS) -o libklutshnik.$(SOEXT) $^ $(LDFLAGS) $(LIBS) 52 | 53 | libklutshnik.$(STATICEXT): $(OBJECTS) 54 | $(AR) rcs $@ $^ 55 | 56 | libklutshnik.pc: 57 | echo "prefix=$(PREFIX)" >libklutshnik.pc 58 | cat libklutshnik.pc0 >>libklutshnik.pc 59 | 60 | install: $(DESTDIR)$(PREFIX)/lib/libklutshnik.$(SOEXT) \ 61 | $(DESTDIR)$(PREFIX)/lib/libklutshnik.$(STATICEXT) \ 62 | $(DESTDIR)$(PREFIX)/lib/pkgconfig/libklutshnik.pc \ 63 | $(DESTDIR)$(PREFIX)/include/klutshnik/streamcrypt.h \ 64 | $(DESTDIR)$(PREFIX)/include/klutshnik/tuokms.h 65 | 66 | uninstall: $(DESTDIR)$(PREFIX)/lib/libklutshnik.$(SOEXT) $(DESTDIR)$(PREFIX)/lib/libklutshnik.$(STATICEXT) \ 67 | $(DESTDIR)$(PREFIX)/lib/pkgconfig/libklutshnik.pc \ 68 | $(DESTDIR)$(PREFIX)/include/klutshnik/streamcrypt.h $(DESTDIR)$(PREFIX)/include/klutshnik/tuokms.h 69 | rm $^ 70 | rmdir $(PREFIX)/include/klutshnik/ 71 | 72 | $(DESTDIR)$(PREFIX)/lib/libklutshnik.$(SOEXT): libklutshnik.$(SOEXT) 73 | mkdir -p $(DESTDIR)$(PREFIX)/lib 74 | cp $< $@.$(SOVER) 75 | ln -sf $@.$(SOVER) $@ 76 | 77 | $(DESTDIR)$(PREFIX)/lib/libklutshnik.$(STATICEXT): libklutshnik.$(STATICEXT) 78 | mkdir -p $(DESTDIR)$(PREFIX)/lib 79 | cp $< $@ 80 | 81 | $(DESTDIR)$(PREFIX)/lib/pkgconfig/libklutshnik.pc: libklutshnik.pc 82 | mkdir -p $(DESTDIR)$(PREFIX)/lib/pkgconfig 83 | cp $< $@ 84 | 85 | $(DESTDIR)$(PREFIX)/include/klutshnik/streamcrypt.h: streamcrypt.h 86 | mkdir -p $(DESTDIR)$(PREFIX)/include/klutshnik 87 | cp $< $@ 88 | 89 | $(DESTDIR)$(PREFIX)/include/klutshnik/tuokms.h: tuokms.h 90 | mkdir -p $(DESTDIR)$(PREFIX)/include/klutshnik 91 | cp $< $@ 92 | 93 | test: libklutshnik.$(SOEXT) libklutshnik.$(STATICEXT) 94 | make -C tests tests 95 | 96 | clean: 97 | @rm -f *.o libklutshnik.$(STATICEXT) libklutshnik.$(SOEXT) libklutshnik.pc 98 | 99 | %.o: %.c 100 | $(CC) $(CFLAGS) -fPIC $(INCLUDES) -c $< -o $@ 101 | 102 | PHONY: clean 103 | -------------------------------------------------------------------------------- /website/faq.org: -------------------------------------------------------------------------------- 1 | 2 | #+TITLE: Klutshnik Key-Management System 3 | #+AUTHOR: klutshnik 4 | #+OPTIONS: H:2 num:t toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t 5 | #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc 6 | #+options: tex:dvisvgm 7 | 8 | #+BEGIN_EXPORT html 9 | 12 | 13 | 23 |
24 | #+END_EXPORT 25 | 26 | * How does the key-rotation work? 27 | 28 | It is really quite simple. For simplicity this is shown in a 29 | non-threshold setting first. The DEK is really the output of an OPRF, 30 | every file has a value ~w~ which is the input of the OPRF and the ~KEK~ 31 | is held by the klutshnik server. Thus 32 | 33 | #+BEGIN_CENTER 34 | $DEK = OPRF(KEK, w) = w \cdot KEK$ 35 | #+END_CENTER 36 | 37 | We use a specific OPRF[fn:hashDH] which retains algebraic structure, 38 | so we can do mathy stuff with the DEK, such as updating the KEK, while 39 | the DEK remains unchanged. When we update, all we do is to have the 40 | klutshnik server choose a random value $\delta_{i}$ and calculates: 41 | 42 | #+BEGIN_CENTER 43 | $KEK_{i+1} = KEK_{i} \cdot \delta_{i}$ 44 | #+END_CENTER 45 | 46 | The server shares $\delta_{i}$ with the untrusted storage, which will adjust 47 | the ~w~ value for each encrypted file belonging to this key by: 48 | 49 | #+BEGIN_CENTER 50 | $w_{i+1} = \frac{w_{i}}{\delta_{i}}$ 51 | #+END_CENTER 52 | 53 | This all works simply because of the algebraic structure of the OPRF 54 | is preserved, and if we expand the OPRF we get the following: 55 | 56 | #+BEGIN_CENTER 57 | $DEK = w_1 \cdot KEK_1 = w_0 \cdot KEK_0$ 58 | 59 | $\frac{w_0}{\delta_{0}} \cdot KEK_0 \cdot \delta_{0}$ 60 | #+END_CENTER 61 | 62 | It is really just some very very simple multiplication and division 63 | with values represented by latin and greek letters. 64 | 65 | In the threshold setup the KEK is split among the shareholders using 66 | basic verifiable Shamirs Secret Sharing, and the new $KEK_{i+1}$ is 67 | being calculated by the shareholders by using a multi-party 68 | computation that multiplies two values shared with secret-sharing 69 | scheme. 70 | 71 | As you can see, neither the $w_{i}$ nor the $\delta_{i}$ values 72 | provide any information about either the $KEK_{i}$ nor the $DEK_{i}$, 73 | and can thus be known by the storage when doing the 74 | key-update. Remember we do trust the storage to provide integrity and 75 | availability and thus also implicitly to correctly calculate the 76 | updated $w_{i+1}$ values based on the $\delta_{i}$ update tokens, 77 | never learning either the DEK nor the KEK, and thus nothing about the 78 | plaintext. 79 | 80 | [fn:hashDH] Notable is that this OPRF is a hashDH style OPRF and not a 81 | more common 2HashDH OPRF, this is important, since this OPRF variant 82 | retains algebraic properties, which would be destroyed by the 2nd hash 83 | in the 2HashDH OPRFs. 84 | 85 | * What's with this weird name Klutshnik? 86 | 87 | It is a homage to the all the great cryptographers having a 88 | polish/slavic background. 'kljutsh' (or variations of it) means "key" 89 | in slavic languages, and the 'nik' postfix means something like 90 | "person" just like in beatnik. Together they mean "person of keys" or 91 | "key person". Anyway I think it is a much better name than GNU 92 | Keymaster 3000 Deluxe Pro. 93 | -------------------------------------------------------------------------------- /server/src/secret_allocator.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const Allocator = std.mem.Allocator; 3 | const sodium = @cImport({ 4 | @cInclude("sodium.h"); 5 | }); 6 | 7 | 8 | pub fn SecretAllocator() type { 9 | return struct { 10 | parent_allocator: Allocator, 11 | 12 | const Self = @This(); 13 | 14 | pub fn init(parent_allocator: Allocator) Self { 15 | return Self{ 16 | .parent_allocator = parent_allocator, 17 | }; 18 | } 19 | 20 | pub fn allocator(self: *Self) Allocator { 21 | return .{ 22 | .ptr = self, 23 | .vtable = &.{ 24 | .alloc = alloc, 25 | .resize = resize, 26 | .remap = remap, 27 | .free = free, 28 | }, 29 | }; 30 | } 31 | 32 | fn remap(ctx: *anyopaque, 33 | buf: []u8, 34 | log2_buf_align: std.mem.Alignment, 35 | new_len: usize, 36 | ra: usize) ?[*]u8 { 37 | const self: *Self = @ptrCast(@alignCast(ctx)); 38 | _=sodium.sodium_munlock(@ptrCast(buf),buf.len); 39 | const result = self.parent_allocator.rawRemap(buf, log2_buf_align, new_len, ra); 40 | if(result) |new_buf| { 41 | if(new_len>0 and 0!=sodium.sodium_mlock(@ptrCast(new_buf), new_len)) { 42 | self.parent_allocator.rawFree(new_buf[0..new_len], log2_buf_align, ra); 43 | return null; 44 | } 45 | } 46 | return result; 47 | } 48 | 49 | fn alloc( 50 | ctx: *anyopaque, 51 | len: usize, 52 | log2_ptr_align: std.mem.Alignment, 53 | ra: usize, 54 | ) ?[*]u8 { 55 | const self: *Self = @ptrCast(@alignCast(ctx)); 56 | const result = self.parent_allocator.rawAlloc(len, log2_ptr_align, ra); 57 | if (result) |buf| { 58 | if(len > 0 and 0!=sodium.sodium_mlock(@ptrCast(buf),len)) { 59 | self.parent_allocator.rawFree(buf[0..len], log2_ptr_align, ra); 60 | return null; 61 | } 62 | } 63 | return result; 64 | } 65 | 66 | fn resize( 67 | ctx: *anyopaque, 68 | buf: []u8, 69 | log2_buf_align: std.mem.Alignment, 70 | new_len: usize, 71 | ra: usize, 72 | ) bool { 73 | const self: *Self = @ptrCast(@alignCast(ctx)); 74 | if(new_len==0) _=sodium.sodium_munlock(@ptrCast(buf),buf.len); 75 | if (self.parent_allocator.rawResize(buf, log2_buf_align, new_len, ra)) { 76 | if(new_len>buf.len) _=sodium.sodium_mlock(buf.ptr, new_len); 77 | return true; 78 | } 79 | std.debug.assert(new_len > buf.len); 80 | return false; 81 | } 82 | 83 | fn free( 84 | ctx: *anyopaque, 85 | buf: []u8, 86 | log2_buf_align: std.mem.Alignment, 87 | ra: usize, 88 | ) void { 89 | const self: *Self = @ptrCast(@alignCast(ctx)); 90 | _ = sodium.sodium_munlock(buf.ptr,buf.len); 91 | self.parent_allocator.rawFree(buf, log2_buf_align, ra); 92 | } 93 | }; 94 | } 95 | 96 | pub fn secretAllocator( 97 | parent_allocator: Allocator, 98 | ) SecretAllocator() { 99 | return SecretAllocator().init(parent_allocator); 100 | } 101 | 102 | test "SecretAllocator" { 103 | var allocator_buf: [10]u8 = undefined; 104 | var fixedBufferAllocator = std.mem.validationWrap(std.heap.FixedBufferAllocator.init(&allocator_buf)); 105 | var allocator_state = secretAllocator(fixedBufferAllocator.allocator()); 106 | const allocator = allocator_state.allocator(); 107 | 108 | var a = try allocator.alloc(u8, 10); 109 | try std.testing.expect(allocator.resize(a, 5)); 110 | a = a[0..5]; 111 | try std.testing.expect(!allocator.resize(a, 20)); 112 | allocator.free(a); 113 | } 114 | -------------------------------------------------------------------------------- /images/klutshnik-sbox-rpi/input/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | if [ -f /etc/klutshnik/initialized ]; then 4 | return 0 5 | fi 6 | 7 | set -x 8 | exec >/data/klutshnik/setup.log 2>&1 9 | 10 | logger -t "rc.klutshnik-setup" "Setting up klutshnik" 11 | 12 | sed "s/some natrium-chloride and some chilli/$(dd if=/dev/random bs=1 count=32 2>/dev/null | base32)/" /etc/klutshnik/config 13 | openssl ecparam -genkey -out /etc/klutshnik/key.pem -name secp384r1 14 | openssl req -new -nodes -x509 -sha256 -key /etc/klutshnik/key.pem -out /etc/klutshnik/cert.pem -days 365 -subj '/CN=klutshnik-rpi' 15 | chown klutshnik /etc/klutshnik/cert.pem /etc/klutshnik/key.pem 16 | 17 | while read line; do 18 | case "$line" in 19 | successfully\ created\ long-term\ signature\ key\ pair*) read _; read _; read _; read _; read ltsigpub;; 20 | successfully\ created\ long-term\ noise\ key\ pair*) read _; read _; read _; read _; read noisepub;; 21 | The\ following\ are\ the\ base64\ encoded\ long-term\ and\ noise\ public\ key*) read authuser;; 22 | esac 23 | done <&1) 25 | EOF 26 | 27 | chown klutshnik:klutshnik /etc/klutshnik/ltsig.key 28 | chown klutshnik:klutshnik /etc/klutshnik/ltsig.key.pub 29 | chown klutshnik:klutshnik /etc/klutshnik/noise.key 30 | chown klutshnik:klutshnik /etc/klutshnik/noise.key.pub 31 | 32 | echo $authuser >>/etc/klutshnik/authorized_keys 33 | chown klutshnik:klutshnik /etc/klutshnik/authorized_keys 34 | 35 | mount -o remount,rw / 36 | # set up tor 37 | 38 | echo "HiddenServiceDir /var/lib/tor/klutshnik/" >>/etc/tor/torrc 39 | echo "HiddenServicePort 443 127.0.0.1:2323" >>/etc/tor/torrc 40 | /etc/init.d/tor start 41 | while [ ! -f /var/lib/tor/klutshnik/hostname ]; do 42 | sleep 1 43 | done 44 | /etc/init.d/tor stop 45 | 46 | cat >/etc/motd <