update connect

This commit is contained in:
SL 2023-08-20 11:31:13 +08:00
parent eb54d0f4d6
commit b0069699df
28 changed files with 195 additions and 203 deletions

2
.idea/misc.xml generated
View File

@ -8,7 +8,7 @@
</option>
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View File

@ -3,6 +3,7 @@ package com.xinbida.wukongdemo;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
@ -130,6 +131,7 @@ public class MainActivity extends AppCompatActivity {
JSONObject jsonObject = new JSONObject(data);
String tcp_addr = jsonObject.optString("tcp_addr");
String[] strings = tcp_addr.split(":");
Log.e("获取连接的IP","-->"+data);
andPortListener.onGetSocketIpAndPort(strings[0], Integer.parseInt(strings[1]));
} catch (JSONException e) {
throw new RuntimeException(e);

View File

@ -34,6 +34,8 @@ class MessageAdapter extends BaseMultiItemQuickAdapter<UIMessageEntity, BaseView
}
String name = uiMessageEntity.msg.fromUID.substring(0, 1);
nameTv.setText(name);
contentTv.setText(uiMessageEntity.msg.baseContentMsgModel.getDisplayContent());
if (uiMessageEntity.msg.baseContentMsgModel!=null){
contentTv.setText(uiMessageEntity.msg.baseContentMsgModel.getDisplayContent());
}
}
}

View File

@ -1 +1 @@
270067ab5c7532476f63dd87238a22f5
5eab9c1249668bd09cfb8a5718dc9643

View File

@ -1 +1 @@
0467491103963d99eb9ebc6eb9b53b9e69c0b914
b16bea7a6426af069315ace7611d0ed3a2c6aa8f

View File

@ -1 +1 @@
221fe85ce0f33eaa2e3845512630bb5888070a5f087dfb99acb6d169a9cebd24
5cb5fc944333eeffd03bdd716ff17366d0cb489e2aa48a1f9cccfe4062dea75c

View File

@ -1 +1 @@
bca2b8de1699abf34669d9621d97a9e479d5e850d8821ed786aaecd422c4de5d622d40ae2349ae700ac841b5084b42243e3d2a58f3f2e7ece73031268aab4b1c
4325ab87ab3ec56e9b44a5965526825a1e26370e7f5d59bdf7e58f1deefbb9061bc11164af920bcda809e76f2ccaa550d89602ad0e6d1e4a1ebf636f29c1e876

View File

@ -8,6 +8,6 @@
<versions>
<version>1.0.1</version>
</versions>
<lastUpdated>20230723092612</lastUpdated>
<lastUpdated>20230820031318</lastUpdated>
</versioning>
</metadata>

View File

@ -1 +1 @@
b02d2b70b6fded0280d37f36fcbcb04a
c9af3f3712d90a532edf6c36cb9cbaff

View File

@ -1 +1 @@
8a0f70f3f2c3d90ee9d5cd55bf7c9b69ccdc2d13
1b93babf2a04c0b02d01bde8b390c911b159536b

View File

@ -1 +1 @@
a0d2ef51822269eeb0fe540d7c736dfb16b7edecad096c123570b9fe40321171
aa187a0220cd5366a8cee104ece1f2d570ea7c9cce02d24b21941393b6f38ff6

View File

@ -1 +1 @@
39d724b42413976f8a1680f17a9834bd77a5418cf454ed0440d37d8e24500904384d67c00f9d560c6c6e034489715903828316a05c80e8680abfa8ec24969771
6c02439c3b2faaf9b36e4e747ee6216210d72ff0edc436db71d4080fd1ce12e91fd70a68dac0f7eea3aa79ea4c8f75aab2a397fe8ff1c8ca03f986e5566800f2

View File

@ -50,3 +50,4 @@
-keep,includedescriptorclasses class net.sqlcipher.** { *; }
-keep,includedescriptorclasses interface net.sqlcipher.** { *; }
-flattenpackagehierarchy 'wkim'

View File

@ -12,7 +12,7 @@ import com.xinbida.wukongim.manager.MsgManager;
import com.xinbida.wukongim.manager.ReminderManager;
import com.xinbida.wukongim.manager.RobotManager;
import com.xinbida.wukongim.message.MessageHandler;
import com.xinbida.wukongim.utils.Curve25519Utils;
import com.xinbida.wukongim.utils.CryptoUtils;
import com.xinbida.wukongim.utils.WKLoggerUtils;
/**
@ -70,7 +70,7 @@ public class WKIM {
WKIMApplication.getInstance().setUid(uid);
WKIMApplication.getInstance().setToken(token);
// 初始化加密key
Curve25519Utils.getInstance().initKey();
CryptoUtils.getInstance().initKey();
// 初始化默认消息类型
getMsgManager().initNormalMsg();
// 初始化数据库

View File

@ -490,6 +490,9 @@ public class ConversationDbManager {
extra.browseTo = WKCursor.readLong(cursor, "browse_to");
extra.draftUpdatedAt = WKCursor.readLong(cursor, "draft_updated_at");
extra.version = WKCursor.readLong(cursor, "version");
if (cursor.getColumnIndex("extra_version") > 0) {
extra.version = WKCursor.readLong(cursor, "extra_version");
}
return extra;
}

View File

@ -278,7 +278,9 @@ public class MsgDbManager {
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
WKMsg wkMsg = serializeMsg(cursor);
wkMsg.setChannelInfo(wkChannel);
messageIds.add(wkMsg.messageID);
if (!TextUtils.isEmpty(wkMsg.messageID)){
messageIds.add(wkMsg.messageID);
}
if (wkMsg.baseContentMsgModel != null && wkMsg.baseContentMsgModel.reply != null && !TextUtils.isEmpty(wkMsg.baseContentMsgModel.reply.message_id)) {
replyMsgIds.add(wkMsg.baseContentMsgModel.reply.message_id);
}
@ -473,7 +475,7 @@ public class MsgDbManager {
return msg;
}
public synchronized void insertMsgList1(List<WKMsg> list) {
public synchronized void insertMsgList(List<WKMsg> list) {
if (list == null || list.size() == 0) return;
if (list.size() == 1) {
insertMsg(list.get(0));
@ -1238,13 +1240,41 @@ public class MsgDbManager {
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
WKMsg msg = serializeMsg(cursor);
boolean isAdd = true;
if (msg.channelType == WKChannelType.GROUP) {
//查询群成员信息
gChannelIds.add(msg.channelID);
for (int i = 0; i < gChannelIds.size(); i++) {
if (gChannelIds.get(i).equals(msg.fromUID)) {
isAdd = false;
break;
}
}
if (isAdd) {
gChannelIds.add(msg.fromUID);
}
} else {
pChannelIds.add(msg.channelID);
for (int i = 0; i < pChannelIds.size(); i++) {
if (pChannelIds.get(i).equals(msg.channelID)) {
isAdd = false;
break;
}
}
if (isAdd) {
pChannelIds.add(msg.channelID);
}
}
fromChannelIds.add(msg.fromUID);
isAdd = true;
for (int i = 0; i < fromChannelIds.size(); i++) {
if (fromChannelIds.get(i).equals(msg.fromUID)) {
isAdd = false;
break;
}
}
if (isAdd) {
fromChannelIds.add(msg.fromUID);
}
list.add(msg);
}

View File

@ -5,7 +5,7 @@ import android.os.Parcelable;
/**
* 2020-05-10 19:16
* 狸猫频道搜索结果
* 频道搜索结果
*/
public class WKChannelSearchResult implements Parcelable {
//频道信息

View File

@ -5,7 +5,7 @@ import android.os.Parcelable;
/**
* 2020-05-10 22:26
* 狸猫消息搜索结果
* 消息搜索结果
*/
public class WKMessageSearchResult implements Parcelable {
//消息对应的频道信息

View File

@ -6,13 +6,11 @@ import com.xinbida.wukongim.WKIM;
import com.xinbida.wukongim.WKIMApplication;
import com.xinbida.wukongim.interfaces.IConnectionStatus;
import com.xinbida.wukongim.interfaces.IGetIpAndPort;
import com.xinbida.wukongim.interfaces.IGetSocketIpAndPortListener;
import com.xinbida.wukongim.message.ConnectionHandler;
import com.xinbida.wukongim.message.MessageHandler;
import com.xinbida.wukongim.utils.WKLoggerUtils;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
@ -34,7 +32,7 @@ public class ConnectionManager extends BaseManager {
private IGetIpAndPort iGetIpAndPort;
private ConcurrentHashMap<String, IConnectionStatus> concurrentHashMap;
private ConcurrentHashMap<String, IConnectionStatus> connectionListenerMap;
// 连接
public void connection() {
@ -100,9 +98,9 @@ public class ConnectionManager extends BaseManager {
}
public void setConnectionStatus(int status, String reason) {
if (concurrentHashMap != null && concurrentHashMap.size() > 0) {
if (connectionListenerMap != null && connectionListenerMap.size() > 0) {
runOnMainThread(() -> {
for (Map.Entry<String, IConnectionStatus> entry : concurrentHashMap.entrySet()) {
for (Map.Entry<String, IConnectionStatus> entry : connectionListenerMap.entrySet()) {
entry.getValue().onStatus(status, reason);
}
});
@ -112,14 +110,14 @@ public class ConnectionManager extends BaseManager {
// 监听连接状态
public void addOnConnectionStatusListener(String key, IConnectionStatus iConnectionStatus) {
if (iConnectionStatus == null || TextUtils.isEmpty(key)) return;
if (concurrentHashMap == null) concurrentHashMap = new ConcurrentHashMap<>();
concurrentHashMap.put(key, iConnectionStatus);
if (connectionListenerMap == null) connectionListenerMap = new ConcurrentHashMap<>();
connectionListenerMap.put(key, iConnectionStatus);
}
// 移除监听
public void removeOnConnectionStatusListener(String key) {
if (!TextUtils.isEmpty(key) && concurrentHashMap != null) {
concurrentHashMap.remove(key);
if (!TextUtils.isEmpty(key) && connectionListenerMap != null) {
connectionListenerMap.remove(key);
}
}
}

View File

@ -299,7 +299,7 @@ public class ConversationManager extends BaseManager {
List<WKUIConversationMsg> uiMsgList = new ArrayList<>();
if (conversationMsgList.size() > 0 || msgList.size() > 0) {
if (msgList.size() > 0) {
MsgDbManager.getInstance().insertMsgList1(msgList);
MsgDbManager.getInstance().insertMsgList(msgList);
}
try {
if (conversationMsgList.size() > 0) {

View File

@ -82,7 +82,7 @@ public class MsgManager extends BaseManager {
return MsgManagerBinder.msgManager;
}
private final long limOrderSeqFactor = 1000L;
private final long wkOrderSeqFactor = 1000L;
// 消息修改
private ConcurrentHashMap<String, IRefreshMsg> refreshMsgListenerMap;
// 监听发送消息回调
@ -272,10 +272,10 @@ public class MsgManager extends BaseManager {
}
private long getOrNearbyMsgSeq(long orderSeq) {
if (orderSeq % limOrderSeqFactor == 0) {
return orderSeq / limOrderSeqFactor;
if (orderSeq % wkOrderSeqFactor == 0) {
return orderSeq / wkOrderSeqFactor;
}
return (orderSeq - orderSeq % limOrderSeqFactor) / limOrderSeqFactor;
return (orderSeq - orderSeq % wkOrderSeqFactor) / wkOrderSeqFactor;
}
/**
@ -307,8 +307,8 @@ public class MsgManager extends BaseManager {
oldestOrderSeq = aroundMsgOrderSeq;
} else {
if (minOrderSeq + limit < aroundMsgOrderSeq) {
if (aroundMsgOrderSeq % limOrderSeqFactor == 0) {
oldestOrderSeq = (aroundMsgOrderSeq / limOrderSeqFactor - 3) * limOrderSeqFactor;
if (aroundMsgOrderSeq % wkOrderSeqFactor == 0) {
oldestOrderSeq = (aroundMsgOrderSeq / wkOrderSeqFactor - 3) * wkOrderSeqFactor;
} else
oldestOrderSeq = aroundMsgOrderSeq - 3;
// oldestOrderSeq = aroundMsgOrderSeq;
@ -468,18 +468,18 @@ public class MsgManager extends BaseManager {
long tempOrderSeq = MsgDbManager.getInstance().getMaxOrderSeq(channelID, channelType);
return tempOrderSeq + 1;
}
return messageSeq * limOrderSeqFactor;
return messageSeq * wkOrderSeqFactor;
}
public long getMessageSeq(long messageOrderSeq) {
if (messageOrderSeq % limOrderSeqFactor == 0) {
return messageOrderSeq / limOrderSeqFactor;
if (messageOrderSeq % wkOrderSeqFactor == 0) {
return messageOrderSeq / wkOrderSeqFactor;
}
return 0;
}
public long getReliableMessageSeq(long messageOrderSeq) {
return messageOrderSeq / limOrderSeqFactor;
return messageOrderSeq / wkOrderSeqFactor;
}
public long getMaxSeqWithChannel(String channelID, byte channelType) {
@ -910,7 +910,7 @@ public class MsgManager extends BaseManager {
MsgDbManager.getInstance().saveOrUpdateMsgExtras(msgExtraList);
}
if (msgList.size() > 0) {
MsgDbManager.getInstance().insertMsgList1(msgList);
MsgDbManager.getInstance().insertMsgList(msgList);
}
}
@ -1038,7 +1038,7 @@ public class MsgManager extends BaseManager {
msg.clientMsgNO = wkSyncRecent.client_msg_no;
msg.fromUID = wkSyncRecent.from_uid;
msg.timestamp = wkSyncRecent.timestamp;
msg.orderSeq = msg.messageSeq * limOrderSeqFactor;
msg.orderSeq = msg.messageSeq * wkOrderSeqFactor;
msg.voiceStatus = wkSyncRecent.voice_status;
msg.isDeleted = wkSyncRecent.is_deleted;
msg.status = WKSendMsgResult.send_success;

View File

@ -110,7 +110,9 @@ class ClientHandler implements IDataHandler, IConnectHandler,
}
}
byte[] buffBytes = iNonBlockingConnection.readBytesByLength(readLen);
ConnectionHandler.getInstance().receivedData(buffBytes.length, buffBytes);
if (buffBytes.length > 0) {
ConnectionHandler.getInstance().receivedData(buffBytes);
}
}
} catch (IOException e) {
@ -123,9 +125,20 @@ class ClientHandler implements IDataHandler, IConnectHandler,
@Override
public boolean onDisconnect(INonBlockingConnection iNonBlockingConnection) {
WKLoggerUtils.getInstance().e("连接断开");
if (iNonBlockingConnection != null && !TextUtils.isEmpty(iNonBlockingConnection.getId()) && iNonBlockingConnection.getAttachment() != null) {
String id = iNonBlockingConnection.getId();
Object attachmentObject = iNonBlockingConnection.getAttachment();
if (attachmentObject instanceof String) {
String att = (String) attachmentObject;
String attStr = "close" + id;
if (att.equals(attStr)) {
return true;
}
}
}
if (WKIMApplication.getInstance().isCanConnect) {
ConnectionHandler.getInstance().forcedReconnection();
}else {
} else {
WKLoggerUtils.getInstance().e("不能重连-->");
}
close(iNonBlockingConnection);

View File

@ -81,6 +81,10 @@ public class ConnectionHandler {
private final long requestIPTimeoutTime = 6;
public String socketSingleID;
private String lastRequestId;
private final long reconnectDelay = 1500;
public volatile Handler reconnectionHandler = new Handler(Objects.requireNonNull(Looper.myLooper()));
Runnable reconnectionRunnable = this::reconnection;
public synchronized void forcedReconnection() {
isReConnecting = false;
@ -99,6 +103,7 @@ public class ConnectionHandler {
return;
}
connectStatus = WKConnectStatus.fail;
reconnectionHandler.removeCallbacks(reconnectionRunnable);
boolean isHaveNetwork = WKIMApplication.getInstance().isNetworkConnected();
if (isHaveNetwork) {
closeConnect();
@ -109,18 +114,7 @@ public class ConnectionHandler {
if (!ConnectionTimerHandler.getInstance().checkNetWorkTimerIsRunning) {
WKIM.getInstance().getConnectionManager().setConnectionStatus(WKConnectStatus.noNetwork, WKConnectReason.NoNetwork);
isReConnecting = false;
new Thread() {
@Override
public void run() {
super.run();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Handler(Looper.getMainLooper()).post(() -> reconnection());
}
}.start();
reconnectionHandler.postDelayed(reconnectionRunnable, reconnectDelay);
}
}
}
@ -128,7 +122,7 @@ public class ConnectionHandler {
private synchronized void getIPAndPort() {
if (!WKIMApplication.getInstance().isNetworkConnected()) {
isReConnecting = false;
reconnection();
reconnectionHandler.postDelayed(reconnectionRunnable, reconnectDelay);
return;
}
if (!WKIMApplication.getInstance().isCanConnect) {
@ -144,7 +138,7 @@ public class ConnectionHandler {
if (TextUtils.isEmpty(ip) || port == 0) {
WKLoggerUtils.getInstance().e("返回连接IP或port错误" + String.format("ip:%s & port:%s", ip, port));
isReConnecting = false;
reconnection();
reconnectionHandler.postDelayed(reconnectionRunnable, reconnectDelay);
} else {
if (lastRequestId.equals(requestId)) {
ConnectionHandler.this.ip = ip;
@ -156,7 +150,7 @@ public class ConnectionHandler {
} else {
if (connectionIsNull()) {
WKLoggerUtils.getInstance().e("请求IP的编号不一致重连中");
reconnection();
reconnectionHandler.postDelayed(reconnectionRunnable, reconnectDelay);
}
}
}
@ -190,8 +184,8 @@ public class ConnectionHandler {
sendMessage(new WKConnectMsg());
}
void receivedData(int length, byte[] data) {
MessageHandler.getInstance().cutBytes(length, data,
void receivedData(byte[] data) {
MessageHandler.getInstance().cutBytes( data,
new IReceivedMsgListener() {
public void sendAckMsg(
@ -524,8 +518,9 @@ public class ConnectionHandler {
private void closeConnect() {
if (connection != null && connection.isOpen()) {
try {
WKLoggerUtils.getInstance().e("stop connection" + connection.getId());
WKLoggerUtils.getInstance().e("stop connection:" + connection.getId());
// connection.flush();
connection.setAttachment("close" + connection.getId());
connection.close();
} catch (IOException e) {
e.printStackTrace();

View File

@ -25,9 +25,8 @@ import com.xinbida.wukongim.protocol.WKReceivedAckMsg;
import com.xinbida.wukongim.protocol.WKReceivedMsg;
import com.xinbida.wukongim.protocol.WKSendAckMsg;
import com.xinbida.wukongim.protocol.WKSendMsg;
import com.xinbida.wukongim.utils.AESEncryptUtils;
import com.xinbida.wukongim.utils.BigTypeUtils;
import com.xinbida.wukongim.utils.Curve25519Utils;
import com.xinbida.wukongim.utils.CryptoUtils;
import com.xinbida.wukongim.utils.WKLoggerUtils;
import com.xinbida.wukongim.utils.WKTypeUtils;
@ -42,6 +41,7 @@ import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashMap;
/**
* 5/21/21 11:28 AM
@ -70,7 +70,7 @@ class MessageConvertHandler {
+ WKIMApplication.getInstance().getToken().length()
+ connectMsg.clientTimeStampLength
+ connectMsg.clientKeyLength
+ Curve25519Utils.getInstance().getPublicKey().length();
+ CryptoUtils.getInstance().getPublicKey().length();
byte[] remainingBytes = WKTypeUtils.getInstance().getRemainingLengthByte(remainingLength);
int totalLen = 1 + remainingBytes.length
@ -84,7 +84,7 @@ class MessageConvertHandler {
+ WKIMApplication.getInstance().getToken().length()
+ connectMsg.clientTimeStampLength
+ connectMsg.clientKeyLength
+ Curve25519Utils.getInstance().getPublicKey().length();
+ CryptoUtils.getInstance().getPublicKey().length();
byte[] bytes = new byte[totalLen];
ByteBuffer buffer = ByteBuffer.allocate(totalLen).order(
@ -102,8 +102,8 @@ class MessageConvertHandler {
buffer.putShort((short) WKIMApplication.getInstance().getToken().length());
buffer.put(WKTypeUtils.getInstance().stringToByte(WKIMApplication.getInstance().getToken()));
buffer.putLong(connectMsg.clientTimestamp);
buffer.putShort((short) Curve25519Utils.getInstance().getPublicKey().length());
buffer.put(WKTypeUtils.getInstance().stringToByte(Curve25519Utils.getInstance().getPublicKey()));
buffer.putShort((short) CryptoUtils.getInstance().getPublicKey().length());
buffer.put(WKTypeUtils.getInstance().stringToByte(CryptoUtils.getInstance().getPublicKey()));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
@ -144,16 +144,16 @@ class MessageConvertHandler {
byte[] enSendMsg(WKSendMsg sendMsg) {
// 先加密内容
byte[] contentByte = AESEncryptUtils.aesEncrypt(sendMsg.payload, Curve25519Utils.getInstance().aesKey, Curve25519Utils.getInstance().salt);
String sendContent = AESEncryptUtils.base64Encode(contentByte);
byte[] contentByte = CryptoUtils.getInstance().aesEncrypt(sendMsg.payload);
String sendContent = CryptoUtils.getInstance().base64Encode(contentByte);
String msgKey = sendMsg.clientSeq
+ sendMsg.clientMsgNo
+ sendMsg.channelId
+ sendMsg.channelType
+ sendContent;
byte[] msgKeyByte = AESEncryptUtils.aesEncrypt(msgKey, Curve25519Utils.getInstance().aesKey, Curve25519Utils.getInstance().salt);
String msgKeyContent = AESEncryptUtils.base64Encode(msgKeyByte);
msgKeyContent = AESEncryptUtils.digest(msgKeyContent);
byte[] msgKeyByte = CryptoUtils.getInstance().aesEncrypt(msgKey);
String msgKeyContent = CryptoUtils.getInstance().base64Encode(msgKeyByte);
msgKeyContent = CryptoUtils.getInstance().digestMD5(msgKeyContent);
int topicLen = 0;
if (sendMsg.setting.topic == 1) {
@ -269,7 +269,7 @@ class MessageConvertHandler {
connectAckMsg.serverKey = serverKey;
connectAckMsg.salt = salt;
//保存公钥和安全码
Curve25519Utils.getInstance().setServerKeyAndSalt(connectAckMsg.serverKey, connectAckMsg.salt);
CryptoUtils.getInstance().setServerKeyAndSalt(connectAckMsg.serverKey, connectAckMsg.salt);
connectAckMsg.timeDiff = time;
connectAckMsg.remainingLength = remainingLength;
@ -428,7 +428,7 @@ class MessageConvertHandler {
if (read == -1) return receivedMsg;
String content = WKTypeUtils.getInstance().bytesToString(payload);
receivedMsg.payload = AESEncryptUtils.aesDecrypt(AESEncryptUtils.base64Decode(content), Curve25519Utils.getInstance().aesKey, Curve25519Utils.getInstance().salt);
receivedMsg.payload = CryptoUtils.getInstance().aesDecrypt(CryptoUtils.getInstance().base64Decode(content));
String msgKey = receivedMsg.messageID
+ receivedMsg.messageSeq
+ receivedMsg.clientMsgNo
@ -437,9 +437,9 @@ class MessageConvertHandler {
+ receivedMsg.channelID
+ receivedMsg.channelType
+ content;
byte[] result = AESEncryptUtils.aesEncrypt(msgKey, Curve25519Utils.getInstance().aesKey, Curve25519Utils.getInstance().salt);
String base64Result = AESEncryptUtils.base64Encode(result);
String localMsgKey = AESEncryptUtils.digest(base64Result);
byte[] result = CryptoUtils.getInstance().aesEncrypt(msgKey);
String base64Result = CryptoUtils.getInstance().base64Encode(result);
String localMsgKey = CryptoUtils.getInstance().digestMD5(base64Result);
if (!localMsgKey.equals(receivedMsg.msgKey)) {
return null;
}

View File

@ -120,11 +120,9 @@ public class MessageHandler {
private List<WKSyncMsg> receivedMsgList;
private byte[] cacheData = null;
synchronized void cutBytes(int available_len, byte[] available_bytes,
synchronized void cutBytes(byte[] available_bytes,
IReceivedMsgListener mIReceivedMsgListener) {
if (available_len == -1) {
return;
}
if (cacheData == null || cacheData.length == 0) cacheData = available_bytes;
else {
//如果上次还存在未解析完的消息将新数据追加到缓存数据中
@ -160,7 +158,6 @@ public class MessageHandler {
WKLoggerUtils.getInstance().e("pong...");
byte[] bytes = Arrays.copyOfRange(lastMsgBytes, 1, lastMsgBytes.length);
cacheData = lastMsgBytes = bytes;
} else {
if (packetType < 10) {
// TODO: 2019-12-21 计算剩余长度
@ -202,7 +199,7 @@ public class MessageHandler {
private void acceptMsg(byte[] bytes, int no_persist, int sync_once, int red_dot,
IReceivedMsgListener mIReceivedMsgListener) {
// 字节数组转成消息数组
if (bytes != null && bytes.length > 0) {
WKBaseMsg g_msg;
g_msg = MessageConvertHandler.getInstance().decodeMessage(bytes);
@ -319,7 +316,7 @@ public class MessageHandler {
}
allList.add(mMsg.wkMsg);
}
MsgDbManager.getInstance().insertMsgList1(saveMsgList);
MsgDbManager.getInstance().insertMsgList(saveMsgList);
//将消息push给UI
WKIM.getInstance().getMsgManager().pushNewMsg(allList);
groupMsg(list);

View File

@ -1,10 +1,14 @@
package com.xinbida.wukongim.utils;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import com.xinbida.wukongim.WKIMApplication;
import org.whispersystems.curve25519.Curve25519;
import org.whispersystems.curve25519.Curve25519KeyPair;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
@ -17,6 +21,7 @@ import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
@ -25,57 +30,79 @@ import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* 2/26/21 12:11 PM
* 2/25/21 6:20 PM
* 消息加密处理
*/
public class AESEncryptUtils {
/**
* 加密算法
*/
private static final String KEY_ALGORITHM = "AES";
/**
* AES 密钥长度32 字节范围16 - 32 字节
*/
public static final int SECRET_KEY_LENGTH = 32;
/**
* 字符编码
*/
public class CryptoUtils {
private byte[] privateKey, publicKey;
private byte[] serverKey;
private String aesKey;
private String salt;
private static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8;
/**
* 秘钥长度不足 16 个字节时默认填充位数
*/
private static final String DEFAULT_VALUE = "0";
/**
* 加解密算法/工作模式/填充方式
*/
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";
private CryptoUtils() {
}
private static class CryptoUtilsBinder {
private final static CryptoUtils util = new CryptoUtils();
}
public static CryptoUtils getInstance() {
return CryptoUtilsBinder.util;
}
public void initKey() {
Curve25519KeyPair keyPair = Curve25519.getInstance(Curve25519.BEST).generateKeyPair();
privateKey = keyPair.getPrivateKey();
publicKey = keyPair.getPublicKey();
}
public String getPublicKey() {
return Base64.encodeToString(publicKey, Base64.NO_WRAP);
}
/**
* aes加密
* 设置服务端公钥和安全码
*
* @param sSrc 内容
* @param sKey key
* @param salt 安全码
* @return
* @throws Exception
* @param serverKey 公钥
* @param salt 安全码
*/
public static byte[] aesEncrypt(String sSrc, String sKey, String salt) {
public void setServerKeyAndSalt(String serverKey, String salt) {
if (TextUtils.isEmpty(serverKey) || TextUtils.isEmpty(salt)) {
this.serverKey = new byte[0];
this.salt = "";
return;
}
this.serverKey = base64Decode(serverKey);
this.salt = salt;
Curve25519 cipher = Curve25519.getInstance(Curve25519.BEST);
byte[] sharedSecret = cipher.calculateAgreement(this.serverKey, privateKey);
String key = digestMD5(base64Encode(sharedSecret));
if (!TextUtils.isEmpty(key) && key.length() > 16) {
aesKey = key.substring(0, 16);
}
}
public byte[] aesEncrypt(String sSrc) {
Cipher cipher = null;
byte[] encrypted = null;
try {
cipher = Cipher.getInstance(CIPHER_ALGORITHM);
byte[] raw = sKey.getBytes(CHARSET_UTF8);
byte[] raw = aesKey.getBytes(CHARSET_UTF8);
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
//使用CBC模式需要一个向量iv可增加加密算法的强度
IvParameterSpec iv = new IvParameterSpec(salt.getBytes(CHARSET_UTF8));
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
encrypted = cipher.doFinal(sSrc.getBytes());
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException |
InvalidAlgorithmParameterException | IllegalBlockSizeException |
BadPaddingException e) {
e.printStackTrace();
Log.e("加密错误:", "-->");
}
@ -90,12 +117,10 @@ public class AESEncryptUtils {
* 解密
*
* @param sSrc 内容
* @param sKey 密钥
* @param salt 安全码
* @return 内容
*/
public static String aesDecrypt(byte[] sSrc, String sKey, String salt) {
byte[] raw = sKey.getBytes(CHARSET_UTF8);
public String aesDecrypt(byte[] sSrc) {
byte[] raw = aesKey.getBytes(CHARSET_UTF8);
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher;
String content = "";
@ -114,21 +139,18 @@ public class AESEncryptUtils {
return content;
}
/**
* Base64 字符串 解码成 字节数组
*/
public static byte[] base64Decode(String data) {
public byte[] base64Decode(String data) {
return Base64.decode(data, Base64.NO_WRAP);
}
/**
* 字节数组 转换成 Base64 编码
*/
public static String base64Encode(byte[] data) {
public String base64Encode(byte[] data) {
return Base64.encodeToString(data, Base64.NO_WRAP);
}
public static String digest(String password) {
public String digestMD5(String password) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] bytes = digest.digest(password.getBytes());
@ -148,9 +170,8 @@ public class AESEncryptUtils {
}
}
public static boolean checkRSASign(String content, String sign) {
public boolean checkRSASign(String content, String sign) {
try {
String publicKey = WKIMApplication.getInstance().getRSAPublicKey();
byte[] keyByte = base64Decode(publicKey);
String key = new String(keyByte);
@ -165,9 +186,10 @@ public class AESEncryptUtils {
boolean result = signature.verify(base64Decode(sign));
Log.e("校验结果", result + "");
return result;
} catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | InvalidKeySpecException e) {
} catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException |
InvalidKeySpecException e) {
e.printStackTrace();
Log.e("校验异常", e.getLocalizedMessage());
Log.e("校验异常", Objects.requireNonNull(e.getLocalizedMessage()));
return false;
}
}

View File

@ -1,71 +0,0 @@
package com.xinbida.wukongim.utils;
import android.text.TextUtils;
import android.util.Base64;
import org.whispersystems.curve25519.Curve25519;
import org.whispersystems.curve25519.Curve25519KeyPair;
/**
* 2/25/21 6:20 PM
* 消息加密处理
*/
public class Curve25519Utils {
private byte[] privateKey, publicKey;
private byte[] serverKey;
public String aesKey;
public String salt;
private Curve25519Utils() {
}
private static class Curve25519UtilsBinder {
private final static Curve25519Utils util = new Curve25519Utils();
}
public static Curve25519Utils getInstance() {
return Curve25519UtilsBinder.util;
}
public void initKey() {
Curve25519KeyPair keyPair = Curve25519.getInstance(Curve25519.BEST).generateKeyPair();
privateKey = keyPair.getPrivateKey();
publicKey = keyPair.getPublicKey();
}
public String getPublicKey() {
return Base64.encodeToString(publicKey, Base64.NO_WRAP);
}
/**
* 设置服务端公钥和安全码
*
* @param serverKey 公钥
* @param salt 安全码
*/
public void setServerKeyAndSalt(String serverKey, String salt) {
if (TextUtils.isEmpty(serverKey) || TextUtils.isEmpty(salt)) {
this.serverKey = new byte[0];
this.salt = "";
return;
}
this.serverKey = AESEncryptUtils.base64Decode(serverKey);
this.salt = salt;
Curve25519 cipher = Curve25519.getInstance(Curve25519.BEST);
byte[] sharedSecret = cipher.calculateAgreement(this.serverKey, privateKey);
String key = AESEncryptUtils.digest(AESEncryptUtils.base64Encode(sharedSecret));
if (!TextUtils.isEmpty(key) && key.length() > 16) {
aesKey = key.substring(0, 16);
}
}
public String encode(String content) {
return content;
}
public String decode(String content) {
return content;
}
}