3 Star 14 Fork 5

John Yet / SMSS安全通讯框架

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
smss_socket_event.js 17.58 KB
一键复制 编辑 原始数据 按行查看 历史
learnhow 提交于 2019-12-20 16:40 . update
import {
MsgHeader,
MsgType,
SmsReq,
UserStatus,
UserInfoResp,
FileDownloadNotice,
FileDownloadReq,
FileDownloadRes,
FileUploadReq,
FileUploadResp,
HeartBeat,
LoginReq,
LoginResp,
ConnectReq,
ConnectResp
} from "./security_msg_pb";
const fs = require("fs");
const crypto = require("crypto");
const { dialog } = require("electron").remote;
const { Writable } = require("stream");
const path = require("path");
const net = require("net");
/**
* 连接事件处理
*
* @param {*} socket
* @param {*} userID
*/
function ConnectEvent(socket, userID) {
return new Promise((resolve, reject) => {
fs.open("./data/.shadow/server.pem", "r", (err, fd) => {
let connectReq = new ConnectReq();
connectReq.setTimestamp(new Date().getTime());
if (err) {
connectReq.setIsNeedKey(true);
} else {
connectReq.setIsNeedKey(false);
}
let connectReqBuffer = connectReq.serializeBinary();
let msgHeader = new MsgHeader();
msgHeader.setMsgSize(connectReqBuffer.length);
msgHeader.setMsgId(0);
msgHeader.setMsgType(MsgType.CONNECT_REQ);
msgHeader.setFrom(userID);
msgHeader.setTo(0); // 发送给服务器
const headerBuffer = msgHeader.serializeBinary();
let packageHeader = Buffer.alloc(8);
packageHeader.write("AB47");
packageHeader.writeInt32LE(headerBuffer.length, 4);
const packageBuffer = Buffer.concat([
packageHeader,
headerBuffer,
connectReqBuffer
]);
socket.write(packageBuffer, () => {
socket.once("data", data => {
let flag = data.toString("utf8", 0, 4);
if (flag !== "AB47") {
return;
}
let headerSize = data.readInt32LE(4);
// 消息头反向序列化
let msgHeader = MsgHeader.deserializeBinary(
data.subarray(8, headerSize + 8)
);
// 消息类型
let msgType = msgHeader.getMsgType();
// 消息大小
let msgSize = msgHeader.getMsgSize();
if (msgType !== MsgType.CONNECT_RESP) {
reject("ConnectEvent RES MsgType Error!");
} else {
let resp = ConnectResp.deserializeBinary(
data.subarray(8 + headerSize, msgSize + 8 + headerSize)
);
if (resp.getPubKey() !== "") {
fs.writeFile(
"./data/.shadow/server.pem",
resp.getPubKey(),
err => {
if (err) {
reject(err);
};
// 连接完成后进行登录
resolve(resp);
}
);
} else {
resolve(resp);
}
}
})
});
});
});
}
/**
* 登录事件处理流程
*
* @param {*} socket
* @param {*} userID
* @param {*} username
* @param {*} password
*/
function LoginEvent(socket, userID, username, password) {
return new Promise((resolve, reject) => {
let loginReq = new LoginReq();
loginReq.setUsername(username);
loginReq.setPassword(password);
fs.open("./data/.shadow/mine.pem", "r", (err, fd) => {
if (err) {
loginReq.setIsNeedKey(true);
} else {
loginReq.setIsNeedKey(false);
}
// 读取服务器通讯公钥
fs.readFile("./data/.shadow/server.pem", (err, data) => {
if (err) {
reject(err);
}
let cipherBuffer = crypto.publicEncrypt(
{
key: data.toString(), // 秘钥
padding: crypto.constants.RSA_PKCS1_PADDING // 填充方式
},
loginReq.serializeBinary()
);
// 构造消息头
let msgHeader = new MsgHeader();
msgHeader.setMsgSize(cipherBuffer.length);
msgHeader.setMsgId(0);
msgHeader.setMsgType(MsgType.CLIENT_LOGIN_REQ);
msgHeader.setFrom(userID);
msgHeader.setTo(0); // 发送给服务器
const headerBuffer = msgHeader.serializeBinary();
let packageHeader = Buffer.alloc(8);
packageHeader.write("AB47");
packageHeader.writeInt32LE(headerBuffer.length, 4);
const packageBuffer = Buffer.concat([
packageHeader,
headerBuffer,
cipherBuffer
]);
socket.write(packageBuffer, () => {
socket.once("data", data => {
let flag = data.toString("utf8", 0, 4);
if (flag !== "AB47") {
return;
}
let headerSize = data.readInt32LE(4);
// 消息头反向序列化
let msgHeader = MsgHeader.deserializeBinary(
data.subarray(8, headerSize + 8)
);
// 消息类型
let msgType = msgHeader.getMsgType();
// 消息大小
let msgSize = msgHeader.getMsgSize();
if (msgType !== MsgType.CLIENT_LOGIN_RESP) {
reject("LoginEvent RES MsgType Error!");
} else {
let res = LoginResp.deserializeBinary(
data.subarray(8 + headerSize, msgSize + 8 + headerSize)
)
resolve(res);
}
});
});
});
});
});
}
/**
* 用户在线状态流程
*
* @param {*} socket
* @param {*} userID
* @param {*} userToken
*/
function UserStatusEvent(socket, userID, userToken) {
return new Promise((resolve, reject) => {
let msgHeader = new MsgHeader();
msgHeader.setFrom(userID);
msgHeader.setTo(0);
msgHeader.setMsgSize(0);
msgHeader.setMsgType(MsgType.USER_STATUS_REQ);
msgHeader.setToken(userToken);
const headerBuffer = msgHeader.serializeBinary();
let packageHeader = Buffer.alloc(8);
packageHeader.write("AB47");
packageHeader.writeInt32LE(headerBuffer.length, 4);
const packageBuffer = Buffer.concat([packageHeader, headerBuffer]);
socket.write(packageBuffer, () => {
socket.once("data", data => {
let flag = data.toString("utf8", 0, 4);
if (flag !== "AB47") {
return;
}
let headerSize = data.readInt32LE(4);
// 消息头反向序列化
let msgHeader = MsgHeader.deserializeBinary(
data.subarray(8, headerSize + 8)
);
// 消息类型
let msgType = msgHeader.getMsgType();
// 消息大小
let msgSize = msgHeader.getMsgSize();
if (msgType !== MsgType.USER_STATUS_RESP) {
reject("UserStatusEvent RES MsgType Error!");
} else {
let res = UserStatus.deserializeBinary(
data.subarray(8 + headerSize, msgSize + 8 + headerSize)
);
resolve(res);
}
});
});
});
}
/**
* 文件上传流程
*
* @param {*} selfId
* @param {*} userToken
* @param {*} otherId
*/
function UploadEvent(selfId, userToken, otherId) {
dialog.showOpenDialog(require("electron").remote.getCurrentWindow(), {
title: "选择上传文件",
properties: ["openFile"]
}).then(result => {
return new Promise((resolve, reject) => {
if (result.canceled) {
reject(result);
}
resolve(result.filePaths[0]);
});
}).then(filePath => { // 上传文件的本地路径
return new Promise((resolve, reject) => {
const hash = crypto.createHash("MD5");
const input = fs.createReadStream(filePath);
input.pipe(hash).pipe(
new Writable({
write(chunk, encoding, callback) {
resolve({ md5: chunk, path: filePath });
}
})
);
})
}).then(obj => { // 文件属性
return new Promise((resolve, reject) => {
fs.stat(obj.path, (err, stats) => {
if (err) {
reject(err);
}
obj['stats'] = stats
resolve(obj);
});
});
}).then(obj => { // 用户私钥
return new Promise((resolve, reject) => {
fs.readFile("./data/.shadow/mine.pem", (err, mine) => {
if (err) {
reject(err);
}
obj['mine'] = mine;
resolve(obj);
});
});
}).then(obj => {
const privateKey = crypto.createPrivateKey(obj.mine);
const sign = crypto.createSign("SHA256");
sign.update(obj.md5.toString("hex"));
sign.end();
const signature = sign.sign(privateKey);
obj['signature'] = signature.toString("hex")
return new Promise((resolve, reject) => {
fs.readFile("./data/bootstrap.json", (err, data) => {
if (err) {
reject(err);
}
const bootstrap = JSON.parse(data.toString());
obj['host'] = bootstrap.socket.host;
obj['port'] = bootstrap.stream.port;
resolve(obj);
});
});
}).then(obj => { // 执行上传获取应答
let fileUploadReq = new FileUploadReq();
fileUploadReq.setFileName(path.basename(obj.path));
fileUploadReq.setFileSize(obj.stats.size);
fileUploadReq.setSignature(obj.signature);
let fileUploadReqBuff = fileUploadReq.serializeBinary();
let msgHeader = new MsgHeader();
msgHeader.setMsgSize(fileUploadReqBuff.length);
msgHeader.setMsgType(MsgType.FILE_UPLOAD_REQ);
msgHeader.setFrom(selfId);
msgHeader.setTo(otherId);
msgHeader.setToken(userToken);
const headerBuf = msgHeader.serializeBinary();
let pkgHeader = Buffer.alloc(8);
pkgHeader.write("AB47");
pkgHeader.writeInt32LE(headerBuf.length, 4);
let requestBuffer = Buffer.concat([
pkgHeader,
headerBuf,
fileUploadReqBuff
]); // 拼装请求数据buf
return new Promise((resolve, reject) => {
const client = net.createConnection(obj.port, obj.host, () => {
client.write(requestBuffer, () => {
client.once("data", data => {
let flag = data.toString("utf8", 0, 4);
if (flag !== "AB47") {
return;
}
let headerSize = data.readInt32LE(4);
// 消息头反向序列化
let msgHeader = MsgHeader.deserializeBinary(
data.subarray(8, headerSize + 8)
);
// 消息类型
let msgType = msgHeader.getMsgType();
// 消息大小
let msgSize = msgHeader.getMsgSize();
if (msgType !== MsgType.FILE_UPLOAD_RESP) {
reject("UploadEvent RES MsgType Error!");
} else {
let fileUploadResp = FileUploadResp.deserializeBinary(
data.subarray(8 + headerSize, msgSize + 8 + headerSize)
);
if (fileUploadResp.getRespType() !== FileUploadResp.FileUploadRespType.OK) {
reject("不允许上传");
};
obj['netSocket'] = client;
resolve(obj);
}
});
});
});
});
}).then(obj => {
const rs = fs.createReadStream(obj.path);
rs.pipe(obj.netSocket);
rs.on("end", () => {
obj.netSocket.once("end", () => {
console.log("上传连接关闭");
})
});
});
}
/**
* 文件下载流程
*
* @param {*} selfId
* @param {*} selfToken
* @param {*} header
* @param {*} fileDownloadNotice
*/
function DownloadEvent(selfId, selfToken, header, fileDownloadNotice) {
new Promise((resolve, reject) => {
fs.readFile("./data/bootstrap.json", (err, data) => {
if (err) {
reject(err);
}
const bootstrap = JSON.parse(data.toString());
resolve({ host: bootstrap.socket.host, port: bootstrap.stream.port });
});
}).then(obj => { // 下载
let fileDownloadReq = new FileDownloadReq();
fileDownloadReq.setFileName(fileDownloadNotice.getFileName());
const fileDownloadReqBuf = fileDownloadReq.serializeBinary();
let msgHeader = new MsgHeader();
msgHeader.setMsgSize(fileDownloadReqBuf.length);
msgHeader.setMsgType(MsgType.FILE_DOWNLOAD_REQ); // 下载请求类型
msgHeader.setFrom(selfId);
msgHeader.setTo(0);
msgHeader.setToken(selfToken);
const headerBuf = msgHeader.serializeBinary();
let pkgHeader = Buffer.alloc(8);
pkgHeader.write("AB47");
pkgHeader.writeInt32LE(headerBuf.length, 4);
let requestBuffer = Buffer.concat([
pkgHeader,
headerBuf,
fileDownloadReqBuf
]); // 拼装请求数据buf
return new Promise((resolve, reject) => {
const client = net.createConnection(obj.port, obj.host, () => {
client.write(requestBuffer, () => {
const ws = fs.createWriteStream(
"storage/" + fileDownloadNotice.getFileName()
);
let recvSize = 0;
client.once("data", data => {
recvSize += data.length;
if (recvSize === fileDownloadNotice.getFileSize()) {
resolve(client)
}
});
client.pipe(ws);
});
});
});
}).then((netSocket) => { // 生成签名
const input = fs.createReadStream(
"storage/" + fileDownloadNotice.getFileName()
);
const hash = crypto.createHash("MD5");
return new Promise((resolve, reject) => {
input.pipe(hash).pipe(new Writable({
write(chunk, encoding, callback) {
const md5 = chunk.toString("hex");
resolve({ md5: md5, netSocket: netSocket });
}
}));
});
}).then(obj => { // 签名验证
return new Promise((resolve, reject) => {
fs.readFile("./data/.shadow/pub/" + header.getFrom() + ".pem", (err, pem) => {
if (err) {
reject(err);
}
const publicKey = crypto.createPublicKey(pem);
const verify = crypto.createVerify("SHA256");
verify.update(obj.md5);
verify.end();
const verifyRes = verify.verify(publicKey, Buffer.from(fileDownloadNotice.getSignature(), "hex"));
if (!verifyRes) {
reject("下载文件签名验证错误");
} else {
resolve(obj);
}
});
});
}).then(obj => { // 发送应答
let fileDownloadRes = new FileDownloadRes();
fileDownloadRes.setFileName(fileDownloadNotice.getFileName());
fileDownloadRes.setResType(FileDownloadRes.FileDownloadResType.OK);
let msgHeader = new MsgHeader();
let fileDownloadResBuf = fileDownloadRes.serializeBinary();
msgHeader.setMsgSize(fileDownloadResBuf.length);
msgHeader.setMsgType(MsgType.FILE_DOWNLOAD_RES); // 下载请求类型
msgHeader.setFrom(selfId);
msgHeader.setTo(0);
msgHeader.setToken(selfToken);
const headerBuf = msgHeader.serializeBinary();
let pkgHeader = Buffer.alloc(8);
pkgHeader.write("AB47");
pkgHeader.writeInt32LE(headerBuf.length, 4);
let requestBuffer = Buffer.concat([
pkgHeader,
headerBuf,
fileDownloadResBuf
]);
obj.netSocket.write(requestBuffer, () => {
obj.netSocket.end();
console.log("下载完成");
});
});
}
export {
ConnectEvent, LoginEvent, UserStatusEvent, UploadEvent, DownloadEvent
}
C++
1
https://gitee.com/learnhow/encrypted_stream.git
git@gitee.com:learnhow/encrypted_stream.git
learnhow
encrypted_stream
SMSS安全通讯框架
master

搜索帮助