End-to-end encrypted chat with Virgil
Scenario Overview
This solution should be implemented by the customer's application based on the E3Kit of virgin security and Chat Sdk. The E3Kit document link: Virtual gild E3Kit|Virtual gild Security.
Learn about the GroupEncryption-End-to-End-Encryption-E3Kit|Virtual Security documentation before reading the following solutions, especially the JWT token(JSON Web Token), create channel/create group, encrypt and decrypt messages.
Open application in virgin security console before using. This product is a paid product. See Pricing|Virgin Security for specific pricing.
The diagram below shows the high-level communication flow:
Products Applied
Chat
Basic Integration Guidelines
1. Chat SDK Initialization.
// 1. Get the `SDKAppID` from the Chat console.// 2. Initialize the `config` object.V2TIMSDKConfig config = new V2TIMSDKConfig();// 3. Specify the log output level.config.setLogLevel(V2TIMSDKConfig.V2TIM_LOG_INFO);// 4. Add the `V2TIMSDKListener` event listener. `sdkListener` is the implementation class of `V2TIMSDKListener`. If you don't need to listen to IM SDK events, skip this step.V2TIMManager.getInstance().addIMSDKListener(sdkListener);// 5. Initialize the IM SDK. You can call the login API as soon as you call this API.V2TIMManager.getInstance().initSDK(context, sdkAppID, config);
2.E3Kit initialization, passing in the console configuration information, and generating jwt. Corresponding operation document link: GenerateClientTokens-GetStarted-E3Kit | VirgilSecurity.
The server generates jwttoken and sends it to the client.
// generate jwt// App Key (you got this Key at the Virgil Dashboard)String appKeyBase64 = "MC4CAQAwBQYDK2VwBCIEINlK4BhgsijAbNmUqU6us0ZU9MGi+HxdYCA6TdZeHjR4";byte[] appKeyData = ConvertionUtils.base64ToBytes(appKeyBase64);// Crypto library imports a key pairVirgilCrypto crypto = new VirgilCrypto();VirgilKeyPair keyPair = crypto.importPrivateKey(appKeyData);// Initialize an access token signer that signs users JWTsVirgilAccessTokenSigner accessTokenSigner = new VirgilAccessTokenSigner();// Use your App Credentials you got at the Virgil Dashboard:String appId = "be00e10e4e1f4bf58f9b4dc85d79c77a";String appKeyId = "70b447e321f3a0fd";TimeSpan ttl = TimeSpan.fromTime(1, TimeUnit.HOURS); // 1 hour - JWT's lifetime// Setup a JWT generator with the required parameters:JwtGenerator jwtGenerator =new JwtGenerator(appId, keyPair.getPrivateKey(), appKeyId, ttl, accessTokenSigner);// Generate a JWT for a user// Remember that you must provide each user with a unique JWT.// Each JWT contains unique user's identity (in this case - Alice).// Identity can be any value: name, email, some id etc.String identity = "Alice";Jwt aliceJwt = jwtGenerator.generateToken(identity);// As a result you get user's JWT, it looks like this: "eyJraWQiOiI3MGI0NDdlMzIxZjNhMGZkIiwidHlwIjoiSldUIiwiYWxnIjoiVkVEUzUxMiIsImN0eSI6InZpcmdpbC1qd3Q7dj0xIn0.eyJleHAiOjE1MTg2OTg5MTcsImlzcyI6InZpcmdpbC1iZTAwZTEwZTRlMWY0YmY1OGY5YjRkYzg1ZDc5Yzc3YSIsInN1YiI6ImlkZW50aXR5LUFsaWNlIiwiaWF0IjoxNTE4NjEyNTE3fQ.MFEwDQYJYIZIAWUDBAIDBQAEQP4Yo3yjmt8WWJ5mqs3Yrqc_VzG6nBtrW2KIjP-kxiIJL_7Wv0pqty7PDbDoGhkX8CJa6UOdyn3rBWRvMK7p7Ak".// You can provide users with JWT at registration or authorization steps.// Send a JWT to client-side.String jwtString = aliceJwt.stringRepresentation();
The Android client initializes the E3Kit, tokenCallback is the jwttoken returned by the above server, and User1 is the user ID.
// initialization E3Kit// create EThreeParams with mandatory parameters// such as identity, tokenCallback and contextEThreeParams params = new EThreeParams("User1",tokenCallback,context);// initialize E3Kit with the EThreeParamsEThree ethree = new EThree(params);
Scenario-specific implementation
User Login
1.Call Chat Sdk login method for account login
String userID = "your user id";//Generating UserSigString userSig = "userSig from your server";V2TIMManager.getInstance().login(userID, userSig, new V2TIMCallback() {@Overridepublic void onSuccess() {Log.i("imsdk", "success");}@Overridepublic void onError(int code, String desc) {// The following error codes indicate an expired `userSig`, and you need to generate a new one for login again.// 1. ERR_USER_SIG_EXPIRED (6206)// 2. ERR_SVR_ACCOUNT_USERSIG_EXPIRED (70001)// Note: Do not call the login API in case of other error codes; otherwise, the IM SDK may enter an infinite loop of login.Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);}});
2.Call the eThree.register method to register the user to virgilSecurity. The corresponding operation document link: UserAuthentication-E3Kit | VirgilSecurity.
Note:User of im_ ID and user registered on virtilsecurity_ The id should be consistent
Start a one-to-one chat
1.Call the ethree.createRatchetChannel method in the E3Kit to create a one to one session (User1 and User2), and the corresponding operation document link: https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/double-ratchet/?#create -channel.
User1 creates a channel with User2
// create one-to-one channelethree.createRatchetChannel(users.get("User2")).addCallback(new OnResultListener<RatchetChannel>() {@Override public void onSuccess(RatchetChannel ratchetChannel) {// Channel created and saved locally!}@Override public void onError(@NotNull Throwable throwable) {// Error handling}});
User2 can join the channel
// join channelethree.joinRatchetChannel(users.get("User1")).addCallback(new OnResultListener<RatchetChannel>() {@Override public void onSuccess(RatchetChannel ratchetChannel) {// Channel joined and saved locally!}@Override public void onError(@NotNull Throwable throwable) {// Error handling}});
One-to-one chat message encryption and decryption
1.Use the channel created above to encrypt messages and link documents:https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/double-ratchet/?#encrypt-and-decrypt-messages.
// one-to-one chat message encryption// prepare a messageString messageToEncrypt = "Hello, User2!";String encrypted = channel.encrypt(messageToEncrypt);
2.The encrypted message content is sent to Chat Sdk and sent with a customized message
// `msgID` returned by the API for on-demand useString msgID = V2TIMManager.getInstance().sendC2CCustomMessage("virgil encrypted msg", "receiver_userID", new V2TIMValueCallback<V2TIMMessage>() {@Overridepublic void onSuccess(V2TIMMessage message) {// The one-to-one text message sent successfully}@Overridepublic void onError(int code, String desc) {// Failed to send the one-to-one text message}});
3.After the peer receiving the customized message
// Set the event listenerV2TIMManager.getInstance().addSimpleMsgListener(simpleMsgListener);/*** Receive the custom one-to-one message* @param msgID Message ID* @param sender Sender information* @param customData The sent content*/public void onRecvC2CCustomMessage(String msgID, V2TIMUserInfo sender, byte[] customData) {Log.i("onRecvC2CCustomMessage", "msgID:" + msgID + ", from:" + sender.getNickName() + ", content:" + new String(customData));//call E3Kit to decrypt msg}
4.the peer calls E3Kit to decrypt and render it, as follows:
// Decrypt messageString decrypted = channel.decrypt(encrypted);
Start a channel(group)
1.Call the ethree.createGroup to create group,document link:https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/group-chat/?#create-group-chat.
// create groupethree.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}});
2.If you need to add group members, the code below is as follows. You can call the remove method to delete a group member. Document link:https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/group-chat/?#add-new-participant.
// add group membergroup.add(users.get("Den")).addCallback(new OnCompleteListener() {@Override public void onSuccess() {// Den was added!}@Override public void onError(@NotNull Throwable throwable) {// Error handling}});
3.Call createGroup of Chat Sdk to create a group, joinGroup or inviteUserToGroup to add group members.
V2TIMManager.getInstance().createGroup(V2TIMManager.GROUP_TYPE_WORK, null, "groupA", new V2TIMValueCallback<String>() {@Overridepublic void onSuccess(String s) {// Group created successfully}@Overridepublic void onError(int code, String desc) {// Failed to create the group}});// Listen for the group creation notificationV2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {@Overridepublic void onGroupCreated(String groupID) {// A group was created. `groupID` is the ID of the created group.}});
// Invite the `userA` user to join the `groupA` groupList<String> userIDList = new ArrayList<>();userIDList.add("userA");V2TIMManager.getGroupManager().inviteUserToGroup("groupA", userIDList, new V2TIMValueCallback<List<V2TIMGroupMemberOperationResult>>() {@Overridepublic void onSuccess(List<V2TIMGroupMemberOperationResult> v2TIMGroupMemberOperationResults) {// Invited the user to the group successfully}@Overridepublic void onError(int code, String desc) {// Failed to invite the user to the group}});// Listen for the group invitation eventV2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {@Overridepublic void onMemberInvited(String groupID, V2TIMGroupMemberInfo opUser, List<V2TIMGroupMemberInfo> memberList) {// A user was invited to the group. This callback can contain some UI tips.}});
Group chat message encryption and decryption
1.Use the group created above to encrypt messages and link documents:https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/group-chat/?#encrypt-and-decrypt-messages.
//Group message encryption// prepare a messageString messageToEncrypt = "Hello, Bob and Carol!";String encrypted = group.encrypt(messageToEncrypt);
String msgID = V2TIMManager.getInstance().sendGroupCustomMessage("virgil encrypted msg ".getBytes(), "groupID", V2TIMMessage.V2TIM_PRIORITY_NORMAL, new V2TIMValueCallback<V2TIMMessage>() {@Overridepublic void onSuccess(V2TIMMessage message) {// The custom group message sent successfully}
// Set the event listenerV2TIMManager.getInstance().addSimpleMsgListener(simpleMsgListener);/*** Receive the custom group message* @param msgID Message ID* @param groupID Group ID* @param sender The group member information of the sender* @param customData The sent content*/public void onRecvGroupCustomMessage(String msgID, String groupID, V2TIMGroupMemberInfo sender, byte[] customData) {Log.i("onRecvGroupCustomMessage", "msgID:" + msgID + ", groupID:" + groupID + ", from:" + sender.getNickName() + ", content:" + new String(customData));//call E3Kit to decrypt msg}
4.The peer decrypt and render it, as follows:
//Group message decryptionString decrypted = group.decrypt(encrypted, users.get("Alice"));
Note: After using this end-to-end encryption scheme, the local chat record search function of imsdk will not be available.
Chat - Developer Groups
Join a Chat developer group for:
● Reliable technical support● Product details● Constant exchange of ideas
Order Now