Wed. Dec 1st, 2021
Build an Encrypted Messaging App

In this tutorial, we’ll construct an encrypted chat/messaging instance app for Android. To do that, we’ll mix the Stream Chat Platform and Virgil Security. Stream and Virgil make it straightforward to construct an answer with glorious safety by combining the entire options you’ll anticipate as a developer when making a messaging app.

These two companies enable builders to combine chat that’s zero information to your backend or Stream. The instance app embeds Virgil Security’s eThree Kit – a safe encrypted messaging platform – with Stream Chat’s Android parts.

Note that each one supply code for this instance Android app is on the market on GitHub. Additionally, earlier than leaping into this tutorial, I like to recommend testing our Android in-app messaging tutorial, which is able to stroll you thru methods to implement Stream Chat from a high-level overview.

What Is End-To-End Encrypted Messaging?

End-to-end encrypted messaging signifies that the customers inside that particular chat can solely learn messages despatched between two folks. To allow this, the messages which can be despatched are encrypted earlier than leaving a person’s machine, and might solely be decrypted by the supposed recipient (end-user).

Virgil Security is a vendor that permits builders to create end-to-end encryption through public/non-public key know-how by the usage of their sturdy and safe encrypted messaging service. With Virgil’s Android SDK, builders can securely create, retailer, and supply sturdy end-to-end encryption.

During this tutorial, we’ll discover ways to construct a chat app that makes use of Virgil’s encryption/decryption platform to stop anybody besides the supposed events from studying messages. No one in your organization, nor any cloud supplier you utilize, can learn these messages. In essence, even when a malicious individual gained entry to the database containing the messages, that individual would solely see encrypted textual content, referred to as ciphertext.

Building an Encrypted Chat Messaging Application

To construct this app, we’ll principally depend on two libraries, Stream Chat Android and Virgil Security for Kotlin. Our final result will encrypt textual content on the machine earlier than sending a message. Decryption and verification will each occur within the receiver’s machine. Stream’s Messaging API will solely see ciphertext, making certain our person’s knowledge isn’t seen by anybody else, together with us.

To accomplish this, the app performs the next steps:

  1. A person authenticates along with your backend.
  2. The person’s app requests a Stream auth token and API key from the backend. The Android app creates a Stream Chat Client for that person.
  3. The person’s app requests a Virgil auth token from the backend and registers with Virgil. This generates their non-public and public key. The non-public secret’s saved domestically, and the general public secret’s saved in Virgil.
  4. Once the person decides who they need to chat with the app creates and joins a Stream Chat Channel.
  5. The app asks Virgil for the receiver’s public key.
  6. The person varieties a message and sends it to Stream. Before sending, the app passes the receiver’s public key to Virgil to encrypt the message. The message is relayed by Stream Chat to the receiver. Stream receives ciphertext, that means they will by no means see the unique message.
  7. The receiving person decrypts the despatched message utilizing Virgil. When the message is obtained, app decrypts the message utilizing the Virgil and that is handed alongside to Stream’s UI parts. Virgil verifies the message is genuine by utilizing the sender’s public key.

While this appears to be like difficult, Stream and Virgil do a lot of the work for us. We’ll use Stream’s out of the field UI parts to render the chat UI and Virgil to do the entire cryptography and key administration. We merely mix these companies.

The code is cut up between the Android frontend contained within the android listing, and the Express (Node.js) backend is discovered within the backend listing. See the in every listing to see putting in and working directions. If you’d wish to observe together with working code, be sure you get each the backend and android working earlier than persevering with.

Let’s stroll by and take a look at the necessary code wanted for every step.


Basic information of Android (Kotlin) and Node.js is required to observe this how-to tutorial.

Note that this safe messaging app is meant solely to run domestically in your machine, and we won’t be overlaying methods to deploy the instance app to iOS or Android app shops.

We use Anko to simplify our asynchronous code. Please notice this library was just lately deprecated. There are additionally doubtless bugs in our async implementation. However, we selected to maintain the noise to a minimal on this tutorial by leveraging Anko and holding async easy. Please use finest practices for asynchronous code.

You will want an account with Stream and Virgil. Once you’ve got created your accounts, you may place your credentials in backend/.env if you would like to run the code. You can use backend/.env.instance as a reference for what credentials are required. You additionally want to put your Stream API key in MainActivity.kt:60.

Step 0. Setup the Backend

For our Android frontend to work together with Stream and Virgil, the applying gives three endpoints:

  • POST /v1/authenticate: This endpoint generates an auth token that permits the Android app to speak with /v1/stream-credentials and /v1/virgil-credentials. To maintain issues easy, this endpoint permits the consumer to be any person. The frontend tells the backend who it needs to authenticate as. In your software, this ought to be changed along with your API’s authentication endpoint.

  • POST /v1/stream-credentials: This returns the information required for the Android app to speak with Stream. In order return this information we have to inform Stream this person exists and ask them to create a sound auth token:

The response payload has this form:

  • apiKey is the stream account identifier on your Stream occasion. Needed to establish what account your frontend is making an attempt to attach with.

  • token JWT token to authorize the frontend with Stream.

  • person: This object incorporates the information that the frontend wants to attach and render the person’s view.

  • POST /v1/virgil-credentials: This returns the authentication token used to attach the frontend to Virgil. We use the Virgil Crypto SDK to generate a sound auth token for us:

In this case, the frontend solely wants the auth token.

  • GET /v1/customers: Endpoint for returning all customers. This exists simply to get a listing of individuals to talk with.

Step 1. User Authenticates With Backend

First, we log in to a person. To maintain issues easy we’ll simply have an empty kind that permits you to log in with any identify:

This is a straightforward kind that takes any arbitrary identify, successfully permitting us to log in as anybody. We set this up in our MainActivity:

And the structure:

When we submit the shape, we signal into our backend, get a Stream and Virgil frontend auth token, generate our non-public key, and register with Virgil, then begin our subsequent exercise. We’ll take a look at every of those in flip.

Let’s see our register and token era:

Since our backend (see Step 1) does the token era, these are easy REST calls. The tokens returned are frontend auth tokens, which permit our consumer to speak to Stream and Virgil straight. Besides returning a listing of customers, we now not want our backend to do any work.

Now that we’ve got our frontend tokens, let’s generate our non-public keys and register our public keys with Virgil:

Virgil’s consumer is known as eThree. We initialize an EThree occasion and register. This name generates a non-public key and shops it on the machine and sends our public key to Virgil. If we get a RegistrationException, we’ve got already registered this person. Keep in thoughts, and you can’t log into the identical person on a unique machine since we’re not sharing the non-public key with the opposite machine! This is feasible, however out of scope for this tutorial. If you would like to perform this, see Virgil’s documentation.

Now that we’ve got our tokens and registration let’s discover a person to talk with!

Step 2: List customers

To maintain issues easy, we’ll get all registered customers from our backend and show them in a easy listing view:

Here is the exercise:

And the structure:

We make an API name through BackendService.getUsers and filter the logged-in person out. We add the response to a easy ArrayAdapter and show our ends in a ListView. When a person clicks on a listing merchandise, we begin a ChannelExercise, which is a 1:1 chat channel.

Step 3: Create a Private 1:1 Channel

First, we have to create our channel for our non-public chat. Let’s take a look at our exercise and structure:

And the structure:

We use off the shelf Stream UI parts with two slight variations. First, we hook in a customized EncryptedMessageInputView, which permits us to encrypt a message earlier than sending it. We additionally hook in a customized EncryptedMessageViewHolderFactory, which permits message decryption (we’ll take a look at this in a bit). The important bits begin inside doAsync. First, we glance up the opposite person’s public key. This let’s use encrypt our messages and confirm their messages are genuine. Next, we create a channel in Stream through .question. Once then channel is created, we load messages. Before we take a look at how we load messages, we have to ship a message first.

Step 4: Sending an Encrypted Message

Let’s take a look at EncryptedMessageInputView, which is sure within the structure and configured in our exercise. Here is the code:

We override Stream’s MessageInputView and easily decrypt the message earlier than sending it. MessageInputView calls put togetherMessage earlier than sending it to the API, so we override this and encrypt earlier than sending the message alongside.

Please notice that updating a message doesn’t make the most of this technique, so bear in mind if you wish to assist edit performance. You can contemplate constructing your personal MessageInputView. For brevity, we can’t go there on this tutorial.

Step 5: Viewing Messages

Since all of our messages in Stream our now ciphertext, we have to decrypt them earlier than displaying. To hook into Stream’s UI parts, we bind through binding.messageList.setViewHolderFactory(EncryptedMessageViewHolderFactory(eThree)). With our customized manufacturing facility, we are able to initialize a customized decryption object for every message:

This manufacturing facility checks if we’ve got a message kind (vs. one other kind resembling a date separator) and initializes our EncryptedMessageViewHolder. Let’s look have a look:

First, we verify if we’ve got a daily message, and if we do, we decrypt it. We copy our message object to keep away from mutating the unique model (Stream caches this, and we’ll mess issues up if we manipulate that). With that replicate, we verify if the message is ours or theirs. In our case, we all know methods to decrypt straight since we created it. If it is theirs, we have to search for their public key to confirm the message. We cross this to Virgil and do our decryption.

Putting these final steps collectively, we’ll see our closing product:

Final Thoughts

And that is it! We now have a non-public and very safe end-to-end encrypted messaging app constructed for Android with Stream Chat and Virgil Security. You ought to have a full understanding of the fundamentals of end-to-end encryption utilizing Stream Chat and Virgil Security, together with a basic understanding of how the E2EE course of works when applied with Android, Virgil, and Stream Chat.

If you need to take it a step additional, Stream Chat provides a number of sources that can assist you get to the following degree along with your Android chops. Check out the hyperlinks beneath:

Happy coding, and as all the time, please be happy to drop any ideas or questions within the feedback beneath!

By admin