CometChat Pro Documentation

You'll find comprehensive guides and documentation to help you start working with CometChat as quickly as possible. Let's jump right in!

End-to-End Encryption

This extension enables you to add end to end encryption to your apps. To enable this, follow the below steps:

Register with Virgil Security

The first step to add End to End Encryption to your apps, the first step you need to do is register with Virgil Security and create an account.

Create an App in the Vigil Dashboard

  1. Once you login to Virgil Security, click on "Create New Application".
  2. Enter the name of your app, and select "ADD END-TO-END ENCRYPTION TO PRODUCT" as your use case.
  3. Click on Create Application.
  1. Once the app is created, you need to get the below three details from the Virgil Security dashboard which will be required later.

a. Virgil APP ID - The app Id of your Virgil Application.
b. Virgil API Key ID - This is the API Key ID and can be found under the API Keys section in the dashboard.
c. Virgil API Key - This is the API Key and can also be obtained from the API Keys section in the dashboard. Please make sure you save this key securely once you create it as it cannot be obtained later.

Login to CometChat Dashboard

  1. Open the CometChat Dashboard. And login to your account.
  2. Select the app you want to enable End to End Encryption for
  3. Navigate to the Extensions Tab.
  4. Click on the "Add Extension" button for End to End Encryption Extension.
  1. Once the extension is added, go to the settings for the extension by clicking the Action button.
  2. Add the details saved earlier from Virgil Dashboard as shown below and click "Save".
  1. Finally, enable the extension.

Setup the Clients

Once the extension is enabled, You need to add End to End Encryption extensions to the clients. In order to add the extension to the clients, you need to perform the below 2 steps:

1. Add the dependency from the respective dependency managers:

dependencies {
	// Other dependencies
	implementation "com.cometchat:pro-ext-e2ee:1.0.+"
}
npm i @cometchat-pro/pro-ext-e2ee
platform :ios, '10.0'
use_frameworks!

target 'MyApp' do
  pod 'Pro-Ext-E2EE', '~> 1.0.0'
end

Important

Please make sure the CometChat SDK version 1.4.0 or above is added to your apps as the extension requires the CometChat SDK for functioning.

Steps to encrypt and decrypt data

1. Init the Extension

The first step is to initialize the extension.

private String appId = "APP_ID";
private String UID = "UID"

E2EEncryptionExtension.init(context, appId, UID, new
CometChat.CallbackListener<String>() {
  
  @Override
    public void onSuccess(String s) {
    	Log.d(TAG, s);              
  }

  @Override
    public void onError(CometChatException e) {
    	Log.d(TAG, e.getMessage());
  }
});
const appId = "APP_ID";
const UID = "UID";

E2EEncryptionExtension.init(appId,UID).then(
  ()=>{
	console.log("E2EEncryptionExtension initialized");
},
  error=>{
	console.log("E2EEncryptionExtension Initialization failed with error",error);
});
let appID = "APP_ID"
let uid = "UID"

E2EEncryptionExtension(appID: appID, uid: uid, onSuccess: { (isSuccess) in

    print("E2EEncryption initialization successful..")
    
}, onError: {
           
     print("E2EEncryption initialization failed..")
})

This method initializes the extension. This method needs to be called once every session of the app.

Encrypt the Message

To encrypt the message you need to use the encryptMessage() method. This method needs to be called before the message is sent.

Important

At the moment, only TextMessage and CustomMessage message types are encrypted. Also, the encryption is only supported for One to One chat and not Group chats.

private String receiverID = "UID";
private String messageText = "Hello world!";
private String messageType = CometChatConstants.MESSAGE_TYPE_TEXT;
private String receiverType = CometChatConstants.RECEIVER_TYPE_USER;

TextMessage textMessage = new TextMessage(receiverID, messageText, messageType, receiverType);

E2EEncryptionExtension.encryptMessage(textMessage, new CometChat.CallbackListener<BaseMessage>() {
  @Override
    public void onSuccess(BaseMessage baseMessage) {
    CometChat.sendMessage((TextMessage)baseMessage, new
CometChat.CallbackListener<TextMessage>() {
  @Override
    public void onSuccess(TextMessage textMessage) {
    E2EEncryptionExtension.decryptMessageForSelf(textMessage, new CometChat.CallbackListener<BaseMessage>() {
      @Override
        public void onSuccess(BaseMessage decryptedMessage) {
        	Log.e(TAG, ((TextMessage)decryptedMessage).toString());
      }

      @Override
        public void onError(CometChatException e) {
        	Log.e(TAG, e.getMessage());
      }
    });

  }

  @Override
    public void onError(CometChatException e) {
    	Log.e(TAG, e.getMessage());
  }
});
  }

  @Override
    public void onError(CometChatException e) {
    	Log.e(TAG, e.getMessage());
  }
});
var receiverID = "UID";
var messageText = "Hello world!";
var messageType = CometChat.MESSAGE_TYPE.TEXT;
var receiverType = CometChat.RECEIVER_TYPE.USER;

var textMessage = new CometChat.TextMessage(receiverID, messageText, messageType, receiverType);

E2EEncryptionExtension.encryptMessage(textMessage).then(textMessage => {
    CometChat.sendMessage(textMessage).then(
        message => {
            console.log("Message sent successfully:", message.getText());
            E2EEncryptionExtension.decryptMessageForSelf(message).then(message => {
                console.log("Message after descrypting", message.getText());
            });
        },
        error => {
            console.log("Message sending failed with error:", error);
        }
    );
}, err => {
    console.error("Message encryption failed with error :", err);
});
let receiverId = "receiver UID"
let textMsg = TextMessage(receiverUid: receiverUID, text: "text you want to send", messageType: .text, receiverType: .text)

E2EEncryptionExtension.encrypt(message: textMsg, onSuccess: { (baseMessage) in 
	
  print("message encrypted successfully.")
  
  E2EEncryptionExtension.decryptForSelf(message: baseMessage, onSuccess: { (baseMessage) in
  
  	print("message decrypted successfully.")
  
  }, onError: { (error) in
  
  	print("error in decrypting with error : \(error)")
     
  })

}, onError: { (error) in

	print("message encryption failed with error : \(error).")
  
})

In the above code snippet, it shows how you can use the encryptMessage() method. The steps can be described as follows:

  1. Create an object of the TextMessage or CustomMessage class.
  2. Call the encryptMessage() method.
  3. In the onSuccess callback, you receive the encrypted Message.
  4. This message needs to be passed to the sendMessage() or sendCustomMessage() based on the type of the message.
  5. Since the message sent is encrypted, the message object received in the onSuccess of the sendMessage() or sendCustomMessage() will also be encrypted.
  6. In order to decrypt this message use the E2EEncryptionExtension.decryptMessageForSelf() which will return the original message.

Decrypt the received messages

When you receive the messages in the methods of the MessageListener class, the messages are encrypted and thus need to be decrypted before using them. You need to use the decryptMessage() method.

CometChat.addMessageListener("Listener 1", new CometChat.MessageListener() {
  @Override
    public void onTextMessageReceived(TextMessage message) {
    
    E2EEncryptionExtension.decryptMessage(message, new
CometChat.CallbackListener<BaseMessage>() {
  @Override
    public void onSuccess(BaseMessage decryptedMessage) {
    	Log.d(TAG, "Message Received :"+ ((TextMessage)decryptedMessage).toString());
  
  }
  
  @Override
    public void onError(CometChatException e) {
			Log.d(TAG, e.getMessage());
  }
});
  }

  @Override
    public void onMediaMessageReceived(MediaMessage message) {               
    	Log.d(TAG, "Message Received : " + message.toString());
  }

  @Override
    public void onCustomMessageReceived(CustomMessage message) {
    E2EEncryptionExtension.decryptMessage(message, new CometChat.CallbackListener<BaseMessage>() {
      @Override
        public void onSuccess(BaseMessage decryptedMessage) {
        	Log.d(TAG, "Message Received : " +((CustomMessage)decryptedMessage).toString());
      }

      @Override
        public void onError(CometChatException e) {
        	Log.d(TAG, e.getMessage());
      }
    });
  }
var listenerID = "UNIQUE_LISTENER_ID";

CometChat.addMessageListener(
    listenerID,
    new CometChat.MessageListener({
        onTextMessageReceived: textMessage => {
            console.log("Text from message", textMessage.getText());
            E2EEncryptionExtension.decryptMessage(textMessage).then(message => {
                console.log("Text message after decypting", message.getText());
            });
        },
        onMediaMessageReceived: mediaMessage => {
            console.log("Media message received successfully", mediaMessage);            
        },
        onCustomMessageReceived: customMessage => {
            console.log("Custom message received successfully", customMessage.getCustomData());
            E2EEncryptionExtension.decryptMessage(customMessage).then(message => {
                console.log("Custom message after decypting", (message).getCustomData());
            }, error => {
                console.log("Error in decrypting custom message",error);
            });
            // Handle media message
        }
    })
);
E2EEncryptionExtension.decrypt(message: textMsg, onSuccess: { (baseMsg) in
                
    print("decrypted messaged on AppDelegate : \(baseMsg)")

}, onError: { (error) in
                
    print("decryption failed : \(error)")
    
})

Supporting multi-device sign-ins

If you wish to add multi-device support, you need to call the backupPrivateKey() method. This method needs to be called only once. We suggest you call this once the user logs into your app successfully.

private String password = "PASSWORD";

E2EEncryptionExtension.backupPrivateKey(password, new
CometChat.CallbackListener<String>() {
  
  @Override
    public void onSuccess(String s) {
    	Log.d(TAG, s);
  }

  @Override
    public void onError(CometChatException e) {
    	Log.d(TAG, e.getMessage());
  }
});
var password="PASSWORD";
E2EEncryptionExtension.backupPrivateKey(password).then(() => {
    console.log("Private keys backedup");
}, error => {
    console.log(error)
})
E2EEncryption.backupPrivateKey(password: "password you want to set", onSuccess: {

	print("private key backed up successfully..")

}, onError: { (error) in

	print("private key backed up failed with error : \(error)")
  
})

This method backs up the private key to the Virgil servers and thus enables you to use the encryption feature on multiple devices.

Important

We recommend you perform this step, as this will make sure you can use the encryption feature even after the app is uninstalled or the data is cleared and the private key is deleted. The password required should be directly entered by the user or you can use the password provided by the user to authenticate himself into your app.

Restore the Private Key

In case the same user logs in to via another device or uninstalls the app and installs again and tries to log in again, you will get an IdentityAlreadyExistsError(E2EEExtensionConstants.ERROR_IDENTITY_ALREADY_EXISTS) in the onError() callback of the init() method. In case this exception is received, you will have to call the restorePrivateKey() method to get the private key back.

private String appId = "APP_ID";
private String UID = "UID"
private String password = "PASSWORD"

E2EEncryptionExtension.init(context, appId, UID, new
CometChat.CallbackListener<String>() {
  
  @Override
    public void onSuccess(String s) {
    	Log.d(TAG, s);              
  }

  @Override
    public void onError(CometChatException e) {
    if(e.getCode().
       equalsIgnoreCase(E2EEExtensionConstants.ERROR_IDENTITY_ALREADY_EXISTS)){  
      E2EEncryptionExtension.restorePrivateKey(password, new
CometChat.CallbackListener<String>() {

  @Override
    public void onSuccess(String s) {
    Log.d(TAG, s);
  }

  @Override
    public void onError(CometChatException e) {
    Log.d(TAG, e.getMessage());
  }
});
    }else{
      Log.d(TAG, e.getMessage());
    }
  }
});
var appId = "APP_ID";
var UID = "UID"
var password = "PASSWORD"

E2EEncryptionExtension.init(appId, UID).then(() => {
    console.log("Extension initialized");
}, error => {
    console.error("Error in initilized", error);
    E2EEncryptionExtension.restorePrivateKey(password).then(() => {
        console.error("created")
    }, error => {
        console.error(error);
    });
});
let appID = "APP_ID"
let uid = "UID"
let password  = "Password"

E2EEncryptionExtension(appID: appID, uid: uid, onSuccess: { (isSuccess) in

    print("E2EEncryption initialization successful..")
    
}, onError: { (error) in
           
     print("E2EEncryption initialization failed with error : \(error)")
     
     E2EEncryptionExtension.restorePrivateKey(password: "Password", onSuccess: {
     
     	print("restored private ket successfully...")
     
     }, onError: { (error) in
     
     	print("restoration of private key failed with error : \(error)")
      
     })
})

Clean Up

You will need to call the cleanUp() method once the user logs out successfully from your app. We suggest you call this in the onSuccess() callback of the CometChat.logout() method which is called once the user logs out successfully from your app.

CometChat.logout(new CometChat.CallbackListener<String>() {
  @Override
    public void onSuccess(String s) {
    	E2EEncryptionExtension.cleanup();
  }

  @Override
    public void onError(CometChatException e) {
    	Log.d(TAG, e.getMessage());
  }
});
CometChat.logout().then(() => {
    E2EEncryptionExtension.cleanup().then(() => {
        console.log("clean up done");
    }, error => {
        console.log("Error in clean up");
    });
}, error => {
    console.log("Error in login out");
})
CometChat.logout(onSuccess: { (isSuccess) in

	E2EEEncryptionExtension.cleanup(onSuccess: {
  
  	print("Cleanup done successfully")
    
  }, onError: { (error) in
  
  	print("Cleanup failed with error : \(error)")
 
 	})

}, onError: { (error) in

	print("logout failed with error : \(error)")
  
})

Important

Before you call the cleanUp() method, please make sure you have backed up your private key using the backupPrivateKey() method. In case the private key is not backed up, you will not be able to decrypt the previously shared messages. If you wish to generate a new set of keys and ignore the messages previously shared, you can use the regenerateKeys() method as shown below.

Regenerate New keys

This method helps you to generate a new set of private and public keys. Once the new keys are generated, the messages encrypted using the earlier keys will not be decrypted.

Important

In case you get the IdentityAlreadyExistsError(E2EEExtensionConstants.ERROR_IDENTITY_ALREADY_EXISTS), and you have not backed up the private key using the backupPrivateKey() method, you will have to use the regenerateKeys() method, to get a new set of keys. This means, that all the messages encrypted in the previous session with the previous set of keys will not be decrypted and hence will be lost.


E2EEncryptionExtension.regenerateKeys(new CometChat.CallbackListener<String>() {
  
  @Override
    public void onSuccess(String s) {
    	Log.d(TAG, s);
  }

  @Override
    public void onError(CometChatException e) {
    	Log.d(TAG, e.getMessage());
  }
});
E2EEncryptionExtension.regenerateKeys().then(
  ()=>{
    console.log("Keys regenerated");
},
  error=>{
    console.log("Error in key regeneration",error);
});
E2EEncryptionExtension.regenerateKeys(onSuccess: {

	print("regenerated the private keys successfully.")
  
}, onError: { (error) in

	print("regenerated the private keys failed with error : \(error)")

})

Change password for Key Backup

You can also change the password for the private key backup. You can do so using the changeBackupPassword() method.

private String oldPassword = "OLD_PASSWORD";
private String newPassword = "NEW_PASSWORD";

E2EEncryptionExtension.changeBackupPassword(oldPassword, newPassword, new CometChat.CallbackListener<String>() {
  @Override
    public void onSuccess(String s) {
    	Log.d(TAG, s);
  }

  @Override
    public void onError(CometChatException e) {
    	Log.d(TAG, e.getMessage());
  }
});
var oldPassword = "OLD_PASSWORD";
var newPassword = "NEW_PASSWORD";

E2EEncryptionExtension.changeBackupPassword(oldPassword, newPassword).then(
  ()=>{
	console.log("Backup password changed");
},
  error=>{
	console.log("Error in changing password",error);
});
let oldPassword = "Old Password"
let newPassword = "New Password"

E2EEncryptionExtension.changeBackupPassword(oldPassword: oldPassword, newPassword: newPassword, onSuccess: {
	
  print("changed password for backup key successfully")

}, onError: { (error) in

	print("changed password for backup key failed with error: \(error)")
  
})

This method changes the password for the user from "OLD_PASSWORD" to "NEW_PASSWORD" and after this, every time the private key needs to be retrieved, you will have to use the new password.

End-to-End Encryption


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.