场景概述
此解决方案应由客户的应用程序基于Virgin Security的E3Kit和Chat SDK实现。E3Kit文档链接:Virgin Security E3Kit | Virgin Security。
在阅读以下解决方案之前,请先了解GroupEncryption-End-to-End-Encryption-E3Kit | Virgin Security 文档,特别是JWT令牌(JSON Web Token)、创建频道/创建组、加密和解密消息。
使用前请在Virgin Security控制台中打开应用程序。此产品为付费产品。有关具体定价,请参见Pricing | Virgin Security。

下图显示了高层次的通信流程:

适用产品
基本集成指南
1.聊天SDK初始化。
// 1. 从聊天控制台获取`SDKAppID`。
// 2. 初始化`config`对象。
V2TIMSDKConfig config = new V2TIMSDKConfig();
// 3. 指定日志输出级别。
config.setLogLevel(V2TIMSDKConfig.V2TIM_LOG_INFO);
// 4. 添加`V2TIMSDKListener`事件监听器。`sdkListener`是`V2TIMSDKListener`的实现类。如果您不需要监听IM SDK事件,可以跳过此步骤。
V2TIMManager.getInstance().addIMSDKListener(sdkListener);
// 5. 初始化IM SDK。您可以在调用此API后立即调用登录API。
V2TIMManager.getInstance().initSDK(context, sdkAppID, config);
2.E3Kit初始化,传入控制台配置信息,并生成jwt。相应操作文档链接:GenerateClientTokens-GetStarted-E3Kit | VirgilSecurity。
服务器生成jwttoken并将其发送给客户端。
// 生成jwt
// 应用密钥(您在Virgil仪表板上获得此密钥)
String appKeyBase64 = "MC4CAQAwBQYDK2VwBCIEINlK4BhgsijAbNmUqU6us0ZU9MGi+HxdYCA6TdZeHjR4";
byte[] appKeyData = ConvertionUtils.base64ToBytes(appKeyBase64);
// 加密库导入密钥对
VirgilCrypto crypto = new VirgilCrypto();
VirgilKeyPair keyPair = crypto.importPrivateKey(appKeyData);
// 初始化访问令牌签署者,用于签署用户的JWT
VirgilAccessTokenSigner accessTokenSigner = new VirgilAccessTokenSigner();
// 使用您在Virgil仪表板上获得的应用凭据:
String appId = "be00e10e4e1f4bf58f9b4dc85d79c77a";
String appKeyId = "70b447e321f3a0fd";
TimeSpan ttl = TimeSpan.fromTime(1, TimeUnit.HOURS); // 1小时 - JWT的生命周期
// 设置带有必需参数的JWT生成器:
JwtGenerator jwtGenerator =
new JwtGenerator(appId, keyPair.getPrivateKey(), appKeyId, ttl, accessTokenSigner);
// 为用户生成JWT
// 请记住,您必须为每个用户提供唯一的JWT。
// 每个JWT包含唯一用户的身份(在本例中为 - Alice)。
// 身份可以是任何值:姓名、电子邮件、某些ID等。
String identity = "Alice";
Jwt aliceJwt = jwtGenerator.generateToken(identity);
// 作为结果,您将获得用户的JWT,它看起来像这样:
// "eyJraWQiOiI3MGI0NDdlMzIxZjNhMGZkIiwidHlwIjoiSldUIiwiYWxnIjoiVkVEUzUxMiIsImN0eSI6InZpcmdpbC1qd3Q7dj0xIn0.eyJleHAiOjE1MTg2OTg5MTcsImlzcyI6InZpcmdpbC1iZTAwZTEwZTRlMWY0YmY1OGY5YjRkYzg1ZDc5Yzc3YSIsInN1YiI6ImlkZW50aXR5LUFsaWNlIiwiaWF0IjoxNTE4NjEyNTE3fQ.MFEwDQYJYIZIAWUDBAIDBQAEQP4Yo3yjmt8WWJ5mqs3Yrqc_VzG6nBtrW2KIjP-kxiIJL_7Wv0pqty7PDbDoGhkX8CJa6UOdyn3rBWRvMK7p7Ak"。
// 您可以在注册或授权步骤中向用户提供JWT。
// 将JWT发送到客户端。
String jwtString = aliceJwt.stringRepresentation();
Android客户端初始化E3Kit,tokenCallback是上述服务器返回的jwttoken,User1是用户ID。
// 初始化E3Kit
// 创建包含身份、tokenCallback和上下文等必要参数的EThreeParams
EThreeParams params = new EThreeParams("User1",
tokenCallback,context);
// 使用EThreeParams初始化E3Kit
EThree ethree = new EThree(params);
场景特定实现
用户登录
1.调用Chat SDK登录方法进行账户登录
String userID = "您的用户ID";
// 生成UserSig
String userSig = "来自您服务器的userSig";
V2TIMManager.getInstance().login(userID, userSig, new V2TIMCallback() {
@Override
public void onSuccess() {
Log.i("imsdk", "成功");
}
@Override
public void onError(int code, String desc) {
// 以下错误代码表示`userSig`已过期,需要为登录再次生成新的userSig。
// 1. ERR_USER_SIG_EXPIRED (6206)
// 2. ERR_SVR_ACCOUNT_USERSIG_EXPIRED (70001)
// 注意:在发生其他错误代码时,请勿调用登录API;否则,IM SDK可能会进入无限循环的登录状态。
Log.i("imsdk", "失败,代码:" + code + ", 描述:" + desc);
}
});
2.调用eThree.register方法将用户注册到virgilSecurity。相应操作文档链接: UserAuthentication-E3Kit | VirgilSecurity。
注意:im_ID的用户和在virgilsecurity上注册的用户_id应保持一致
开始一对一聊天
1.调用ethree.createRatchetChannel方法在E3Kit中创建一对一会话(User1和User2),相应操作文档链接:https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/double-ratchet/#create-channel
User1与User2创建频道
// 创建一对一频道
ethree.createRatchetChannel(users.get("User2"))
.addCallback(new OnResultListener<RatchetChannel>() {
@Override public void onSuccess(RatchetChannel ratchetChannel) {
// 渠道创建成功并保存在本地!
}
@Override public void onError(@NotNull Throwable throwable) {
// 错误处理
}
});
User2可以加入频道
// 加入频道
ethree.joinRatchetChannel(users.get("User1"))
.addCallback(new OnResultListener<RatchetChannel>() {
@Override public void onSuccess(RatchetChannel ratchetChannel) {
// 渠道已加入并保存在本地!
}
@Override public void onError(@NotNull Throwable throwable) {
// 错误处理
}
});
一对一聊天消息加密和解密
1.使用上述创建的频道来加密消息和链接文档:https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/double-ratchet/?#encrypt-and-decrypt-messages。
// 一对一聊天消息加密
// 准备一条消息
String messageToEncrypt = "你好,User2!";
String encrypted = channel.encrypt(messageToEncrypt);
2.将加密的消息内容发送到Chat SDK,并以自定义消息发送
// `msgID`由API返回以供按需使用
String msgID = V2TIMManager.getInstance().sendC2CCustomMessage("virgil加密消息", "接收者用户ID", new V2TIMValueCallback<V2TIMMessage>() {
@Override
public void onSuccess(V2TIMMessage message) {
// 一对一文本消息发送成功
}
@Override
public void onError(int code, String desc) {
// 发送一对一文本消息失败
}
});
3.对方接收自定义消息后
// 设置事件监听器
V2TIMManager.getInstance().addSimpleMsgListener(simpleMsgListener);
/**
* 接收自定义一对一消息
* @param msgID 消息ID
* @param sender 发送者信息
* @param customData 发送的内容
*/
public void onRecvC2CCustomMessage(String msgID, V2TIMUserInfo sender, byte[] customData) {
Log.i("onRecvC2CCustomMessage", "msgID:" + msgID + ", 来自:" + sender.getNickName() + ", 内容:" + new String(customData));
// 调用E3Kit解密消息
}
4.对方调用E3Kit进行解密并渲染,如下所示:
// 解密消息
String decrypted = channel.decrypt(encrypted);
启动频道(群组)
1.调用ethree.createGroup创建群组,文档链接:https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/group-chat/?#create-group-chat。
// 创建群组
ethree.createGroup(groupId, users).addCallback(new OnResultListener<Group>() {
@Override public void onSuccess(Group group) {
// 群组创建成功并保存在本地!
}
@Override public void onError(@NotNull Throwable throwable) {
// 错误处理
}
});
2.如果需要添加群组成员,下面的代码如下。您可以调用remove方法删除群组成员。文档链接:https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/group-chat/?#add-new-participant。
// 添加群组成员
group.add(users.get("Den")).addCallback(new OnCompleteListener() {
@Override public void onSuccess() {
// Den被添加!
}
@Override public void onError(@NotNull Throwable throwable) {
// 错误处理
}
});
3.调用Chat SDK的createGroup创建群组,joinGroup或inviteUserToGroup添加群组成员。
V2TIMManager.getInstance().createGroup(V2TIMManager.GROUP_TYPE_WORK, null, "groupA", new V2TIMValueCallback<String>() {
@Override
public void onSuccess(String s) {
// 群组创建成功
}
@Override
public void onError(int code, String desc) {
// 创建群组失败
}
});
// 监听群组创建通知
V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {
@Override
public void onGroupCreated(String groupID) {
// 群组已创建。`groupID`是创建的群组的ID。
}
});
// 邀请`userA`用户加入`groupA`群组
List<String> userIDList = new ArrayList<>();
userIDList.add("userA");
V2TIMManager.getGroupManager().inviteUserToGroup("groupA", userIDList, new V2TIMValueCallback<List<V2TIMGroupMemberOperationResult>>() {
@Override
public void onSuccess(List<V2TIMGroupMemberOperationResult> v2TIMGroupMemberOperationResults) {
// 用户成功被邀请加入群组
}
@Override
public void onError(int code, String desc) {
// 邀请用户加入群组失败
}
});
// 监听群组邀请事件
V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {
@Override
public void onMemberInvited(String groupID, V2TIMGroupMemberInfo opUser, List<V2TIMGroupMemberInfo> memberList) {
// 用户被邀请加入群组。此回调可以包含一些UI提示。
}
});
群聊消息加密和解密
1.使用上述创建的群组来加密消息并链接文档:https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/group-chat/?#encrypt-and-decrypt-messages。
// 群组消息加密
// 准备一条消息
String messageToEncrypt = "你好,Bob和Carol!";
String encrypted = group.encrypt(messageToEncrypt);
2.将加密的消息内容发送到腾讯Chat SDK,并以自定义消息发送
String msgID = V2TIMManager.getInstance().sendGroupCustomMessage("virgil加密消息".getBytes(), "groupID", V2TIMMessage.V2TIM_PRIORITY_NORMAL, new V2TIMValueCallback<V2TIMMessage>() {
@Override
public void onSuccess(V2TIMMessage message) {
// 自定义群组消息发送成功
}
3.当对方腾讯云Chat SDK接收到自定义消息后,
// 设置事件监听器
V2TIMManager.getInstance().addSimpleMsgListener(simpleMsgListener);
/**
* 接收自定义群组消息
* @param msgID 消息ID
* @param groupID 群组ID
* @param sender 发送者的群组成员信息
* @param customData 发送的内容
*/
public void onRecvGroupCustomMessage(String msgID, String groupID, V2TIMGroupMemberInfo sender, byte[] customData) {
Log.i("onRecvGroupCustomMessage", "msgID:" + msgID + ", groupID:" + groupID + ", 来自:" + sender.getNickName() + ", 内容:" + new String(customData));
// 调用E3Kit解密消息
}
4.对方进行解密并渲染,如下所示:
// 群组消息解密
String decrypted = group.decrypt(encrypted, users.get("Alice"));
注意:在使用此端到端加密方案后,imsdk的本地聊天记录搜索功能将无法使用。
立即订购
点击这里快速进入购买页面进行订单。