-
Notifications
You must be signed in to change notification settings - Fork 8
Binary Extensions (BEX) Draft
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.
[ 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.
- 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.
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)
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.