Definitions #
- XBee®: the family of radio modules currently in use made by Digi International.
- Beenode: a node in the Beechat network. It consists of an active XBee router in the network. The Beenode is simple if it only re-routes data (such as a relay), and complex if it also sends data (such as an end user).
- Beechat Address (BA): a 12 byte array calculated from BLAKE3(DilithiumPublicKey).
- NodeID: a user modifiable field in the XBee radio, which is visible to other Beenodes.
- BLAKE3: the hashing algorithm in use
- Dilthium: the post-quantum asymmetric digital signature algorithm. Each user has one private key for each public key.
- Kyber: the post-quantum asymmetric key exchange algorithm. Each user has one private key for each public key.
- secretKey: a secret key created with a Kyber public key.
- shareableKey: a key that can be shared publicly. It is an encapsulated secretKey. Only the owner of the Kyber private key can decrypt it and extract the secretKey.
Registration on the network #
Our Beechat Address (BA) is a 12 byte array calculated from BLAKE3(DilithiumPublicKey). While using a Beechat Clip, we set the NodeID of our XBee module to our Beechat Address.
Upon registration on the Beechat app, our node sends a broadcast to all reachable nodes on the network of our BA.
Other devices will store our registrationString in their unconfirmedNodes arraylist.
Unconfirmed contact #
To add a contact, we must have first received the BA of someone else. When refreshing the devices list, we may find a Hardware Address and NodeID Address in the devices list that matches an object in the unconfirmedNodes arraylist. If their NodeID also matches the BA of the same registrationString, we begin a “Node Challenge”.
Beenode challenging #
Once a NodeID is matched to a registrationString, our Beenode challenges that remote Beenode to find out if they own the correct Dilithium private key.
- Our Beenode creates a random number of 32 bytes (or 256 bits) length, then, we hash it with BLAKE3. This is the randomHash.
- Our Beenode sends the randomHash to the remote Beenode.
- Remote Beenode’s app must sign the randomHash with the Dilithium private key and send the signed randomHash + full Dilithium public key back to us. (up until this point we only had a hash of the public key)
- Our Beenode takes the just received Dilithium public key from the response and verifies the signed randomHash matches the randomHash we sent. If it matches, the identity has been fully verified.
Key exchange with a remote Beenode #
Before having a key exchange with a contact, we must have verified them, and they must have verified us. A key exchange is the act of our Beenode and a remote Beenode agreeing on an AES-256 key to encrypt messages before they are sent through the network. The key exchange may be initiated by the first Beenode that wants to send a message and is done as follows, in this example we are the first to message the remote Beenode:
- The remote Beenode creates a Kyber keypair, signs the Kyber public key with their Dilithium private key, and sends the signed Kyber public key to us. Our Beenode verifies the Kyber public key with the Dilithium public key of the remote Beenode.
- We take remote Beenode’s Kyber public key and create a secretKey and shareableKey.
- We send the shareableKey to the remote Beenode.
- Remote Beenode decrypts the shareableKey with their Kyber private key and sends the Dilithium signed “AOK” string to our node confirming the key exchange was successful.
- We verify the “AOK” message with the Dilithium public key. If verified successfully, our Beenode, and remote Beenode, enable sending messages between two devices on the front-end.
- All the following messages are encrypted using secretKey as input into a BLAKE3 256-bit hash. The resulting hash is used as the AES-256 password.
Packets #
A Digimesh packet can contain up to 73 bytes of data. We divide packets into sections containing various types of data so it can be properly processed.
Packet structure
Type | Part number | Total size | Hash | Payload |
1 byte | 4 bytes | 4 bytes | 2 bytes | 62 bytes |
Available packet types
Label | Value | Description |
MESSAGE_DATA | 0x1 | Payload contains a text message part or whole message |
FILE_DATA | 0x2 | Payload contains a file part |
DP_KEY | 0x3 | Request to Dilithium public key |
SIGNED_HASH | 0x4 | Response / Signed randomHash |
KP_KEY | 0x5 | Request a signed Kyber public key |
CHIPHER | 0x6 | Return shareableKey |
INFO | 0x7 | Information packet |
FILE_NAME_DATA | 0x8 | Payload contains a file name |