Group Encryption

E3Kit's group encryption provides true end-to-end encryption and data signature for one or multiple users. It also provides you with the functions to create and manage dynamic groups for encrypted communication. A group key is shared between participants, which enables new members to have access to the previously encrypted data history in the group. These functions can be used for chat, file sharing, and more. In this section, we assume that your users have installed and initialized E3Kit, and are already registered with Virgil Cloud.

Before you begin

Be sure to implement the following:

Create group chat

Let's imagine Alice wants to start a group chat with Bob and Carol. First, Alice creates a ticket for the group by running the createGroup function. This ticket holds a shared root key for future group encryption. E3Kit will store the ticket in Virgil Cloud.

Alice has to specify a unique identifier of the group (groupId) with length > 10 and the initial participants (users). We recommend tying this identifier to the id you already use to identify the group in your system.

ethree.createGroup(groupId, users).addCallback(new OnResultListener<Group>() {
    @Override public void onSuccess(Group group) {
        // Group created and saved locally!
    }

    @Override public void onError(@NotNull Throwable throwable) {
        // Error handling
    }
});

Start group chat session

Now, other participants, Bob and Carol, want access to Alice's group. They have to start the group session using the loadGroup method. It loads and saves the group ticket locally. This function requires specifying the group identifier and the group owner's Card.

ethree.loadGroup(groupId, users.get("Alice")).addCallback(new OnResultListener<Group>() {
    @Override public void onSuccess(Group group) {
        // Group loaded and saved locally!
    }

    @Override public void onError(@NotNull Throwable throwable) {
        // Error handling
    }
});

Then, you can use the getGroup method to retrieve the group instance from local storage.

Group group = ethree.getGroup(groupId);

Encrypt and decrypt messages

To encrypt and decrypt messages, use the encrypt and decrypt functions, which allow you to work with data and strings.

Use the following code snippets to encrypt messages:

// prepare a message
String messageToEncrypt = "Hello, Bob and Carol!";

String encrypted = group.encrypt(messageToEncrypt);

Use the following code snippets to decrypt messages:

String decrypted = group.decrypt(encrypted, users.get("Alice"));

At the decrypt step, you should also use the findUsers method to verify that the message hasn't been tampered with.

Encrypt large files

To encrypt large files (plain text length >30000) for a group, go through the following steps:

  1. Generate a new symmetric key for the file
  2. Encrypt the file with the symmetric key
  3. Upload the encrypted file to any storage
  4. Encrypt file URL with the group encryption method
  5. Send the symmetric key with the encrypted file URL to the group.

Use Virgil Crypto Library wrapper of your choice to generate a symmetric key:

// generate a new symmetric key and encrypt the file with it

VirgilCrypto crypto = new VirgilCrypto();
byte[] yourFile;
byte[] encryptedFile;
byte[] key = crypto.generateRandomData(44); // 32-byte key + 12-byte nonce

try (Aes256Gcm aes256Gcm = new Aes256Gcm()) {
    aes256Gcm.setKey(Arrays.copyOfRange(key, 0, aes256Gcm.getKeyLen()));
    aes256Gcm.setNonce(Arrays.copyOfRange(key, aes256Gcm.getKeyLen(), aes256Gcm.getKeyLen() + aes256Gcm.getNonceLen()));
    AuthEncryptAuthEncryptResult authEncryptResult = aes256Gcm.authEncrypt(yourFile, new byte[0]);
    encryptedFile = concat(authEncryptResult.getOut(), authEncryptResult.getTag());
}
catch (FoundationException e) {
    ///
}

private byte[] concat(byte[] body1, byte[] body2) {
    byte[] body = new byte[body1.length + body2.length];
    System.arraycopy(body1, 0, body, 0, body1.length);
    System.arraycopy(body2, 0, body, body1.length, body2.length);
    return body;
}

//TODO: upload the encrypted file to any storage and send the symmetric key with the encrypted file URL to the group (step 3, 4, 5)

Manage group chat

E3Kit also allows you to perform other operations, like participants management, while you work with group chat. In current version of E3Kit only the group initiator can change participants or delete group.

Add new participant

To add a new chat member, the group owner needs to use the add method and specify the new member's Card. The new member will be able to decrypt all the previous message history.

group.add(users.get("Den")).addCallback(new OnCompleteListener() {
    @Override public void onSuccess() {
        // Den was added!
    }

    @Override public void onError(@NotNull Throwable throwable) {
        // Error handling
    }
});

Remove participant

To remove a participant, the group owner needs to use the remove method and specify the member's Card. Removed participants won't be able to load or update this group:

group.remove(users.get("Den")).addCallback(new OnCompleteListener() {
    @Override public void onSuccess() {
        // Den was removed!
    }

    @Override public void onError(@NotNull Throwable throwable) {
        // Error handling
    }
});

Update group chat

If changes are made in your group, e.g. adding a new participant or deleting an existing participant, each group chat participant has to update the encryption key by calling update or reload the Group by calling loadGroup:

group.update().addCallback(new OnCompleteListener() {
    @Override public void onSuccess() {
        // Group updated!
    }

    @Override public void onError(@NotNull Throwable throwable) {
        // Error handling
    }
});

Delete group chat

To delete a group, the owner needs to use the deleteGroup method and specify the group identifier:

ethree.deleteGroup(groupId).addCallback(new OnCompleteListener() {
    @Override public void onSuccess() {
        // Group was deleted!
    }

    @Override public void onError(@NotNull Throwable throwable) {
        // Error handling
    }
});

Limitations

No Perfect Forward Secrecy

E3Kit provides a more secure method that implements the Double Ratchet algorithm to accomplish Perfect Forward Secrecy and post-compromise security for one-to-one communication only. See our Double Ratchet Encryption method.