Realtime Client Library API

Encryption

Ably client libraries support built-in symmetric encryption of message content, making it easier to build apps that encrypt content fully end-to-end. Whilst TLS is enabled by default and ensures that data is securely sent to and received from Ably, messages are not encrypted within the Ably system. Using the encryption feature of our client libraries ensures that message payloads are opaque, can never be decrypted by Ably, and can only be decrypted by other clients that share your secret key.

Getting started

Channels can be easily configured to automatically encrypt and decrypt all message payloads using the secret key provided in the channel options. Below is a simple example:

Ably.Realtime.Crypto.generateRandomKey(function(err, key) {
  var channelOpts = { cipher: { key: key } };
  var channel = realtime.channels.get('gin-log-cry', channelOpts);
  channel.subscribe(function(message) {
    alert('Decrypted data: ' + message.data);
  });
  channel.publish('unencrypted', 'encrypted secret payload');
});
Ably.Realtime.Crypto.generateRandomKey(function(err, key) {
  var channelOpts = { cipher: { key: key } };
  var channel = realtime.channels.get('gin-log-cry', channelOpts);
  channel.subscribe(function(message) {
    console.log('Decrypted data: ' + message.data);
  });
  channel.publish('unencrypted', 'encrypted secret payload');
});
key = Ably::Util::Crypto.generateRandomKey()
channel_opts = { cipher: { key: key } }
channel = realtime.channels.get('gin-log-cry', channel_opts)
channel.subscribe do |message|
  puts "Decrypted data: #{message.data}"
end
channel.publish 'unencrypted', 'encrypted secret payload'
ChannelOptions options = ChannelOptions.withCipherKey(<key>);
Channel channel = realtime.channels.get("gin-log-cry", options);
channel.subscribe(new MessageListener() {
  @Override
  public void onMessage(Message message) {
    System.out.println("Decrypted data: " + message.data);
  }
});
channel.publish('unencrypted', 'encrypted secret payload');
byte[] key = Crypto.GenerateRandomKey();
ChannelOptions options = new ChannelOptions(key);
IRealtimeChannel channel = realtime.Channels.Get("gin-log-cry", options);
channel.Subscribe(message => {
  Console.WriteLine("Decrypted data: " + message.Data);
});
channel.Publish("unencrypted", "encrypted secret payload");
ARTChannelOptions *options = [[ARTChannelOptions alloc] initWithCipherKey:<key>];
ARTRealtimeChannel *channel = [realtime.channels get:@"gin-log-cry" options:options];
[channel subscribe:^(ARTMessage *message) {
  NSLog(@"Decrypted data: %@", message.data);
}];
[channel publish:@"unencrypted" data:@"encrypted secret payload"];
let options = ARTChannelOptions(cipherKey: <key>)
let channel = realtime.channels.get("gin-log-cry", options: options)
channel.subscribe { message in
  print("Decrypted data: \(message.data)")
}
channel.publish("unencrypted", data: "encrypted secret payload")

Note that all examples on this page assume you are running them within an EventMachine reactor. Find out more in our Realtime usage documentation.

Note that the key should not be a pass-phrase, but a cryptographic key – generated from a secure random source, 128 or 256 bits long, binary or base64-encoded. If you wish to encrypt messages with a pass-phrase (for example, one entered by a user), you should use a key derivation function to transform that into a key. The client libraries are also capable of generating a random key for you.

Understanding encryption

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 CipherParams 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 256 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 the data attribute (payload) of published messages and presence member messages on a channel, over both REST and Realtime publish operations. Decryption is supported in Realtime message and presence message subscriptions and in REST and Realtime history operations.

All other attributes of messages and presence messages, such as event name or clientIdclient_idClientId remain un-encrypted. All sensitive data, when using the library’s symmetric encryption, must be placed in the data attribute to ensure it is encrypted before it is transmitted to Ably.

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 configured for the channel before the history request is made.

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

API Reference

View the Encryption API Reference.


Need help?

If you need any help with your implementation or if you have encountered any problems, do get in touch. You can also quickly find answers from our knowledge base, and blog.