Please be aware that you are viewing our bleeding edge unstable documentation. Unless you wanted to view the bleeding edge (and possibly unstable) documentation, we recommend you use our stable docs.

Go to Ably's stable canonical documentation »

I know what I'm doing, let me see the bleeding edge docs »

You are viewing our bleeding edge unstable documentation. We recommend you use our stable documentation »
Fork me on GitHub


Ably client libraries support encryption of message content, making it easier to build apps that encrypt content fully end-to-end.

Objectives and Scope

The libraries support encryption purely as a convenience; the libraries ensure interoperability between environments by having compatible implementations of encryption algorithms and by making common choices on format, mode, padding etc. However, Ably intentionally does not manage the distribution of keys between clients, and end-to-end encryption is enabled without exposing keys to the Ably service at all. This has the advantage that Ably demonstrably has no access to the un-encrypted contents of your messages, but also means that each app is responsible for enabling the distribution of keys to clients independently of Ably.

The client library support for encryption supports symmetric encryption only, and requires each participating client to each specify the correct secret key when creating a Channel instance. Clients that do not specify a key will be delivered the still-encrypted message payloads that they may then still wish to decrypt offline.

The client libraries are designed to be extensible, but initially only support the AES algorithm (with a default key length of 128 bits) and CBC mode. These defaults are intended to ensure that encryption support can be provided in all target environments and platforms.

Encryption is supported for both REST and Realtime publish operations and presence data payloads. Decryption is supported in Realtime message subscriptions amd presence events and in REST and Realtime history operations.

The key in use at any given time is known by the client library, but the Ably service has no visibility of the key; it knows only that a given message payload was encrypted. When accessing messages via the history API, it is the caller’s responsibility to ensure that the correct key is used for the requested interval.

Only message data payloads are encrypted, all other message data and metadata is not encrypted; for example the clientId and event name. This means that messages with a specific event name can still be routed by the library to the correct handler even if the recipient does not have the key; the encrypted payload data is delivered instead. Furthermore, the message encoding attribute is simply regarded as metadata just like other message metadata.

Encryption options (algorithm, key, etc) are specified on a per-channel basis; it is expected that apps will wish to have both un-encrypted and encrypted channels on a single connection.

Encrypted message format

Message representation

All Ably messages carry their payload in a data member, with various supported data types. A given encrypted message can be exchanged using either the binary or JSON protocol and encryption and decryption are interoperable between the representations.

In the case of the JSON encoding, the data member either contains the data value directly (either a String, JSON Object or JSON Array) or contains an encoded string value, with the encoding specified in the encoding property of the message. For un-encrypted messages, the type is implicit, or is implicitly a binary buffer when an encoding is present.

In the case of a JSON encoded encrypted message the data member always carries the encrypted message payload as a base64-encoded string and the encoding member contains the string cipher+aes-128-cbc/base64.

Therefore in the JSON encoding, an encrypted message is represented as follows:

  "id": "<unique message ID string>",
  "name": "<name>",
  "timestamp": <timestamp>,
  "data": "<string containing base64-encoded representation of encrypted data>",
  "encoding": "cipher+aes-128-cbc/base64"


Each possible data value type is canonically converted to a byte array before being encrypted, as follows:

the utf8-encoding of the string, without any trailing null byte
the unmodified buffer contents
the utf8-encoding of the JSON-stringified value of the object
the utf8-encoding of the JSON-stringified value of the array

Conversion to ciphertext

Conversion from plaintext to ciphertext requires the following steps:


All of the client libraries have identical encrypted message payload tests to ensure client libraries across all platforms encode and decode messages in binary compatible formats. See the encoding tests for

Back to top