Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
新增 加密和压缩flags
  • Loading branch information
ohun committed Dec 27, 2015
1 parent 27f21a3 commit 5e69daa
Show file tree
Hide file tree
Showing 20 changed files with 199 additions and 109 deletions.
3 changes: 3 additions & 0 deletions mpush-api/src/main/java/com/shinemo/mpush/api/Constants.java
Expand Up @@ -12,6 +12,9 @@ public interface Constants {
int HEADER_LEN = 13; int HEADER_LEN = 13;
short MAGIC_NUM = 1122; short MAGIC_NUM = 1122;
byte HB = '\n'; byte HB = '\n';
int COMPRESS_LIMIT = 1024 * 10;
byte CRYPTO_FLAG = 0x01;
byte COMPRESS_FLAG = 0x02;
long TIME_DELAY = 1L; long TIME_DELAY = 1L;


String JVM_LOG_PATH = "/opt/"; String JVM_LOG_PATH = "/opt/";
Expand Down
2 changes: 1 addition & 1 deletion mpush-api/src/main/java/com/shinemo/mpush/api/Request.java
Expand Up @@ -10,7 +10,7 @@ public interface Request {


Command getCommand(); Command getCommand();


Packet getMessage(); byte[] getBody();


Connection getConnection(); Connection getConnection();


Expand Down
Expand Up @@ -27,6 +27,14 @@ public String getStringBody() {
return body == null ? "" : new String(body, Constants.UTF_8); return body == null ? "" : new String(body, Constants.UTF_8);
} }


public void setFlag(byte flag) {
this.flags |= flag;
}

public boolean hasFlag(byte flag) {
return (flags & flag) != 0;
}

@Override @Override
public String toString() { public String toString() {
return "Packet{" + return "Packet{" +
Expand Down
Expand Up @@ -83,5 +83,4 @@ private Packet readPacket(ByteBuf in, int bodyLength) {
packet.body = body; packet.body = body;
return packet; return packet;
} }

} }
Expand Up @@ -9,7 +9,6 @@
import com.shinemo.mpush.core.security.CipherManager; import com.shinemo.mpush.core.security.CipherManager;
import com.shinemo.mpush.tools.Jsons; import com.shinemo.mpush.tools.Jsons;
import com.shinemo.mpush.tools.Strings; import com.shinemo.mpush.tools.Strings;
import com.shinemo.mpush.tools.crypto.CryptoUtils;
import com.shinemo.mpush.tools.crypto.AESUtils; import com.shinemo.mpush.tools.crypto.AESUtils;
import com.shinemo.mpush.tools.crypto.RSAUtils; import com.shinemo.mpush.tools.crypto.RSAUtils;
import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerAdapter;
Expand Down
Expand Up @@ -3,19 +3,18 @@


import com.shinemo.mpush.api.MessageHandler; import com.shinemo.mpush.api.MessageHandler;
import com.shinemo.mpush.api.Request; import com.shinemo.mpush.api.Request;
import com.shinemo.mpush.api.protocol.Packet;


/** /**
* Created by ohun on 2015/12/22. * Created by ohun on 2015/12/22.
*/ */
public abstract class BaseMessageHandler<T> implements MessageHandler { public abstract class BaseMessageHandler<T> implements MessageHandler {
@Override @Override
public void handle(Request request) { public void handle(Request request) {
T t = decodeBody(request.getMessage()); T t = decodeBody(request.getBody());
handle(t, request); handle(t, request);
} }


public abstract T decodeBody(Packet packet); public abstract T decodeBody(byte[] data);


public abstract void handle(T body, Request request); public abstract void handle(T body, Request request);
} }
Expand Up @@ -10,8 +10,8 @@
*/ */
public class BindHandler extends BaseMessageHandler<String> { public class BindHandler extends BaseMessageHandler<String> {
@Override @Override
public String decodeBody(Packet packet) { public String decodeBody(byte[] body) {
return new String(packet.body, Constants.UTF_8); return new String(body, Constants.UTF_8);
} }


@Override @Override
Expand Down
Expand Up @@ -18,8 +18,8 @@
*/ */
public class FastConnectHandler extends BaseMessageHandler<FastConnectMessage> { public class FastConnectHandler extends BaseMessageHandler<FastConnectMessage> {
@Override @Override
public FastConnectMessage decodeBody(Packet packet) { public FastConnectMessage decodeBody(byte[] body) {
return Jsons.fromJson(packet.getStringBody(), FastConnectMessage.class); return Jsons.fromJson(body, FastConnectMessage.class);
} }


@Override @Override
Expand Down
@@ -1,59 +1,57 @@
package com.shinemo.mpush.core.handler; package com.shinemo.mpush.core.handler;


import com.shinemo.mpush.api.SessionInfo;
import com.shinemo.mpush.api.Constants; import com.shinemo.mpush.api.Constants;
import com.shinemo.mpush.api.Request; import com.shinemo.mpush.api.Request;
import com.shinemo.mpush.api.SessionInfo;
import com.shinemo.mpush.api.protocol.Packet; import com.shinemo.mpush.api.protocol.Packet;
import com.shinemo.mpush.core.message.HandShakeMessage; import com.shinemo.mpush.core.message.HandshakeMessage;
import com.shinemo.mpush.core.security.CredentialManager; import com.shinemo.mpush.core.message.HandshakeSuccessMsg;
import com.shinemo.mpush.core.security.ReusableToken; import com.shinemo.mpush.core.security.CipherManager;
import com.shinemo.mpush.core.security.ReusableTokenManager; import com.shinemo.mpush.core.security.ReusableSession;
import com.shinemo.mpush.core.security.ReusableSessionManager;
import com.shinemo.mpush.tools.Jsons; import com.shinemo.mpush.tools.Jsons;
import com.shinemo.mpush.tools.MPushUtil; import com.shinemo.mpush.tools.MPushUtil;
import com.shinemo.mpush.tools.crypto.CryptoUtils; import com.shinemo.mpush.tools.crypto.AESUtils;
import com.shinemo.mpush.tools.crypto.DESUtils;
import com.shinemo.mpush.tools.crypto.RSAUtils; import com.shinemo.mpush.tools.crypto.RSAUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;


import java.io.Serializable;
import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPrivateKey;
import java.util.HashMap;
import java.util.Map;


/** /**
* Created by ohun on 2015/12/24. * Created by ohun on 2015/12/24.
*/ */
public class HandShakeHandler extends BaseMessageHandler<HandShakeMessage> { public class HandshakeHandler extends BaseMessageHandler<HandshakeMessage> {
public static final Logger LOGGER = LoggerFactory.getLogger(HandShakeHandler.class); public static final Logger LOGGER = LoggerFactory.getLogger(HandshakeHandler.class);


@Override @Override
public HandShakeMessage decodeBody(Packet packet) { public HandshakeMessage decodeBody(byte[] body) {
RSAPrivateKey privateKey = CredentialManager.INSTANCE.getPrivateKey(); RSAPrivateKey privateKey = CipherManager.INSTANCE.getPrivateKey();
byte[] rawData = RSAUtils.decryptByPrivateKey(packet.body, privateKey); byte[] rawData = RSAUtils.decryptByPrivateKey(body, privateKey);
return Jsons.fromJson(new String(rawData, Constants.UTF_8), HandShakeMessage.class); return Jsons.fromJson(new String(rawData, Constants.UTF_8), HandshakeMessage.class);
} }


@Override @Override
public void handle(HandShakeMessage body, Request request) { public void handle(HandshakeMessage body, Request request) {
String serverKey = RandomStringUtils.randomAscii(CryptoUtils.DES_KEY_SIZE); byte[] iv = body.iv;
String clientKey = body.clientKey; byte[] clientKey = body.clientKey;
String desKey = CryptoUtils.mixString(clientKey, serverKey);//生成混淆密钥 byte[] serverKey = CipherManager.INSTANCE.randomAESKey();
SessionInfo info = new SessionInfo(body.osName, body.osVersion, body.clientVersion, body.deviceId, desKey); byte[] sessionKey = CipherManager.INSTANCE.mixKey(clientKey, serverKey);//会话密钥混淆 Client random
SessionInfo info = new SessionInfo(body.osName, body.osVersion, body.clientVersion,
body.deviceId, sessionKey, iv);
request.getConnection().setSessionInfo(info); request.getConnection().setSessionInfo(info);
ReusableToken token = ReusableTokenManager.INSTANCE.genToken(info); ReusableSession session = ReusableSessionManager.INSTANCE.genSession(info);
ReusableTokenManager.INSTANCE.saveToken(token); ReusableSessionManager.INSTANCE.saveSession(session);
Map<String, Serializable> resp = new HashMap<String, Serializable>(); HandshakeSuccessMsg resp = new HandshakeSuccessMsg();
resp.put("serverKey", serverKey); resp.serverKey = serverKey;
resp.put("serverHost", MPushUtil.getLocalIp()); resp.serverHost = MPushUtil.getLocalIp();
resp.put("serverTime", System.currentTimeMillis()); resp.serverTime = System.currentTimeMillis();
resp.put("heartbeat", Constants.HEARTBEAT_TIME); resp.heartbeat = Constants.HEARTBEAT_TIME;
resp.put("tokenId", token.tokenId); resp.sessionId = session.sessionId;
resp.put("tokenExpire", token.expireTime); resp.expireTime = session.expireTime;
byte[] responseData = DESUtils.encryptDES(Jsons.toJson(resp).getBytes(Constants.UTF_8), clientKey); byte[] responseData = AESUtils.encrypt(Jsons.toJson(resp).getBytes(Constants.UTF_8), clientKey, iv);
request.getResponse().sendRaw(responseData); request.getResponse().sendRaw(responseData);
LOGGER.info("会话密钥:{},clientKey={}, serverKey={}", desKey, clientKey, serverKey); LOGGER.info("会话密钥:{},clientKey={}, serverKey={}", sessionKey, clientKey, serverKey);


} }
} }
Expand Up @@ -9,7 +9,7 @@
public class HeartBeatHandler extends BaseMessageHandler<Void> { public class HeartBeatHandler extends BaseMessageHandler<Void> {


@Override @Override
public Void decodeBody(Packet packet) { public Void decodeBody(byte[] body) {
return null; return null;
} }


Expand Down
Expand Up @@ -9,7 +9,7 @@
*/ */
public class LoginHandler extends BaseMessageHandler<LoginMessage> { public class LoginHandler extends BaseMessageHandler<LoginMessage> {
@Override @Override
public LoginMessage decodeBody(Packet packet) { public LoginMessage decodeBody(byte[] body) {
return new LoginMessage(); return new LoginMessage();
} }


Expand Down
@@ -1,31 +1,51 @@
package com.shinemo.mpush.core.message; package com.shinemo.mpush.core.message;


import com.shinemo.mpush.api.Connection; import com.shinemo.mpush.api.*;
import com.shinemo.mpush.api.Request;
import com.shinemo.mpush.api.Response;
import com.shinemo.mpush.api.protocol.Command; import com.shinemo.mpush.api.protocol.Command;
import com.shinemo.mpush.api.protocol.Packet; import com.shinemo.mpush.api.protocol.Packet;
import com.shinemo.mpush.tools.IOUtils;
import com.shinemo.mpush.tools.crypto.AESUtils;


/** /**
* Created by ohun on 2015/12/22. * Created by ohun on 2015/12/22.
*/ */
public class NettyRequest implements Request{ public class NettyRequest implements Request {
private final Command command;
private final Packet message; private final Packet message;
private final Connection connection; private final Connection connection;
private Command command;
private byte[] body;


public NettyRequest(Packet message, Connection connection) { public NettyRequest(Packet message, Connection connection) {
this.message = message; this.message = message;
this.connection = connection; this.connection = connection;
this.command = Command.toCMD(message.cmd);
} }


public Command getCommand() { public Command getCommand() {
return command; return command == null ? command = Command.toCMD(message.cmd) : command;
} }


public Packet getMessage() { public byte[] getBody() {
return message; if (message.body == null) return null;
if (body == null) {
//1.解密
byte[] tmp = message.body;
if (message.hasFlag(Constants.CRYPTO_FLAG)) {
SessionInfo info = connection.getSessionInfo();
if (info != null && info.sessionKey != null) {
tmp = AESUtils.decrypt(tmp, info.sessionKey, info.iv);
}
}

//2.解压
if (message.hasFlag(Constants.COMPRESS_FLAG)) {
byte[] result = IOUtils.uncompress(tmp);
if (result.length > 0) {
tmp = result;
}
}
this.body = tmp;
}
return body;
} }


public Connection getConnection() { public Connection getConnection() {
Expand All @@ -34,8 +54,8 @@ public Connection getConnection() {


public Response getResponse() { public Response getResponse() {
Packet packet = new Packet(); Packet packet = new Packet();
packet.cmd = message.cmd; packet.cmd = this.message.cmd;
packet.sessionId = message.sessionId; packet.sessionId = this.message.sessionId;
return new NettyResponse(packet, connection); return new NettyResponse(packet, connection);
} }
} }
Expand Up @@ -3,7 +3,9 @@
import com.shinemo.mpush.api.Connection; import com.shinemo.mpush.api.Connection;
import com.shinemo.mpush.api.Constants; import com.shinemo.mpush.api.Constants;
import com.shinemo.mpush.api.Response; import com.shinemo.mpush.api.Response;
import com.shinemo.mpush.api.SessionInfo;
import com.shinemo.mpush.api.protocol.Packet; import com.shinemo.mpush.api.protocol.Packet;
import com.shinemo.mpush.tools.IOUtils;
import com.shinemo.mpush.tools.crypto.AESUtils; import com.shinemo.mpush.tools.crypto.AESUtils;


/** /**
Expand All @@ -19,7 +21,22 @@ public NettyResponse(Packet packet, Connection connection) {
} }


public void send(byte[] body) { public void send(byte[] body) {
packet.body = AESUtils.decrypt(body, connection.getSessionInfo().sessionKey, connection.getSessionInfo().iv); byte[] tmp = body;
//1.压缩
if (tmp.length > Constants.COMPRESS_LIMIT) {
byte[] result = IOUtils.compress(tmp);
if (result.length > 0) {
tmp = result;
packet.setFlag(Constants.COMPRESS_FLAG);
}
}
//2.加密
SessionInfo info = connection.getSessionInfo();
if (info != null && info.sessionKey != null) {
tmp = AESUtils.encrypt(tmp, info.sessionKey, info.iv);
packet.setFlag(Constants.CRYPTO_FLAG);
}
packet.body = tmp;
connection.send(packet); connection.send(packet);
} }


Expand Down
Expand Up @@ -104,8 +104,8 @@ public byte[] mixKey(byte[] clientKey, byte[] serverKey) {
byte a = clientKey[i]; byte a = clientKey[i];
byte b = serverKey[i]; byte b = serverKey[i];
int sum = Math.abs(a + b); int sum = Math.abs(a + b);
byte c = (sum % 2 == 0) ? a : b; int c = (sum % 2 == 0) ? a ^ b : b ^ a;
sessionKey[i] = c; sessionKey[i] = (byte) c;
} }
return sessionKey; return sessionKey;
} }
Expand Down
Expand Up @@ -20,8 +20,8 @@ public void testGetPublicKey() throws Exception {
byte[] clientKey = CipherManager.INSTANCE.randomAESKey(); byte[] clientKey = CipherManager.INSTANCE.randomAESKey();
byte[] serverKey = CipherManager.INSTANCE.randomAESKey(); byte[] serverKey = CipherManager.INSTANCE.randomAESKey();
byte[] sessionKey = CipherManager.INSTANCE.mixKey(clientKey, serverKey); byte[] sessionKey = CipherManager.INSTANCE.mixKey(clientKey, serverKey);
System.out.println("clientKey:" + Arrays.toString(clientKey)); //System.out.println("clientKey:" + Arrays.toString(clientKey));
System.out.println("serverKey:" + Arrays.toString(serverKey)); //System.out.println("serverKey:" + Arrays.toString(serverKey));
System.out.println("sessionKey:" + Arrays.toString(sessionKey)); System.out.println("sessionKey:" + Arrays.toString(sessionKey));


} }
Expand Down
40 changes: 40 additions & 0 deletions mpush-tools/src/main/java/com/shinemo/mpush/tools/IOUtils.java
Expand Up @@ -3,7 +3,12 @@
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;


/** /**
* Created by ohun on 2015/12/25. * Created by ohun on 2015/12/25.
Expand All @@ -20,4 +25,39 @@ public static void close(Closeable closeable) {
} }
} }
} }


public static byte[] compress(byte[] data) {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
DeflaterOutputStream zipOut = new DeflaterOutputStream(byteStream);
try {
zipOut.write(data);
zipOut.finish();
zipOut.close();
} catch (IOException e) {
LOGGER.error("compress ex", e);
return Constants.EMPTY_BYTES;
} finally {
close(zipOut);
}
return byteStream.toByteArray();
}

public static byte[] uncompress(byte[] data) {
InflaterInputStream in = new InflaterInputStream(new ByteArrayInputStream(data));
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[data.length * 2];
int length;
try {
while ((length = in.read(buffer)) != -1) {
out.write(buffer, 0, length);
}
} catch (IOException e) {
LOGGER.error("uncompress ex", e);
return Constants.EMPTY_BYTES;
} finally {
close(in);
}
return out.toByteArray();
}
} }
4 changes: 4 additions & 0 deletions mpush-tools/src/main/java/com/shinemo/mpush/tools/Jsons.java
Expand Up @@ -36,6 +36,10 @@ public static <T> T fromJson(String json, Class<T> clazz) {
return null; return null;
} }


public static <T> T fromJson(byte[] json, Class<T> clazz) {
return fromJson(new String(json, Constants.UTF_8), clazz);
}

public static <T> T fromJson(String json, Type type) { public static <T> T fromJson(String json, Type type) {
try { try {
return GSON.fromJson(json, type); return GSON.fromJson(json, type);
Expand Down

0 comments on commit 5e69daa

Please sign in to comment.