Picture of a Tree with roots
Tree Davies' Blog
[ Main ] [ Blog ]


A descriptive text

9.01.2026 - Udon: An End to End Encrypted message passing service / tool

Context
The Udon Project is an End to End Encrypted (E2EE) message passing tool. It started as (and still is) a personal research project. I call it the 20 minute a day project. Some days are more productive than others. Over time, I have bounced around like an ADHD Hamster surrounded by more exercise wheels than I have time for, but this project has continued to catch my attention. It has been a fun thing to think about.

What I want, and what I don't
Minimalist, Punktech, DIY, Under the radar, Auditable software. I want to send a message using a command line tool/service that can be easily self hosted, configurable, some security, and makeshift automation tool. Also, lets write it in an widely used programming language which is easy to read and learn.

There are so many platforms which act as hubs for our communication, and they all have something in common. Our data on someone else's servers. Additionally, we are forced into a Terms of Service and/or privacy agreement, which usually is not providing users with value. In most cases, these platforms are using us like livestock, feeding off our data to be analyzed bought and sold by data brokers in the data market economy. As of 2026, the estimated global market share of data brokers reported by Grand View Research, is estimated at $307,300,000,000, with a future estimate of $512,500,000,000 by 2033. That being said, Internet privacy is not forecasted to improve. Thinking about this, gives me the urge to touch my head to feel for a Tin Foil Hat. but there is nothing there. This is the reality in which we live.

Sure, there are tools which do appear to operate in societies best interests. I am a thankful user of the Signal app, which makes me smile every time, when my 75 year old Mother uses it to text or call me. But the question which keeps coming to mind; is what do we do when suddenly the Signal app stops working?

Udon
Written in Python, using the Cryptography module, and gRPC (Google Remote Procedure Call) library, Udon passes public key encrypted messages from one client to another, through (via OpenSSL) an intermediary server. Users query the server for new messages, fetch, and decrypt them on the client side. Kind of like... well... email. OK, yes... exactly like email...


Star Trek Captain Picard facepalming
Shit, I reinvented email...?

How it works
Similar to most chat services, a channel of communication is used to organize context. Udon uses a channel config file which defines server, port, locations for public/private keys, message database, and the root certificate used to validate the server's OpenSSL certificate. The 'clean_on_sync' option instructs the client to delete all messages from the server after every sync to the client. This can help reduce server disk usage and maybe a security benefit in the event the server is physically or logically compromised.

Example of a channel config:
channel = "bob_and_bender"
client_key_name = 'bob.pub'
client_private_key = '/home/bob/.udon/keys/client_side_keys/bob'
client_db_path = '/home/bob/.udon/db/bob.pub-udon-local.db'
dest_key_name_list = ['bender.pub', 'bob.pub']
clean_on_sync = 'disable'
server_fqdn = 'darkphysics.net'
server_port = '50051'
ssl_root = '/home/bob/.udon/TLS/chain.pem'

Protobuffers
gRPC uses Protocol Buffers as a way to define RPC (Service API) calls the server supports. Six unary RPCs have been defined in udon.proto.

service Unary{
rpc commit(CommitMessage) returns (MessageResponse) {}
rpc check(CheckRequest) returns (CheckRequestResponse) {}
rpc fetch(Request) returns (MessageResponse) {}
rpc clean(CleanRequest) returns (CleanResponse) {}
rpc ping(PingRequest) returns (PingResponse) {}
rpc module(ModuleRequest) returns (ModuleResponse) {}
}


commit() - Sends a message to a desired recipient in care of the server.

check() - Requests a integer value of the number of messages in a users queue.

fetch() - Requests a specific message from a users queue.

clean() - Requests the server to delete all messages in a user's queue.

ping() - returns success/fail if server is online.

module() - Simple Python modules can be plugged into the server. Authorized users can use this RPC to call/run a specific module by name.


Authentication on the Server.
The server uses OpenSSL Certificates and DNS to ensure the server is who it says it is, and can be setup to use certs issued by certificate authorities or even self signed certs if the use-case fits. Requests to the server contain a request ID + a cryptographic signature of that ID, derived from the users private key. The server uses the client's public key to validate the request was issued by that user.

Adding users on the Server:
Users are added to the system by copying the user's public key to the server's .udon/keys/server-side keys directory. The filename is not important. The server is intended to be ignorant. Once a user's public key is on the server, the server identifies the key (and user) by the key's md5sum. The md5sum is used as the name of the database table for all messages sent to that key. The md5sum of a public key is also what client's use for commit() requests to tell the server where to store a message.

What is a message?
A message is composed of 6 parts, which directly map to 6 columns of a user's DB table on the server. This is referred to as the primary table. The primary table is what is synchronized when new messages are fetched. The table is identified by the md5sum of the user's public key. For example, examining a message table on the server by running the following select statement, would output something like the following


sqlite> SELECT * FROM 'b049e6ef06106051882400b303918c67' LIMIT 2;

ID TIME SRC MSG MSGSIG CHANNEL KEY
1 x'6543...' x'8792...' x'8523...' x'6545...' x'7254...' x'1152...'
2 x'3543...' x'8791...' x'9226...' x'3575...' x'7224...' x'2152...'

Every message is encrypted with a randomly generated Symetric encryption key. The Sym key is then encrypted by the recipient's public key and sent with the message. The SRC of the message is the md5sum of the sender's key. The recipient decrypts the KEY, and uses it to decipher all other fields of the message. Once the sender's public key ID (the SRC) is known, it can be loaded, and used in combination with the MSG contents and the message signature to validate/verify the message was actually sent by the person they say are. Messages are output to the user with [V] indicate this validation, otherwise the message is marked wtih [!].

Example: Basic usage of channel between Bob and Bender:

$ udon --poll bob_and_bender
Key: bob.pub - Local:41 Remote:42

$ udon --sync bob_and_bender
sync'd: 1

$ udon --read bob_and_bender -n 1
#42: 2026-04-08 10:06:02:004462
[V] bender.pub [bob_and_bender]
Hey bob, how did humanity ever think a 32 bit address space would scale?

$ udon --message bob_and_bender
> Hey, with IPv8, we should be able to address every galaxy in the universe.
>
Sending...
Sent: 2/2

$ udon --poll bob_and_bender
Key: bob.pub - Local:42 Remote:44

$ udon --sync bob_and_bender
sync'd: 2

$ udon --read bob_and_bender -n 2
#43: 2026-04-08 10:10:09:104682
[V] bob.pub [bob_and_bender]
Hey, with IPv8, we should be able to address every galaxy in the universe.

#44: 2026-04-08 10:15:01:172954
[V] bender.pub [bob_and_bender]
Considering how long it took to rollout IPv6, I won't hold my virtual breath.


First Release
It's nice to track a project by small milestones. And so, this blog post marks Udon's first beta release - version 0.01; Wu-Tang Name Generator dubs thee, Codename: Phantom Shinobi. Additional features for future work will experiment with file sharing, automatic channel join/leave, key exchange, in memory databases, and Post-quantum cryptography (PQC) algorithms, while attempting to keep the project minimal.

Wrapping up
I am not a security expert, but cryptography, and deeper thought about how/what we put on the wire, has been an enjoyable space to explore. What I hope for is not (yet another) software project to change the world, but a societal change where society manages the core technology of their own services. Everything else is just the infrastructure which should be owned as a public utility.

As already mentioned, this is just a hobby project under GPLv2. Feel free to use it, change it, fork it etc... Contributions and bug reports welcome and appreciated. Thanks for reading. Live long, and prosper.