Skip to content
chrisballinger edited this page Oct 16, 2014 · 13 revisions

Bluetooth LE Mesh Chat Spec

This project is an experiment to see if it's possible to build a usable offline sneakernet using Bluetooth LE. Will it work? Who knows!

Goals

  • Use the Bluetooth 4.0 Low Energy APIs on iOS and Android to allow for pairing-free promiscuous background synchronization for anyone with a protocol-compatible app installed.
  • Be a 100% sneakernet protocol, with absolutely no internet functionality.
  • Use modern crypto (via libsodium) that's tailored to the limitations of BLE and an ultra-high latency, unreliable sneakernet.
  • Implement a familiar and friendly Twitter-style UI/UX with a public feed, replies, reposts and (maybe) direct messaging.
  • Only show Gravatar-style avatars and hashes for other's identities until you verify keys in person, and somehow make this process seem enjoyable.

Unsolved Problems

  • How do you prevent people from tracking your daily movements and public key all the way back to your house? Maybe allow for multiple disposable identities per device, and a geofence / privacy radius that won't share your identity with untrusted peers within certain sensitive areas.
  • Is it possible to achieve some level of forward secrecy for DMs given the extreme latency and unreliable delivery? Maybe exchange a bunch of disposable Axolotl-style pre-keys after verifying people in person.
  • Given that someone could create modified clients to sniff and record geo-location information, would it make sense to have "nothing to hide" and do something crazy like include a low-accuracy public geohash with every message and build that into the user experience?

Protocol Description

Definitions

Global

  • version: Spec version, 1 byte
  • timestamp: Current 64-bit Unix timestamp, 8 bytes
  • signature: 512-bit Ed25519 signature, 64 bytes
  • sender_public_key: Your 256-bit Ed25519 public key, 32 bytes
  • sender_private_key: Your 512-bit Ed25519 private key, 64 bytes

Identity

  • display_name: desired nickname, 35 bytes

Messaging

  • message_body: UTF-8 message body, 140 bytes
  • reply_signature: signature of message you're replying to, 64 bytes

Direct Messaging

  • mac: message authentication code (crypto_box_MACBYTES in libsodium), 32 bytes

Data Packets

All text fields are UTF-8 and padded with " " (0x20) if shorter than the max length. All protocol data is always versioned, timestamped and signed in its entirety by your private key.

All data packets follow this format:

[key=#bytes]
[[version=1][timestamp=8][sender_public_key=32][payload_data=n]][signature=64]
signature = sign(version + timestamp + sender_public_key + payload_data, sender_private_key)

There is a constant 105-byte overhead for each data packet comprised of version, timestamp, sender_public_key and signature.

Identity

Your identity is revealed on the first read to the identity characteristic. Your public key is your unique identifier, and the display name can be anything. Subsequent reads give other people's identities signed by your own.

Your Identity (140-bytes):

payload_data: [display_name=35]
full: [[version=1][timestamp=8][sender_public_key=32][display_name=35]][signature=64]

Propagated Identities (245-bytes):

payload_data: [others_identity=140]
full: [[version=1][timestamp=8][sender_public_key=32][others_identity=140]][signature=64]

Public Messages

All public messages flowing over the network will have the following format. They are uniquely identified by their signature.

payload_data: [message=140][reply_signature=64]]
full: [[version=1][timestamp=8][sender_public_key=32][message=140][reply_signature=64]][signature=64]

Broadcast

Messages with valid message but empty reply_signature are considered general broadcast.

Replies

Messages with both message and reply_signature are considered replies to the original message.

Upvote/Repost

Messages with an empty message but still containing a valid reply_signature are considered upvotes/reposts.

Direct Messages

Convert Ed25519 keys to Curve25519 for authenticated asymmetric encryption.

{} denotes ciphertext encrypted to destination_public_key
payload_data: [destination_public_key=32][mac=32]{[message=140]}[reply_signature=64]
full: [[version=1][timestamp=8][sender_public_key=32][destination_public_key=32][mac=32]{[message=140]}[reply_signature=64]][signature=64]

This example doesn't yet provide forward secrecy. The performance characteristics of a BLE-only mesh may prevent PFS from working reliably.

Acknowledgement / Delivery Receipt

When a direct message is received, a reply to the sender with an empty message body will be sent to acknowledge the message has reached its destination. When clients who are forwarding direct messages see there has been a reply_signature that matches the original message's signature, it should check to see if the reply's signature is from the correct destination_public_key. If it matches, the original message can be deleted and cease propagating through the network.