Security controls have been designed into Ditto from the beginning. All communications are consistently protected by strong and modern encryption, whether it is via the Internet or via Bluetooth. Cryptographically-signed business rules ensure users can only sync data that they are permitted to access. The app developer is in complete control of the keys, certificates and rules.

Capability Type

TLS 1.3

Authentication EC keypairs with signed certificates
Trust infrastructure X.509 with a developer-controlled certificate authority
Access Rules Regex patterns that define read/write rules for collections and document IDs


Every installation of an app that uses Ditto has its own identity. When you start prototyping with Ditto you can use a development identity, which contains default settings and offers no real security. Once you are ready to deploy, this can be swapped for a production identity where security is enforced.

An identity is a bundle of device and app-specific information:

  • Site ID - A number unique to this device.
  • App Name - A name identifying the application. This avoids different Ditto-enabled apps trying to sync with each other. Like iOS App IDs, this takes the form of a domain name. Example:
  • Access Rules - Define which documents this device is allowed to read or write during sync.
  • Private Key - A secret for authenticating as this identity.
  • Identity Certificate - A certificate verifying the particulars of this device, signed by the CA.
  • CA Certificate - Used to verify certificates presented by other devices with the same app.

Production Development
Site ID

Allocated by central authority

Defaults to a random number; can be customized

App Name Set by central authority

Defaults to ""; can be customized

Access Rules Set by central authority

All devices may read/write all documents

Private Key Either generated on device, or distributed by central authority

Hard-coded and shared by all devices

Identity Certificate Unique and signed by central authority; contains this device's public key

Hard-coded and shared by all devices

CA Certificate

Shared by all users of the same app

Hard-coded and shared by all devices


Ditto identities and public keys are distributed in the standard X.509 certificate format. They do not directly contain potentially sensitive data such as access rules.

Ditto does not commit you to any workflow for managing identity data and certificates. When you are ready to start using production identities, contact the Ditto team through the Ditto Portal and we will help you set up the right CA tooling for your use case - or provide specifications so you can build your own.

Shared Secret Security

Ditto offers an intermediate-level of security for applications where all users and devices are trusted. For example, this could be appropriate for an enterprise application run on centrally managed devices. In this mode, every device knows the same secret key, and uses this to validate incoming connections. The benefit of this approach is that distinct certificates do not have to be distributed to every device, simplifying the deployment considerations.

To generate a shared secret, use this command with OpenSSL:

openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -outform pem | openssl pkcs8 -topk8 -nocrypt -outform der | base64 -w 0

At time of writing, this command works on Linux machines with an up-to-date OpenSSL but not with the LibreSSL distributed on Macs. See openssl version.

You can then pass in the base64 encoded DER when creating an identity for Ditto:

let p256DerB64 = "<base64 DER string>"
let identity = DittoIdentity.sharedKey(appName: "app", sharedKey: p256DerB64)
Ditto(identity: identity)
NSString *p256_der_b64 = @"<base64 DER string>";
DITIdentity *identity = [[DITIdentity alloc] initWithAppName:@"app" sharedKey:p256_der_b64 siteID:nil];
DITDitto *ditto = [[DITDitto alloc] initWithIdentity:identity];
val p256DerB64 = "<base64 DER string>"
val androidDependencies = DefaultAndroidDittoDependencies(context)
val identity = DittoIdentity.SharedKey("app", p256DerB64, null)
Ditto(androidDependencies, identity)
String p256DerB64 = "<base64 DER string>"
DefaultAndroidDittoDependencies androidDependencies = new DefaultAndroidDittoDependencies(applicationContext);
DittoIdentity identity = new DittoIdentity.SharedKey("app", p256DerB64, null)
Ditto ditto = new Ditto(androidDependencies, identity);
String p256DerB64 = "<base64 DER string>";
var identity = DittoIdentity.SharedKey("app", p256DerB64);
Ditto ditto = new Ditto(identity);
std::string p256_der_b64 = "<base64 DER string>";
Identity identity = Identity("app", p256_der_b64);
Ditto ditto = Ditto(identity);

Shared secrets are not supported by the JS SDK yet.

App-level Security

The access rules contained in the identity are rigid, signed by the central certificate authority, and enforced by all participating devices. This offers the highest level of security. If a person is not allowed to access particular data, it will never be synced to their device.

For apps with weaker security requirements a developer may choose to relax the access rules for Ditto, then restrict access in their application code.

One advantage is that the developer has more flexibility to change the access rules dynamically, since they are not encoded in signed certificates. Another advantage is that all devices in the mesh can participate in syncing the data, which may help it propagate faster. If certain data is only accessible to a few privileged devices which are not often in range of each other, it will take longer for them to sync.

The disadvantage is that an unprivileged user does have a device containing privileged data. A technically savvy user or phone thief may be able to gain access to not only their regular data, but also the more privileged data that they were never intended to able to view.

Therefore relaxed access rules - app-level security - are only suitable for environments where there is a degree of trust that the devices won't end up unlocked in the wrong hands.