Free and open source encrypted chat for iOS.

ChatSecure v4.0 - OMEMO and Signal Protocol

ChatSecure v4.0 - OMEMO and Signal Protocol

We’re excited to announce the release of ChatSecure v4.0, our largest step forward in usability since the addition of push messaging six months ago. The most significant new feature is OMEMO Encryption, a mobile-friendly encryption scheme pioneered by Conversations that adapts Signal Protocol to the XMPP world.

Using OTR on mobile has always been problematic because it was designed for desktop computers and synchronous conversations. For example, if you don’t have an active OTR session, you can’t start a new secure session if your contact is offline. Even if you do have an OTR session, it can go stale if one of the sides is purged from RAM due to low memory. This can lead to messages that disappear into the ether with no standardized way for the recipient to indicate which message they couldn’t decrypt.

OMEMO fixes all of these problems, and opens doors to new features that were impossible with OTR, like multi-client support, encrypted group chat, and more reliable file transfers. Multi-client conversations would work particularly well with our planned Desktop client, so we’re excited to add support for these features in future releases.

There are some other major changes in this release that improve the user experience, such as the outgoing message queue and enhanced identity management. The message queue automatically negotiates OMEMO and OTR sessions and allows you to resend messages in case of failure.

Image of Profile View

The new profile view allows you to view a contact’s OMEMO and OTR fingerprints, change each fingerprint’s trust settings, and modify the default encryption method. We’ve made important changes to the way trust is handled for new contacts by adopting the TOFU or “trust on first use” model. The first time you see OMEMO or OTR fingerprints for a contact, they will appear as trusted and marked with “TOFU” in the user interface. Any subsequent fingerprints will be untrusted and need to be manually verified. In this release you can compare fingerprints out-of-band by pressing on the cell and bringing up the system share dialog, but we plan to streamline the fingerprint comparison process in the future.

There are hundreds of other changes under the hood that fix bugs, improve performance, and enhance reliability. On the roadmap for v4.1 and beyond are improvements to group chat, including OMEMO encryption, multi-device chat history synchronization (XEP-0313 MAM), read receipts (aka chat markers XEP-0333), improved file transfer, and more.

We’re excited to see people experience this new frontier for XMPP usability. We will be working with the Zom project to bring OMEMO support to their suite of apps, and we expect other apps will start adopting OMEMO as well.

Thank you to everyone who helped make this release a reality!

Download on the App Store

Download ChatSecure on the App Store

Written By
Chris Ballinger

The End of ChatSecure Android

The End of ChatSecure Android

The developers of the Android version have hard forked the code and are no longer maintaining the upstream version. If you still use ChatSecure Android you should migrate to another app immediately. For a similar user experience and the best compatibility with the latest features of ChatSecure iOS, we recommend downloading Conversations.

The development of ChatSecure iOS is unaffected by this change and we will continue to release new features and updates.

Written By
Chris Ballinger

ChatSecure iOS v3.2.3 - XMPP Push

ChatSecure iOS v3.2.3 - XMPP Push

We’re excited to announce that XMPP push (XEP-0357) is now available, finally allowing users to receive push messages from any contact. This feature is only available when used with compatible XMPP servers, and requires special modules to be enabled for Prosody (mod_cloud_notify) or ejabberd (mod_push).

Our next release will focus on OMEMO support for multi-device asynchronous end-to-end encryption, which will provide huge usability gains over OTR on mobile devices. Thankfully the GPL + App Store licensing issues concerning SignalProtocol have been resolved. You can try OMEMO today in other apps such as Conversations, Gajim, and Cryptocat.

v3.2.3 changes:

  • XMPP push for supported servers (XEP-0357)
  • Improved subscription requests UI
  • Basic vCard nickname support
  • Fix issues with missing messages during stale OTR sessions
  • Improved IPv6 support for NAT64/DNS64
  • Fix some issues with presence/availability
  • Added button to view your password
  • Fix issue where message view would appear multiple times
  • Automatically start OTR sessions when contact is online
  • Send error messages back to contact when messages cannot be decrypted

Download on the App Store.

Written By
Chris Ballinger

ChatSecure iOS v3.2 - Decentralized Interoperable Push Support

ChatSecure iOS v3.2 - Decentralized Interoperable Push Support

With the release of ChatSecure iOS v3.2, we have enabled the first phase of a new form of push messaging that is decentralized, interoperable, and reduces identifiable metadata. Users of any app compatible with the ChatSecure Push protocol can send push messages across app boundaries, starting with the latest release of ChatSecure iOS and the next version of Zom Messenger. These push messages currently contain no content and are simply a way to wake up the receiving client for ~20 seconds.

Unlike centralized messaging applications like WhatsApp, Signal or Telegram, a core part of our mission is to allow users to connect any XMPP server of their choice and to encourge users to run their own servers. This privacy win also comes with a major drawback for iOS users, because Apple prevents the application from running in the background. The only way push messages can be sent are through servers run by app developers themselves, which presents a problem when trying to support push for any arbitrary XMPP server.

Example Flow

Alice ([email protected]) and Bob ([email protected]) are both using the ChatSecure iOS app to communicate via their private XMPP server After each OTR session is established, they each send a payload inside the OTR channel that contains a fresh token and their push API endpoint. The token is used by the API endpoint to lookup your device APNS token, and the endpoint parameter is what allows this to work between apps from different developers. Because all of this data is exchanged by the clients themselves, our push server has no idea about the JIDs of Alice or Bob, or where any of the tokens ended up.

Contact Offline

The next time Alice opens the app and she wants to talk to Bob, she sees that Bob is offline.

Knock Sent

On the chat screen there is now a new button called Knock that has replaced the Send button when the contact is offline (and no text is entered). By pressing Knock, it looks up the token and endpoint that Bob gave her earlier, and sends a HTTP POST to that endpoint with the token.

Contact Online

About 5 seconds later Bob’s client will wake up in the background and automatically login to his XMPP account.

Knock Received

His device will also receive back the token he gave to Alice, do a local lookup to see that the incoming push is coming from Alice, and show a local notification visibile on the lock screen. We are able to keep the app open for about 20 seconds in the background, which is enough time for Alice to establish a new OTR session and send a few messages.

Improving the UX

Having a Knock button is not the ideal user experience because it’s a foreign UI concept and not immediately clear how it works. Originally we tried to automatically trigger knock messages, but hit issues with missing messages caused by sending messages to offline contacts, or when in a stale OTR session. Our message pipeline needs to be reworked to handle these cases and ensure that no message ever enters a black hole.

There is a relatively new way for XMPP servers to interact with app push gateways called XEP-0357 but not very many servers support this extension right now. Our current solution works immediately with any XMPP server as long as you’re both running a ChatSecure Push compatible client. In the future we will roll out client support for XEP-0357 to allow you to receive pushes from any contact, as long as you’re connected to a compatible XMPP server.

The Road Ahead

Although OTR has proven to be trustworthy over the years, it is showing its age in the face of more modern protocols like SignalProtocol (formerly known as Axolotl). Originally we wanted to integrate Axolotl/OMEMO but we haven’t been able to acquire a license from Open Whisper Systems. The next post will be about our plans, in collaboration with the Conversations team, to implement a revision of OMEMO that supports Olm instead of SignalProtocol.

Written By
Chris Ballinger

Better XMPP Identifiers - Ed25519 Public Keys and .onions

Better XMPP Identifiers - Ed25519 Public Keys and .onions

In a future version of ChatSecure I’d like to introduce a human-usable implementation of using entire public keys as identifiers. We are already experimenting with appending a portion of your OTR fingerprint to your XMPP username, but I’d like to take it a step further using some of the latest advances in ECC.

The Current State of XMPP Identifiers

Right now identifiers for XMPP-based apps (JID) are currently in the form:

Where whichever person who first registered username on owns that identifier, similar to an email address. Even this basic level of complexity can be confounding for most non-technical people I’ve come across, so we’ve been doing what we can in our UX to relieve this complexity.

One of the main ways we’ve been simplifying things has been to implement QR-code and URL-based invite links of the form:<base64 encoded JID + OTR fingerprint>

Which shows invited contacts links to download the apps if they don’t have them, or directly opens ChatSecure to the add contact screen (with a somewhat-verified OTR key!).

Ed25519 Public Key Cryptography

The great thing about Ed25519 signing keys, is that that the whole public key can fit into 32-bytes. That’s equivalent to 32 ASCII characters (between 0-255). To allow for a more seamless representation (non-alphanumeric ASCII characters can be a bummer), you can use hex, for example:


This is 32-bytes of random data from, which in theory could represent an entire Ed25519 public key. Using other encodings such as Base64 can result in an event shorter output:


But unfortunately XMPP JIDs don’t play well with Base64 because JIDs are case-insensitive. We can, however, use Base32 to shrink the size while still maintaining compatibility with XMPP JIDs:


Now that we have our username portion, let’s solve the other big problem with XMPP JIDs… the server.

Let’s Get Rid of XMPP Servers

Although there are some trustworthy XMPP servers out there, you can never be more secure than hosting your server yourself on hardware you own. Traditionally this has been a problem for non-technical users. Asking them to SSH into their headless Raspberry Pi to apt-get install prosody won’t get you the results you’d want.

For technical users, on the other hand, one of the main problems has often been the lack of a publicly reachable IP address. Fortunately by utilizing Tor .onion services, you can have a reachable address from anywhere, even behind carrier-grade NAT (like on a cellphone)!

.onion addresses are an 80-bit number represented in base32 and look like this:


The above example is the XMPP server’s .onion address.

Similar Work

A similar approach to the .onion endpoints has been taken by the Ricochet project.

They replace both the username and server with the .onion address itself. The main drawback (or feature, depending on your viewpoint) is that it’s a ground-up rewrite of a full stack chat client, which means no interoperability for existing XMPP clients.

Pond also operates in a similar way as far as .onion addresses, but as far as I know there’s still only a rudimentary GUI and command line client, which limits its usefulness to very technical users.

My approach would be completely backwards compatible with existing XMPP clients, where you could use the same Ed25519 identifier on multiple servers (including your own .onion) to ensure reachability by all of your contacts, regardless of their client of choice.

A Glorious Dawn

Using this new public key identifier, you can sign your other cryptographic identities and identifiers, and upload the results to, or wherever. New contacts can automatically verify your identity, and can use our new QR-code invites and links to avoid typing these long strings.


This above example could be your fully valid JID containing your public key and personal .onion address. Because no human would ever type that in, we can share it in link form:

You can still have a human-readable username in your XMPP vCard, so you can choose whatever ‘username’ you’d like without creating a collision. You can also upload signatures of your OTR, PGP, or Axolotl identities (using this same Ed25519 key) to your vCard to help contacts auto-verify your cryptographic identity.

Contrived Example

Bob serendipitously meets Alice in a crowded bar and they instantly hit it off by talking about obscure cryptographic protocols. A loud band starts playing and they have difficulty maintaining conversation, so they decide to move their communication to a secure channel.

Bob opens up the latest version of ChatSecure, and tries to share his Invite URL to Alice’s phone via a secure Bluetooth LE channel. Due to the crowding of the 2.4 GHz channel, they have trouble establishing a connection, and decide to switch to QR codes, which should work well in the dim lighting.

Alice successfully scans Bob’s QR code Invite URL, which opens up her browser to, where she sees how to download the latest version of ChatSecure. Once the app finishes downloading, she clicks the same link again, but this time instead of opening her browser, it opens ChatSecure to the Add Contact screen. Bob’s account details are shown on the screen, and she can see his other cryptographic identities being pulled down in realtime from Keybase.

Now that they have established a secure channel, they decide that this music is too loud anyway, and it would be a good point to leave the bar and drink some coffee at one of their apartments. An encryption success story!


This is just one of many exciting changes I want to bring in the months ahead. Coming very soon will be a new iOS release with group chat, slick onboarding, and… push notifications. 🚀

Stay tuned!

Written By
Chris Ballinger

‹ Newer Older ›