kee

Offline IOU signer with QR as transport
git clone git://holbrook.no/kee-gtk4.git
Info | Log | Files | Refs | README | LICENSE

README.md (12194B)


      1 # kee
      2 
      3 **The upstream respository is [git://holbrook.no/kee-gtk4.git](git://holbrook.no/kee-gtk4.git)**
      4 
      5 I am building a cryptographically counter-signed IOU application with linux phones ([GTK4](https://www.gtk.org/), [phosh](https://phosh.mobi/)) as the primary targets.
      6 
      7 It will maintain bi-lateral mutual channels of credit and collateral. Each change is linked as a chain, and documentation for each change in embedded as [email-link MIME structures](https://datatracker.ietf.org/doc/html/rfc2049)
      8 
      9 It is currently in alpha state, and does not yet have a friendly introduction.
     10 
     11 See "Protocol" and "Concepts" headings below for more details on what this actually is aiming to become.
     12 
     13 
     14 ## What it can do (currently)
     15 
     16 The UI state is still fragmented and does not yet implement a full sequence of actions for creating and mutually signing ledger.
     17 
     18 However, a ledger can be created, counter-signed and imported by restarting UI as Alice, Bob and Alice respectively, and manually use the import option.
     19 
     20 What it _does_ have is:
     21 
     22 * GTK interface pages for
     23     - Unlock wallet key
     24     - List IOUs
     25     - List IOU details and deltas (transactions)
     26     - Import data and/or delta (QR or pasted text)
     27     - Import summary and accept page
     28     - Create new ledger entry page
     29 * Testdata generator for tests and demonstrating state of UI:
     30     - Create keys for Alice and (main) Bob, as well as two additional Bobs
     31     - Symlinks to use (main) Bob key instead of Alice as identity for UI
     32     - A configurable number of randomized ledger entries and deltas
     33 * CLI tool:
     34     - Show details about a ledger entry
     35     - Sign a ledger delta
     36     
     37 
     38 ## Dependencies
     39 
     40 Below are the library versions of the [archlinux](https://archlinux.org/) component packages I am using for dependencies and tooling while working on my own system.
     41 
     42 | package | version |
     43 |---|---|
     44 | gcc | 13.2.1 |
     45 | graphicsmagick | 1.3.42 |
     46 | gst-plugins-bad  | 1.24.0 |
     47 | gstreamer | 1.24.0 |
     48 | gtk4 | 4.12.5 |
     49 | libb64 | 1.2.1 |
     50 | libgcrypt | 1.10.3 |
     51 | qrencode | 4.1.1 |
     52 | libxdg-basedir | 1.2.3 |
     53 | lmdb | 0.9.32 |
     54 | openldap | 2.6.7 |
     55 | rustup | 1.26.0 |
     56 | zbar | 0.23.90 |
     57 | zlib | 1.3.1 |
     58 
     59 The `gst-plugins-bad` provides [libgstzbar.so](https://gstreamer.freedesktop.org/documentation/zbar/index.html?gi-language=c#zbar-page), used as part of QR scanning.
     60 
     61 
     62 ### Other sources
     63 
     64 The code expects objects from these source trees to be available somehow:
     65 
     66 |project | upstream source | version | tar.gz sha256 |
     67 |---|---|---|---|
     68 | liblash* | [https://holbrook.no/src/liblash](https://holbrook.no/src/liblash) `(193dd4032e8088ada2dc9dcedab8d7486e9305f5)` | `0.1.0` | `333cdf49bb7e9f44b37e5bc9f594a01e4b3b8ecb3fcd3d9ffec3ea6dcdeaec7b` |
     69 | libcmime | [https://github.com/spmfilter/libcmime.git](https://github.com/spmfilter/libcmime.git) `(dd21eb096d162656e30243f60fc4bc35ad39ae6e)` | `0.2.2` | `18a8d46ebec575a79212acc2dc6af7fd7bdeba3a9b85a70677ed0b7785c5c04e` |
     70 | gst-plugins-rs | [https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs](https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs) `(a84bbc66f30573b62871db163c48afef75adf6ec)` | `1.22.10 (gstreamer)` | `691d5d52f59ec6322a2f6ddc1039ef47c9ac5e6328e2df1ef920629b46c659df` |
     71 
     72 You can clone `liblash` with `git clone git://holbrook.no/liblash`
     73 
     74 (\*liblash is now bundled in the `src/aux` directory)
     75 
     76 
     77 ## Building
     78 
     79 **There are instructions on building and running with [qemu](https://www.qemu.org/) and [Debian Bookworm (12)](https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-12.5.0-amd64-netinst.iso) in `README.qemu.adoc`**
     80 
     81 There is no magic pathfinder implemented currently. Thus, you must configure the environment for building and linking the external sources yourself.
     82 
     83 Here is what I use in my local setup.
     84 
     85 
     86 ### libcmime
     87 
     88 I can't seem to set the cmake build prefix so that the `libcmime.pc` file is generated correctly. Unfortunately, `pkg-config` is thus off the table.
     89 
     90 ```
     91 git clone -b 0.2.2 https://github.com/spmfilter/libcmime.git
     92 https://github.com/spmfilter/libcmime.git
     93 mkdir -p libcmime/build
     94 cd libcmime/build
     95 cmake ..
     96 make install DESTDIR=.
     97 ```
     98 
     99 Your include path, relative to the repository root directory, will be `<repo_root>/build/usr/include/lib64` and your ld path will be `build/usr/include/lib64`.
    100 
    101 
    102 ### libgstgtk4 (gst-plugin-rs)
    103 
    104 The `gtk4` part of the code uses the `gtk4paintablesink` gstreamer plugin (for QR scanning). It is part of the `gst-plugins-rs` source above, built as the `libgstgtk4.so` shared library file.
    105 
    106 The specific package to build is `gst-plugin-gtk4`, which builds the plugin at version `0.9.13`.
    107 
    108 I was able to build with toolchain `1.75-x86_64-unknown-linux-gnu`.
    109 
    110 ```
    111 rustup default 1.75.0
    112 cargo install cargo-c
    113 git clone -b gstreamer-1.22.10 https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs
    114 cd gst-plugins-rs
    115 cargo cbuild -p gst-plugin-gtk4
    116 ```
    117 
    118 
    119 ## Environment 
    120 
    121 ```
    122 #!/bin/bash
    123 
    124 set -x
    125 
    126 export GST_PLUGIN_PATH=/home/lash/src/build/gst-plugins-rs/target/x86_64-unknown-linux-gnu/debug/
    127 export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/home/lash/src/build/libcmime/0.2.2/build/usr/local/lib64/pkgconfig
    128 export LIBRARY_PATH=$LIBRARY_PATH:/home/lash/src/build/libcmime/0.2.2/build/usr/local/lib64:/home/lash/src/home/liblash/src
    129 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/lash/src/build/libcmime/0.2.2/build/usr/local/lib64:/home/lash/src/home/liblash/src
    130 export C_INCLUDE_PATH=$C_INCLUDE_PATH:/home/lash/src/build/libcmime/0.2.2/build/usr/local/include:/home/lash/src/home/liblash/src
    131 
    132 make run
    133 
    134 set +x
    135 ```
    136 
    137 Here is some background if you need:
    138 
    139 * [C_INCLUDE_PATH](https://gcc.gnu.org/onlinedocs/cpp/Environment-Variables.html)
    140 * [LIBRARY_PATH](https://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html#index-LIBRARY_005fPATH)
    141 * [LD_LIBRARY_PATH](https://www.man7.org/linux/man-pages/man8/ld.so.8.html#ENVIRONMENT)
    142 * [Difference between LD_LIBRARY_PATH and LIBRARY_PATH](https://www.baeldung.com/linux/library_path-vs-ld_library_path)
    143 * [PKG_CONFIG_PATH](https://man.archlinux.org/man/pkgconf.1.en#ENVIRONMENT)
    144 * [GST_PLUGIN_PATH](https://gstreamer.freedesktop.org/documentation/gstreamer/running.html?gi-language=c)
    145 * [cargo-c](https://github.com/lu-zero/cargo-c)
    146 
    147 
    148 ## Running
    149 
    150 In order to run the GTK application in its current condition, generated test data should be used as data path.
    151 
    152 Take care to install python dependencies in `requirements.txt` before the first command. Using a [virtual environment](https://docs.python.org/3/library/venv.html) is recommended. The author is using `python 3.12.x`.
    153 
    154 ```
    155 make testdata
    156 export KEE_PATH=$(realpath ./testdata)
    157 make run
    158 ``` 
    159 
    160 The testdata contains private keys for both Alice and Bob in the generated entries. To start as Bob, add before running:
    161 
    162 ```
    163 export KEE_KEY_PATH=$(realpath ./testdata/crypt_reverse)
    164 ```
    165 
    166 
    167 ### pip problems
    168 
    169 As of february 2025, I was not able to build pygcrypt or lmdb anymore on my archlinux system. Workaround was to ignore some pointer bloopers:
    170 
    171 `CPPFLAGS="-Wno-implicit-function-declaration -Wno-incompatible-pointer-types" pip install --no-cache --force-reinstall -r requirements.txt`
    172 
    173 
    174 ## Protocol
    175 
    176 TODO: The terms need to be tightened up; don't use different terms for same thing.
    177 
    178 The serialization format of the credit issuance is defined in `src/asb1/schema_entry.txt`. The serialization method is _der-encoding_.
    179 
    180 More about `asn1` here: [https://luca.ntop.org/Teaching/Appunti/asn1.html](https://luca.ntop.org/Teaching/Appunti/asn1.html).
    181 
    182 
    183 The protocol uses Elliptic Curve signatures. The curve used is `Ed25519`.
    184 
    185 
    186 ### Concepts
    187 
    188 The protocol consists of a series of ledgers, each with two participants, Alice and Bob.
    189 
    190 Alice and Bob are identified by their public keys.
    191 
    192 The protocol tracks an amount of credit issued by one party to another.
    193 
    194 The ledger may also define an amount of collateral that has been pledged against the credit.
    195 
    196 Credit and collateral are defined by a unit of account, which is defined for the entire ledger.
    197 
    198 Each credit issuance consists of one or more deltas (KeeEntry) changing the balance of the credit, and some identical metadata (KeeEntryHead) embedded in each one, together called an _entry item_.
    199 
    200 
    201 ### Creating a new entry
    202 
    203 We call the creator of the entry Alice.
    204 
    205 The default values of `signatureRequest` and `signatureResponse` is an empty octet string (length 0).
    206 
    207 The default value for `response` is `False`.
    208 
    209 If the entry is the first in the ledger, the value of `parent` is 64 0-bytes. If not, it is the sha512 sum of the preceding _entry item_.
    210 
    211 Alice generates the _entry item_ and signs it:
    212 
    213 ```
    214 head = der(KeeEntryHead)
    215 headsum = sha512(head)
    216 entry = der(KeeEntry)
    217 msg = sha512(concat(head, entry))
    218 sig = sign(msg) # TODO verify whether an additional sha512 on the message is performed by the internals
    219 copy(KeeEntry.signatureRequest, sig)
    220 ```
    221 
    222 ### Counter-signing an entry
    223 
    224 Alice shares KeeEntryHead and KeeEntry with Bob.
    225 
    226 Bob verifies Alice's signature.
    227 
    228 If Bob accepts the contents of the _entry item_, he sets `response` to `True`.
    229 
    230 Bob proceeds to sign the _entry item_:
    231 
    232 ```
    233 set(KeeEntry.response, bobs_decision)
    234 head = der(KeeEntryHead)
    235 headsum = sha512(head)
    236 entry = der(KeeEntry)
    237 msg = sha512(concat(head, entry)
    238 sig = sign(msg)
    239 copy(KeeEntry.signatureResponse, sig)
    240 ```
    241 
    242 Bob then adds the counter-signed _entry item_ to his persistent storage.
    243 
    244 
    245 ### Sharing the result
    246 
    247 Bob shares KeeEntryHead and KeeEntry with Alice.
    248 
    249 Alice verifies both signatures.
    250 
    251 Alice adds the counter-signed _entry_item_ to her persistent storage.
    252 
    253 Alice and Bob now have the same ledger state, adjusted by the deltas in the _entry item_.
    254 
    255 
    256 ### Sanity checks
    257 
    258 Checking that the delta in an _entry item_ makes sense is the responsibility of both parties, e.g. that the delta does not incur a negative credit value.
    259 
    260 
    261 ### Descriptive content
    262 
    263 Both the KeeEntryHead and KeeEntry structures include an optional `body` value, which is a sha512 hash of some content offering some description of what the ledger and individual changes consist of. If no description is provided, 64 0-bytes are used for the data field.
    264 
    265 This implementation uses, as previously mentioned, [MIME-structures](https://datatracker.ietf.org/doc/html/rfc2049) for this purpose.
    266 
    267 
    268 ## Data carriers
    269 
    270 A final implementation should define several ways of sharing content, including:
    271 
    272 * Copy and paste 
    273 * File sharing
    274 * Network retrieval
    275 * QR codes
    276 This implementation uses QR codes to exchange signature requests and signatures.
    277 
    278 
    279 ### QR exchange
    280 
    281 A separate transport container, `KeeTransport`, is used for this exchange, as well as some additional encoding.
    282 
    283 ```
    284 container = KeeTransport(KeeEntryHead, KeeEntry)
    285 raw = der(container)
    286 compressed = zlib_compress(raw)
    287 payload = base64(compressed)
    288 transport = concat(0x02, readable) # 0x02 = KEE_CMD_LEDGER, defined in src/transport.h
    289 qrencode(transport)
    290 ```
    291 
    292 
    293 #### Sharing descriptive content
    294 
    295 Descriptive content is currently not shared as part of the signature exchange.
    296 
    297 Since decriptive content can potentially be of some size, a transport protocol should be considered which can span multiple sequential QR codes, and allow of the same kind of offline exchange as the signature exchange itself.
    298 
    299 
    300 ## Examples
    301 
    302 The `make testdata` script creates several useful data examples:
    303 
    304 - `testdata/mdb` which is the persistent storage of a ledger and required indicies. Can be easily viewed using the `mdb_dump` command. Key prefixes are defined in `src/db.h:enum DbKey`
    305 - `testdata/crypt` contains alice and bob's private and public keys in sexp format, as well as an encrypted version of the private keys. The encryption used is `CHACHA20-POLY1305`, and password for both keys is `1234`. The `kee.key` symlink points to the private key (Alice) used by the GTK application.
    306 - `testdata/crypt_reverse` contains a symlink `kee.key` to Bob's encrypted private key, enabling use of the GTK application as Bob.
    307 - `testdata/import` Three files respresenting all phases of the _entry item_ format:
    308     * `request` - without signatures.
    309     * `response` - with Alice's signature.
    310     * `final` - with both signatures.
    311 - `testdata/resource` All descriptive content for the generated _ledgers_ and _entry items_.
    312 
    313 
    314 ## License
    315 
    316 [GPLv3](https://www.gnu.org/licenses/gpl-3.0.txt)