Skip to content

Binary Extensions (BEX) Draft

Joshua Achorn edited this page Nov 7, 2018 · 19 revisions

BEX is a format designed to add additional functionality to Cryptodog.

Rather than replacing and/or modifying Multiparty and OTR, it uses them as a vehicle for the transmission of BEX metadata.

This draft has not yet been finalized. Feel free to offer suggestions, concerns and comments to improve it.

Format

[ 0-3 ] magic bytes
[ 4-? ] Submessage count (varint)
 [ ? + 0 ] Submessage header (varint)
 [ ? + ? ] Submessage data (length of header type)

BEX makes use of non-UTF8 binary messages (which are currently ignored by Cryptodog clients) to transmit metadata.

Other than saving a few bytes of ciphertext, why should we use a binary format instead of JSON messages, which are already used for other things? -GH

By using a binary format, we can retain compatibility with the existing messaging system which ignores non-UTF8 messages. Also, using JSON messages can lead to users being misled into entering potentially malicious JSON metadata into the message field (browsers prevent copy-pasting binary strings) -JA

In this document, "varint" refers to a LEB-128 unsigned integer field.

"varint-prefixed string" refers to a UTF-8 encoded string prefixed by its length encoded as a varint.

Serialization of varints in JavaScript can be provided by this library: etc.

Each BEX message is prefixed with the "magic" bytes 0xBB, 0x0E, 0xFF to separate it from a UTF-8 Cryptodog message.

Then, a message contains a header describing how many sub-messages it contains.

What follows is the submessages. Each submessage contains a header varint.

The value of this header determines the length of the submessage's body.

Submessage Types

  • 0: unknown / failure

Users should not ever send a unknown header, as it is a reserved value for handling non-BEX messages.

This message has no body.

  • 1: change color

This is a message a user sends when they want to change their display color.

This message's body is 3 bytes which are converted into a 6-character hexadecimal string, which is an HTML color code. For instance, a body 0xAA, 0xBB, 0xCC means the HTML color #AABBCC.

  • 2: change status

This message transmits a change in a user's status. The body is a varint-prefixed string. e.g. away, online

If we're trying to save bytes, why not just use a 0 or 1 bit, since there are only 2 states? -GH

This makes sense. XMPP allows for a multitude of statuses, whereas Cryptodog only assumes a user is of one or two states. Cryptodog should still send "online" XMPP statuses (as it appears to break connectivity to disable this), while a user clicking an away/online button should trigger the transmission of the away/online bit state through BEX, changing the UI states of the user's peers. -JA

  • 3: composing notification

This is a message a user sends when they want to notify a peer that they are currently composing a text message.

This message has no body.

  • 4: paused notification

This is a message a user sends when they want to notify a peer that they have stopped typing.

This message has no body.

  • 5: file attachment

This message is sent when a user has uploaded a file ciphertext successfully to a BEX Attachment Server. (Refer to File Attachments to learn how to use this)

This message's body is as follows:

[0 - 32]  Encryption key
[32 - 56] Encryption nonce
[56 - ?]  File MIME type (varint-prefixed string)
[?  - ? + 16] File UUID      (16 bytes)
  • 6: text message

This message provides a special method for sending typed UTF-8 strings through BEX.

[0 - ?] Text type  (varint-prefixed string) (e.g. json, html, markdown)
[? - ?] Text value (varint-prefixed string 
  • 7: i am a bot

This message should be sent by bots to signify that they are bots, so users that do not like viewing automated messages can opt out of conversing with them. Also, this helps bots avoid interpreting messages from other bots as commands, leading to an infinite cycle of request and reply.

This message has no body.

File Attachments

A reference Go implementation of a BEX Attachment Server can be found here: bex-attachment-server

To send a file, a user must first load it and determine its MIME type.

Then, generate a 24-byte random nonce and a random 32-byte key.

Use the NaCl secretbox cryptosystem to seal the file data with the key and nonce.

Then, make a request to a BEX Attachment Server. Any Cryptodog conversation MUST have the same BEX Attachment Server URL to work.

Make a POST request to {Server URL}/upload?cl={the length of the encrypted ciphertext}

with the ciphertext as the request body.

If the upload was a success, the server will reply with 200 Status OK and a 16-byte UUID as the response.

The server may respond with the following HTTP status codes:

  • 400 Bad Request

If your request was malformed.

  • 429 Too Many Requests

If your IP has sent too many requests recently.

  • 409 Conflict

If the number of bytes received by the server did not match the ciphertext length URL parameter cl in the request.

What's the point of that parameter? HTTP already has Content-Length as a header, which should be sent with any POST upload. -GH

  • 500 Internal Server Error

If the server has run out of disk space and was unable to free any up, OR if the server is malfunctioning.

Once completed, you can send a BEX submessage like this:

 header:              file attachment (5).
 fileEncryptionKey:   (your 32-byte key)
 fileEncryptionNonce: (your 24-byte nonce)
 fileMIME:            (your file's mime type as a varint-prefixed string)
 fileID:              (the UUID you recieved from the server in binary form)

Receiving Attachments

Once you receive a BEX file attachment submessage,

You can request the Attachment Server like so:

GET /files/{fileID UUID in text representation}

If the response code is 200 OK, it will have the complete attachment's ciphertext. You can decrypt it using the NaCl secretbox cryptosystem and fields provided in the BEX submessage.

If the response code is 404 Not Found, the file has been deleted by the server to save disk space.

Clone this wiki locally