Testing the incredible claims made by developers of an encrypted messaging application

Testing the incredible claims made by developers of an encrypted messaging application


This article has been translated from its original publication at https://habr.com/ru/companies/productivity_inside/articles/737752/

Recently, I heard the following in a podcast:

"I use the Converso app because I care about security, and all other apps that claim to prioritize security look like NSA in comparison. With Converso, you can rely on end-to-end encryption, messages are not stored on the server, and there is no user data or metadata..."

No metadata? That's an extremely bold and intriguing promise. Even Signal, which is considered the gold standard for message encryption with its Double Ratchet and X3DH components, still leaks a lot of metadata.

The company's website and custom interviews (a fragment of one can be listened to here) make other grand statements, so I became curious about how the developers actually fulfill all the promises they make.

It seemed self-evident to me that applications with end-to-end encryption cannot eliminate the need for an intermediary who receives an encrypted message from one party and forwards it to another. This process inevitably involves the generation of metadata, such as information about who you were talking to and when it happened. However, according to the creators of Converso, their messages are "bypassing" the servers and leaving no trace.

As far as I know, the only way to eliminate the intermediary from the scenario is to switch from a "client-server" model to a peer-to-peer "client-client" model, but this is associated with a range of problems:

  • The sender and receiver must be online simultaneously. Sending a message to an offline user won't work, and the ability to asynchronously exchange messages with users who are offline is considered a basic requirement for modern chat applications.
  • Both parties need to establish a direct connection with each other, and they are likely sitting behind NAT routers. Moreover, how do they find each other based on IP addresses to begin with? There is hole punching, of course, but even with that, reliance on a third party for mediation during the connection is required.

Unfortunately, Converso's code is not publicly available, and the website doesn't mention anything about cryptographic primitives and protocols, which is quite atypical for an app with "cutting-edge" security methods, according to their own claims. In comparison, Signal, WhatsApp, and Telegram have provided the public with detailed explanations of the technical implementation of their end-to-end encryption systems, and these have been officially tested and evaluated by third-party experts. However, the creators of Converso state that they are waiting to obtain a patent before making the code open.

Therefore, there remains only one way to familiarize oneself with the internal processes - reverse engineering or decompilation. So, I looked into the Converso Android application to verify the company's claims and roughly compare their original encryption protocol with existing ones used in services for exchanging encrypted messages, like Signal.


Screenshots of the conversoapp.com/ and conversoapp.com/about-us/ pages.

Getting the APK

Before opening the application, I decided to inspect its contents. I downloaded the APK and looked inside.

Fortunately, the application is written in JavaScript (React Native). The index.android.bundle file contains the entire application code and most of its dependencies. It has been minified but is still readable.


Contents of the Converso package

Let's start with a few searches. Let's see which domains are mentioned in the code.

The first thing I noticed was that they included a measurementId in the Firebase configuration file. This is an optional field that developers can enable to track usage with Google Analytics. It's not necessarily a bad thing, but it seems out of place in an application that claims to "not use any user data at all."

Then I saw another interesting domain name: zekeseo.com. It appears to be another website owned by the creators of Converso, offering SEO and marketing services. It's strange to see it here.

In short, the code tells us that usernames without the "@" symbol will be transformed by the application into email addresses by adding "@zekeseo.com". I assume something in the application, probably the backend, requires usernames to have an email address format, but there is nothing like that in the frontend.

Next, there is a mention of a URL on Pixabay. It seems to be a fallback URL for the user profile picture. I'm not sure why an external resource was chosen. It seems like an oversight to me.


Default user profile picture downloaded from cdn.pixabay.com.

Searching for encryption in the code

When I started looking for cryptographic primitives, I found mentions of AES and RSA. I expected to see elliptic curve cryptography because I haven't come across modern encryption protocols that use something else.

Either way, it seems that messages are indeed encrypted, as evident from the function names encryptMessage and decryptMessage. That's not bad, but there's no guarantee that this encryption is providing any real security. How are the messages encrypted? How are the encryption keys generated and distributed? How often are the keys changed? How is authentication done for keys and messages? And how do the encrypted messages travel from sender to recipient?

While browsing the code near the aforementioned encryption functions, I noticed mentions of Seald and an API stored on the subdomain seald.io.

Just a quick look at the Seald homepage is enough to get answers to many questions. Seald is a ready-made SDK for developers that allows seamless encryption to be integrated into "any application in minutes."

Now it's clear: the Converso developers didn't create any groundbreaking encryption protocol; they simply implemented this SDK. All encryption-related components of the application are entrusted to Seald.


Seald Homepage

However, this still doesn't explain how Converso and, in turn, Seald manage to transmit messages without storing them on the server or collecting metadata. Does the Seald SDK really provide Converso with the ability to do everything they promise?

Fortunately, the answer to this question can be found in the developer documentation from Seald. There's no need to dig into the Converso source code anymore.

Encryption Principle in Converso: What's Claimed and What's True

Here's what happens when you send a message to another user on Converso:

  1. The sender retrieves the recipient's public RSA key (Pk) associated with their phone number from the Seald server and considers it authoritative.
  2. The sender encrypts the message (M) using AES-256-CBC with an ephemeral symmetric encryption key (K).
  3. The sender encrypts K using RSAES-OAEP so that only the owner of Pk can decrypt it.
  4. The sender constructs a message authentication code (Mac) for message authentication using HMAC-SHA-256.
  5. The sender sends the Mac in plaintext, as well as encrypted copies of M and K, to the server via a network request. Later, the server delivers what was sent to the recipient.

That's essentially it. There are no peer-to-peer networks involved; the application uses a classic "client-server" architecture.

Now that we understand how the encryption protocol in Converso works, we can examine the claims they make on their website and check how well they align with reality.

Note from May 13, 2023: Since the publication of this article, many of these claims have disappeared from the internet. Below, we provide literal quotes that were previously found on the Converso website and official marketing materials.

Claim: "The most advanced encryption tools"

Verdict: False

Screenshot from the conversoapp.com/about-us/ page.

For an encryption standard to be considered "the most advanced," it should at least encompass all the capabilities of modern encryption protocols. Converso uses a simple and not-so-new RSA, one of the oldest available encryption standards.

At first glance, the random number generation seems fine. Converso appears to rely on java.security.SecureRandom on Android devices and Apple's CSPRNG on iOS as the source of generation.

Next, how does Converso protect against a man-in-the-middle attack? It is the defense that ensures you're talking to the intended person and not an imposter or intermediary. Converso relies on the mercy of a third party, Seald servers, and assigns it the role of the sole certification authority that matches identities with public keys. The third party has unlimited capabilities to authenticate anyone as anyone. There is nothing resembling Safety Numbers, which would provide confidence in the integrity of encrypted messages in Converso. The application lacks the functionality to view the counterpart's public key, and there are no notifications if that key changes. This is a serious omission.

Note from May 17, 2023: I want to make it clear that I'm in no way questioning the security of Seald. Seald does not repeat the promises made by Converso regarding end-to-end encryption protocols. Seald's protocols, which are well-documented, are an excellent tool for many scenarios. However, they are not suitable for a messaging application with end-to-end encryption that compares itself to Signal. Additionally, some of the flaws, such as the lack of protection against a man-in-the-middle attack, stem from the clumsy implementation of the SDK.

Now, message authenticity and authentication. How can we be sure that a message hasn't been tampered with in transit, and how can we verify that it actually came from the sender? Since the public keys are unreliable, there can be no meaningful message identification.

Forward secrecy? There is no such thing. Unlike established services for encrypted messaging like Converso (Signal, WhatsApp, Telegram, and Viber), if a user's Converso device is compromised, a knowledgeable attacker can use the keys stored on it to decrypt previous messages, including those that have been deleted from the device. In Seald, the default storage time for asymmetric encryption keys is three years (in comparison, the Signal protocol changes them after each message).

Security after compromise? Modern encrypted messengers have the ability to self-heal, preventing an attacker from decrypting future messages after the device has been compromised. Converso doesn't even attempt to do that.

Statement: "No servers," "no message storage on servers." 

Verdict: False

Messages and keys are transmitted to and delivered by servers. Naturally, servers exist in this scheme.

Statement: "Absolutely no use of user data," "No tracking," "When using Converso, your data is not stored on servers or anywhere else." 

Verdict: False

Screenshot from conversoapp.com/faqs/

Converso not only incorporates the Google Analytics tracker to record your actions in the application but also collects phone numbers for each account, along with other metadata that inevitably accompanies the sending or receiving of any message or key. All this data is stored on servers.

Additionally, presumably due to a developer error, every Converso user sends an HTTP request to cdn.pixabay.com to download the default profile picture. Pixabay's privacy policy states that they record these requests along with IP addresses and device information.

The developers' claim that Converso messages leave "no metadata" is erroneous, as are the following private statements.

"Where you come from [remains hidden]."

When using the application, your IP address, as well as location and device information, are transmitted to Seald, Google Analytics, and Pixabay.

"Who you are [remains hidden]."

During registration, a phone number is required and stored on the server.

"Who you communicate with [remains hidden]."

Messages are addressed by phone numbers and delivered through the server. The server needs to know the recipient of each message in order to direct it to the correct device. It is aware of whom you are communicating with and when.

Statement: "End-to-end encryption of the platform is impossible to bypass," "Each message is protected by end-to-end encryption, meaning only the intended recipient can read it."

Verdict: False

As evident from the above, the encryption protocol used by Converso is outdated and vulnerable to various attacks.

Since the asymmetric encryption keys are not reliable, Converso cannot guarantee the security of its users. The Converso encryption protocol relies on the assumption that its third-party trusted intermediary will always act in good faith.

Statement: "It so happened that Signal was founded by the same person who was behind WhatsApp."

Verdict: False

Screenshot from converso.com

The co-founder of WhatsApp did indeed contribute to the establishment and activities of the foundation that is currently developing Signal, but he became involved eight years after the company's inception. This foundation and Signal are separate entities.

Signal was released in 2014 by the company Open Whisper Systems, under the leadership of Moxie Marlinspike, but the history of this product dates back to 2010; it was previously known as TextSecure and RedPhone. In 2018, Brian Acton, co-founder of WhatsApp, assisted in the launch of the Signal Technology Foundation, a nonprofit organization with a mission to "support, accelerate, and broaden the Signal mission of making private communication accessible and ubiquitous."

Statement: "WhatsApp, Telegram, and Viber store messages (in readable form) on servers."

Verdict: False or a significant distortion of the truth

Both WhatsApp and Viber have implemented the Signal protocol. Encrypted conversations in Telegram use MTProto. Both of these protocols are well-known, well-documented, and have undergone official assessments by third-party experts.

Encrypted messages are not stored in readable form on the servers of WhatsApp, Telegram, and Viber. (In Telegram, end-to-end encryption is an optional feature that can be enabled; simple, unencrypted messages are accessible from the server.)

In another text, Converso claims that WhatsApp "generates unencrypted chat backups on Google Cloud or iCloud," but that is not entirely accurate. WhatsApp backups are created at the user's discretion and can be protected with end-to-end encryption (although this is not yet the default setting).

Statement: "Any conversation taking place on our platform is part of a decentralized architecture." 

Verdict: False

Converso uses central servers for the transmission of keys and messages. Decentralized architecture is not employed in Converso - its creators rely on the traditional client-server centralized model.

Statement: "[Signal] relies on Amazon S3 for distributing blockchain data."

Verdict: False or a significant distortion of the truth

Signal supports peer-to-peer transactions through MobileCoin, a private cryptocurrency, but this functionality is not imposed on anyone and is not popular. Simple end-to-end encrypted messages in Signal are not related to MobileCoin or any other blockchain data.

Summarizing the above

From all of this, we can once again draw the conclusion that not everything written on the internet corresponds to reality. Converso creates a false image of its product as a messenger with the most advanced end-to-end encryption technologies, which is very far from the truth. The truth is that the incredible claims made by the Converso team on their website (promising complete security in the application and boasting about top-level encryption tools) are false, and it is easy to prove it. Therefore, I believe that relying on Converso for security matters is definitely not advisable, and certainly not worth paying them $4.95 per month.

But wait, it's much worse

When I was finishing the text above, I noticed something strange in the code - it had somehow passed me by before. There were numerous mentions of something resembling functions related to the Google Firestore database.

Even before that, I noticed that for some simple operations, such as local indexing of address books on the device, the code uses SQLite. I assumed that SQLite was used for other things as well, such as messages, and that the servers were only needed for data transmission and not for long-term storage. I was wrong.

The code with SQLite from previous investigations (those who find an additional vulnerability here - well done)

It seems that Converso uses the Firestore database framework to store various data from the application, including received and sent messages, call logs, user registration data, and possibly other categories of user content.

This surprised and puzzled me because Firestore is a cloud database hosted by Google. It is definitely not the internal, strictly offline database interface you would expect to see in an application of this type. And apparently, Firestore is used for many data that should ideally be kept offline. I saw collection and sub-collection names in Firestore such as users, chats, messages, missedCalls, videoInfo, recents, rooms, fcmTokens, phoneRooms, phoneInfo, usersPublic, loginError, callerCandidates, and calleeCandidates.

But this Firestore database, of course, is secure... right?

From any online database, you expect that server-side rules are in place to restrict access in order to prevent unauthorized dissemination of confidential information.

I decided to test the Firebase credentials I found earlier in the code to see if the data is properly protected according to Firestore security rules. One would think that these credentials alone would not be sufficient to provide unrestricted access to confidential information from the database.

I wrote a few lines of code to see what would happen if I tried to retrieve data from the users collection:

And here's what I got:

A small fragment from the users collection

It appears that I unintentionally intruded into Converso's user database. The users collection, open to the entire internet and publicly accessible, contains the registration data of each user of the application. Phone numbers, registration times, and identifiers of the groups to which users belong (in other words, who is talking to whom).

Many other database collections are equally open to anyone interested. Collections like fcmTokens, loginError, missedCalls, phoneInfo, phoneRooms, rooms, usersPublic, and videoPublic do not require any server-side authorization to grant access.

For those unfamiliar with Firestore, this error is almost equivalent to creating an internet-facing SQL database without setting a username and password - anyone can read and write whatever they want.

Converso's metadata is publicly accessible

Converso not only collects and stores vast amounts of metadata that supposedly do not exist at all, but it also makes this metadata publicly accessible. When you make a call to someone, the information about it is spread across the world, and anyone interested can track the situation in real-time.

This data is stored in unencrypted form on Google servers - quite ironic for a company that opposes "tech giants" (specifically Google) in its marketing slogans.

"Converso is created for those who want absolute privacy and freedom from any surveillance, whether it be from the government or tech giants" - conversoapp.com.

Exploring other collections in Firestore

The rooms collection contains metadata related to video call sessions (WebRTC is used for video and audio streaming between users).

A small fragment from the rooms collection

Similarly, the phoneRooms collection contains metadata for audio calls made from the application.

A small fragment from the phoneRooms collection

The fcmTokens collection appears to contain a long list of FCM registration tokens for each user. These are identifiers issued by GCM servers to allow clients to receive notifications and other types of internal application messages.

I'm not sure exactly how these tokens are used in Converso, but the Firebase documentation clearly states: "Registration tokens must be kept secret."

A small fragment from the fcmTokens collection

I couldn't access the chats and messages collections - apparently, there's some permission system in place there (at least somewhere). I can't say for sure what security rules are implemented there; perhaps I'll figure them out later. But let's get back to the code.

Converso online messaging database

In Converso, there are two types of messages: plaintext messages and encrypted messages. Both are stored in the messages collection on Firestore, hosted by Google.

The records look like this:

The following message categories in Converso are not encrypted:

  • Image messages. These are messages where isImage: true and the plaintext filename of the image is specified in the imageName field. Image files are converted to an unencrypted format using a cloud storage service on Firebase. 
  • Animated images. There are message records that have url and isGif: true fields. When a recipient's device receives such messages, the corresponding image is automatically downloaded without prompting, and there is no way to disable this. This appears to create an obvious and serious vulnerability: anyone can discover the IP address of any Converso user simply by sending a message with a URL pointing to the host.
  • Requests to clear chat history. These are plaintext records with isClear: true. 
  • Requests to delete a previous message. These are plaintext records with isDelete: true and a messageId field indicating which message should be deleted. 
  • Notifications of screenshots taken. If the application detects that you have taken a screenshot, it creates a plaintext record stating "Screenshot taken" with isScreenshot: true.
  • Encrypted messages - their Firestore entries include an encryptedMessage string - are passed to the Seald SDK for decryption using the decryptMessage function. This function decodes the base64 ciphertext into plaintext as described above.

Encrypted messages - their records in Firestore include the "encryptedMessage"string and are passed to the Seald SDK for decryption using the decryptMessage function. This function decodes the Base64 ciphertext into plaintext using the method described above. Let's take a closer look at the "encrypted" messages.

Let's take a closer look at the "encrypted" messages.

After carefully examining the Seald-related code, I discovered that Converso utilizes the Seald module @seald-io/sdk-plugin-ssks-password. According to the developer's documentation, this allows Converso to utilize a "reliable key storage service" provided by Seald, enabling the "easy and secure preservation of Seald identities with user-password encryption."

So, the private keys are duplicated on Seald servers and encrypted there with user passwords. If a user deletes the Converso app, they can later restore their super-secret RSA key by retrieving the encrypted version from the server and decrypting it locally using their password. Once the key is restored, they can decrypt old messages stored in the Firestore database.

However, a serious issue arises here: Converso does not use any passwords. To create an account, you simply need to enter your phone number and then an SMS code for verification. But if there are no passwords, how are the keys encrypted?

In the minified JavaScript, it is quite challenging to determine where the password variable (u) originates from. It's time to use a tool that will make the code more readable.

Now it's easier to track variables across functions. Upon closer inspection, I see that the examined code is a React Native component called Seald.

As it turns out, the username in Seald is the user's phone number, and the password is simply the user's identifier. And this is very problematic. The decryption passwords match the user identifiers in Firebase, and the identifiers are publicly accessible.

I already have a list of phone numbers and identifiers for all Converso users - I downloaded it when working with the users collection. Therefore, I have enough account data to download and decrypt all Converso private keys, giving me the ability to decrypt any encrypted message.

With the help of the official Seald SDK, I will run a small script to verify my findings.

Using the Seald credentials from the application's code, a random user's phone number, and an identifier from the public Converso database.

$ node test.js 
[19:29:17.328 04/05/2023 UTC+10] info :seald-sdk - Seald SDK - Start
[19:29:17.338 04/05/2023 UTC+10] info :goatee - Instantiating Goatee
[19:29:17.341 04/05/2023 UTC+10] info :goatee - Initializing goatee
[19:29:18.993 04/05/2023 UTC+10] info :seald-sdk - Already initialized
[19:29:19.028 04/05/2023 UTC+10] info :goatee - Setting new default user...
[19:29:23.590 04/05/2023 UTC+10] info :goatee/database/models/User - Sigchain updated for user 2yXXXXXXXXXXXLEw. Sigchain matches with db: true
good password!

Oh no.

At this point, I will cease my investigations. I am now one step away from intruding into someone's private life by reading a message that should be encrypted and personal.

Private keys are also publicly accessible.

Not only are metadata accessible to outsiders, but the keys used for message encryption are also available. Anyone can download a Converso user's private key and use it to decrypt their private conversations.

The distinction between plaintext and encrypted messages becomes blurred - nothing is encrypted in a meaningful way. For the sake of your own security, only send via Converso what you would be comfortable publishing on Twitter.

I reported all of these glaring vulnerabilities to Converso before publishing the article.

05.05.2023: Vulnerability information was shared with Converso. A draft article has been prepared.

05.05.2023: Response received from Converso: "Thank you for your response and the time you have spent on this issue. I have forwarded your email to the general and technical directors, and we will immediately start working on it. We will send you a detailed response as soon as possible."

05.05.2023: Converso asks: "How were you able to decompile the application's source code, and what measures do you think should be taken to protect against such incidents in the future?"

05.05.2023: My response: "Your application is written in React Native. It is sufficient to rename the Converso APK file to '.7z' and then extract the 'assets/index.android.bundle' file. This file contains the source code of Converso and its JavaScript dependencies after bundling. There is nothing to protect against here - other applications work the same way. Moreover, even if this process could be made more difficult, reinforcing server-side security from the client side is an unreliable strategy."

05.05.2023: Converso asks: "Can we know who you are and where you are located? Thank you."

06.05.2023: Converso informs: "We wanted to let you know that we have deployed a new version and are waiting for the build to go through moderation. In future updates, we will take your feedback into account, for which we are very grateful."

06.05.2023: Apple approves the new version of the app for iOS. In the release notes, the Converso developer mentions that the new version "fixes minor bugs" and "adds more enhanced next-generation protection mechanisms."

05.05.2023-05.06.2023: Google approves the new version of the app for Android.

09.05.2023: Converso writes: "The vulnerability related to Firebase rules has been addressed, and we invite you to test it. Another vulnerability related to pre-defined decryption keys has been implemented on our side, and we are only waiting for new credentials for existing users to undergo reauthentication. However, all existing messages sent with the old decryption keys are protected by Firebase rules, so outsiders still cannot read them."

10.05.2023: I receive thanks again from Converso for bringing the vulnerabilities to their attention. I published an article on my blog.

11.05.2023 – 12.05.2023: Converso Founder Tanner Haas informs me that he and his legal team are unhappy with my article and advise its removal. He sends me a series of emails accusing me of defamation and claiming that I am either "their employee [Signal]" or "Moxie himself." At the same time, Converso begins removing content from their website and marketing materials, including most of the false or distorted statements I quoted above.

14.05.2023: Converso publishes a new article on their website's blog, seemingly attempting to push down the search results for my article and possibly others that point out flaws in Converso's security and incorrect claims. The meta description tag includes the phrase "verifying Converso's statements."

16.05.2023: The Converso application appears to no longer be available for download on the Google Play Store and iOS App Store. It is unclear at this point what the reason is and whether the application will return to the market. Either Converso deliberately withdrew it, or the marketplaces have raised concerns about it.

16.05.2023: In an email to me, Converso employees confirm that they voluntarily removed the application from sale in stores while working on "improvements and addressing deficiencies."


Report Page