eufy-security-client 2.4.2 → 2.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/build/error.d.ts +57 -57
- package/build/error.js +155 -155
- package/build/eufysecurity.d.ts +162 -161
- package/build/eufysecurity.js +2104 -2091
- package/build/eufysecurity.js.map +1 -1
- package/build/http/api.d.ts +90 -90
- package/build/http/api.js +1407 -1407
- package/build/http/api.js.map +1 -1
- package/build/http/cache.d.ts +8 -8
- package/build/http/cache.js +33 -33
- package/build/http/const.d.ts +3 -3
- package/build/http/const.js +8545 -8545
- package/build/http/device.d.ts +360 -360
- package/build/http/device.js +2793 -2793
- package/build/http/device.js.map +1 -1
- package/build/http/error.d.ts +28 -28
- package/build/http/error.js +76 -76
- package/build/http/index.d.ts +10 -10
- package/build/http/index.js +29 -29
- package/build/http/interfaces.d.ts +202 -202
- package/build/http/interfaces.js +2 -2
- package/build/http/models.d.ts +561 -561
- package/build/http/models.js +2 -2
- package/build/http/parameter.d.ts +5 -5
- package/build/http/parameter.js +75 -75
- package/build/http/station.d.ts +292 -292
- package/build/http/station.js +6780 -6780
- package/build/http/station.js.map +1 -1
- package/build/http/types.d.ts +945 -945
- package/build/http/types.js +6070 -6070
- package/build/http/utils.d.ts +37 -37
- package/build/http/utils.js +370 -370
- package/build/index.d.ts +7 -7
- package/build/index.js +25 -25
- package/build/interfaces.d.ts +113 -113
- package/build/interfaces.js +2 -2
- package/build/mqtt/interface.d.ts +6 -6
- package/build/mqtt/interface.js +2 -2
- package/build/mqtt/model.d.ts +24 -24
- package/build/mqtt/model.js +2 -2
- package/build/mqtt/service.d.ts +30 -30
- package/build/mqtt/service.js +168 -168
- package/build/mqtt/service.js.map +1 -1
- package/build/p2p/ble.d.ts +47 -47
- package/build/p2p/ble.js +188 -188
- package/build/p2p/ble.js.map +1 -1
- package/build/p2p/error.d.ts +24 -24
- package/build/p2p/error.js +67 -67
- package/build/p2p/index.d.ts +8 -8
- package/build/p2p/index.js +27 -27
- package/build/p2p/interfaces.d.ts +162 -162
- package/build/p2p/interfaces.js +2 -2
- package/build/p2p/models.d.ts +146 -146
- package/build/p2p/models.js +2 -2
- package/build/p2p/session.d.ts +168 -168
- package/build/p2p/session.js +2087 -2087
- package/build/p2p/session.js.map +1 -1
- package/build/p2p/talkback.d.ts +10 -10
- package/build/p2p/talkback.js +22 -22
- package/build/p2p/types.d.ts +923 -923
- package/build/p2p/types.js +957 -957
- package/build/p2p/utils.d.ts +56 -56
- package/build/p2p/utils.js +653 -653
- package/build/push/client.d.ts +51 -51
- package/build/push/client.js +311 -311
- package/build/push/client.js.map +1 -1
- package/build/push/index.d.ts +5 -5
- package/build/push/index.js +24 -24
- package/build/push/interfaces.d.ts +19 -19
- package/build/push/interfaces.js +2 -2
- package/build/push/models.d.ts +292 -292
- package/build/push/models.js +30 -30
- package/build/push/parser.d.ts +28 -28
- package/build/push/parser.js +215 -215
- package/build/push/parser.js.map +1 -1
- package/build/push/service.d.ts +45 -45
- package/build/push/service.js +643 -643
- package/build/push/service.js.map +1 -1
- package/build/push/types.d.ts +176 -176
- package/build/push/types.js +192 -192
- package/build/push/utils.d.ts +7 -7
- package/build/push/utils.js +102 -102
- package/build/utils.d.ts +16 -13
- package/build/utils.js +207 -191
- package/build/utils.js.map +1 -1
- package/package.json +10 -10
package/build/p2p/utils.js
CHANGED
|
@@ -1,654 +1,654 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.getLockV12P2PCommand = exports.getLockP2PCommand = exports.getSmartSafeP2PCommand = exports.decodeSmartSafeData = exports.decodeP2PCloudIPs = exports.buildTalkbackAudioFrameHeader = exports.getLockV12Key = exports.getAdvancedLockKey = exports.eufyKDF = exports.decryptPayloadData = exports.encryptPayloadData = exports.isP2PQueueMessage = exports.buildVoidCommandPayload = exports.checkT8420 = exports.getVideoCodec = exports.generateAdvancedLockAESKey = exports.eslTimestamp = exports.decodeBase64 = exports.decodeLockPayload = exports.getLockVectorBytes = exports.encodeLockPayload = exports.generateLockSequence = exports.getCurrentTimeInSeconds = exports.generateBasicLockAESKey = exports.encryptLockAESData = exports.decryptLockAESData = exports.isIFrame = exports.findStartCode = exports.decryptAESData = exports.getNewRSAPrivateKey = exports.getRSAPrivateKey = exports.sortP2PMessageParts = exports.buildCommandWithStringTypePayload = exports.buildCommandHeader = exports.hasHeader = exports.sendMessage = exports.buildIntStringCommandPayload = exports.buildStringTypeCommandPayload = exports.buildIntCommandPayload = exports.buildCheckCamPayload2 = exports.buildCheckCamPayload = exports.buildLookupWithKeyPayload3 = exports.buildLookupWithKeyPayload2 = exports.buildLookupWithKeyPayload = exports.getLocalIpAddress = exports.isPrivateIp = exports.MAGIC_WORD = void 0;
|
|
30
|
-
const node_rsa_1 = __importDefault(require("node-rsa"));
|
|
31
|
-
const CryptoJS = __importStar(require("crypto-js"));
|
|
32
|
-
const crypto_1 = require("crypto");
|
|
33
|
-
const os = __importStar(require("os"));
|
|
34
|
-
const types_1 = require("./types");
|
|
35
|
-
const device_1 = require("../http/device");
|
|
36
|
-
const ble_1 = require("./ble");
|
|
37
|
-
exports.MAGIC_WORD = "XZYH";
|
|
38
|
-
const isPrivateIp = (ip) => /^(::f{4}:)?10\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
|
39
|
-
/^(::f{4}:)?192\.168\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
|
40
|
-
/^(::f{4}:)?172\.(1[6-9]|2\d|30|31)\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
|
41
|
-
/^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
|
42
|
-
/^(::f{4}:)?169\.254\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
|
43
|
-
/^f[cd][0-9a-f]{2}:/i.test(ip) ||
|
|
44
|
-
/^fe80:/i.test(ip) ||
|
|
45
|
-
/^::1$/.test(ip) ||
|
|
46
|
-
/^::$/.test(ip);
|
|
47
|
-
exports.isPrivateIp = isPrivateIp;
|
|
48
|
-
const stringWithLength = (input, chunkLength = 128) => {
|
|
49
|
-
const stringAsBuffer = Buffer.from(input);
|
|
50
|
-
const bufferSize = stringAsBuffer.byteLength < chunkLength ? chunkLength : Math.ceil(stringAsBuffer.byteLength / chunkLength) * chunkLength;
|
|
51
|
-
const result = Buffer.alloc(bufferSize);
|
|
52
|
-
stringAsBuffer.copy(result);
|
|
53
|
-
return result;
|
|
54
|
-
};
|
|
55
|
-
const getLocalIpAddress = (init = "") => {
|
|
56
|
-
const ifaces = os.networkInterfaces();
|
|
57
|
-
let localAddress = init;
|
|
58
|
-
for (const name in ifaces) {
|
|
59
|
-
const iface = ifaces[name].filter(function (details) {
|
|
60
|
-
return details.family === "IPv4" && details.internal === false;
|
|
61
|
-
});
|
|
62
|
-
if (iface.length > 0) {
|
|
63
|
-
localAddress = iface[0].address;
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return localAddress;
|
|
68
|
-
};
|
|
69
|
-
exports.getLocalIpAddress = getLocalIpAddress;
|
|
70
|
-
const p2pDidToBuffer = (p2pDid) => {
|
|
71
|
-
const p2pArray = p2pDid.split("-");
|
|
72
|
-
const buf1 = stringWithLength(p2pArray[0], 8);
|
|
73
|
-
const buf2 = Buffer.allocUnsafe(4);
|
|
74
|
-
buf2.writeUInt32BE(Number.parseInt(p2pArray[1]), 0);
|
|
75
|
-
const buf3 = stringWithLength(p2pArray[2], 8);
|
|
76
|
-
return Buffer.concat([buf1, buf2, buf3], 20);
|
|
77
|
-
};
|
|
78
|
-
const buildLookupWithKeyPayload = (socket, p2pDid, dskKey) => {
|
|
79
|
-
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
|
|
80
|
-
const addressInfo = socket.address();
|
|
81
|
-
const port = addressInfo.port;
|
|
82
|
-
const portAsBuffer = Buffer.allocUnsafe(2);
|
|
83
|
-
portAsBuffer.writeUInt16LE(port, 0);
|
|
84
|
-
//const ip = socket.address().address;
|
|
85
|
-
const ip = (0, exports.getLocalIpAddress)(addressInfo.address);
|
|
86
|
-
const temp_buff = [];
|
|
87
|
-
ip.split(".").reverse().forEach(element => {
|
|
88
|
-
temp_buff.push(Number.parseInt(element));
|
|
89
|
-
});
|
|
90
|
-
const ipAsBuffer = Buffer.from(temp_buff);
|
|
91
|
-
const splitter = Buffer.from([0x00, 0x02]);
|
|
92
|
-
const magic = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00]);
|
|
93
|
-
const dskKeyAsBuffer = Buffer.from(dskKey);
|
|
94
|
-
const fourEmpty = Buffer.from([0x00, 0x00, 0x00, 0x00]);
|
|
95
|
-
return Buffer.concat([p2pDidBuffer, splitter, portAsBuffer, ipAsBuffer, magic, dskKeyAsBuffer, fourEmpty]);
|
|
96
|
-
};
|
|
97
|
-
exports.buildLookupWithKeyPayload = buildLookupWithKeyPayload;
|
|
98
|
-
const buildLookupWithKeyPayload2 = (p2pDid, dskKey) => {
|
|
99
|
-
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
|
|
100
|
-
const dskKeyAsBuffer = Buffer.from(dskKey);
|
|
101
|
-
const fourEmpty = Buffer.from([0x00, 0x00, 0x00, 0x00]);
|
|
102
|
-
return Buffer.concat([p2pDidBuffer, dskKeyAsBuffer, fourEmpty]);
|
|
103
|
-
};
|
|
104
|
-
exports.buildLookupWithKeyPayload2 = buildLookupWithKeyPayload2;
|
|
105
|
-
const buildLookupWithKeyPayload3 = (p2pDid, address, data) => {
|
|
106
|
-
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
|
|
107
|
-
const portAsBuffer = Buffer.allocUnsafe(2);
|
|
108
|
-
portAsBuffer.writeUInt16LE(address.port, 0);
|
|
109
|
-
const temp_buff = [];
|
|
110
|
-
address.host.split(".").reverse().forEach(element => {
|
|
111
|
-
temp_buff.push(Number.parseInt(element));
|
|
112
|
-
});
|
|
113
|
-
const ipAsBuffer = Buffer.from(temp_buff);
|
|
114
|
-
const splitter = Buffer.from([0x00, 0x02]);
|
|
115
|
-
const eightEmpty = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
|
116
|
-
return Buffer.concat([p2pDidBuffer, splitter, portAsBuffer, ipAsBuffer, eightEmpty, data]);
|
|
117
|
-
};
|
|
118
|
-
exports.buildLookupWithKeyPayload3 = buildLookupWithKeyPayload3;
|
|
119
|
-
const buildCheckCamPayload = (p2pDid) => {
|
|
120
|
-
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
|
|
121
|
-
const magic = Buffer.from([0x00, 0x00, 0x00]);
|
|
122
|
-
return Buffer.concat([p2pDidBuffer, magic]);
|
|
123
|
-
};
|
|
124
|
-
exports.buildCheckCamPayload = buildCheckCamPayload;
|
|
125
|
-
const buildCheckCamPayload2 = (p2pDid, data) => {
|
|
126
|
-
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
|
|
127
|
-
const magic = Buffer.from([0x00, 0x00, 0x00, 0x00]);
|
|
128
|
-
return Buffer.concat([data, p2pDidBuffer, magic]);
|
|
129
|
-
};
|
|
130
|
-
exports.buildCheckCamPayload2 = buildCheckCamPayload2;
|
|
131
|
-
const buildIntCommandPayload = (value, strValue = "", channel = 255) => {
|
|
132
|
-
const emptyBuffer = Buffer.from([0x00, 0x00]);
|
|
133
|
-
const magicBuffer = Buffer.from([0x01, 0x00]);
|
|
134
|
-
const channelBuffer = Buffer.from([channel, 0x00]);
|
|
135
|
-
const valueBuffer = Buffer.allocUnsafe(4);
|
|
136
|
-
valueBuffer.writeUInt32LE(value, 0);
|
|
137
|
-
const headerBuffer = Buffer.allocUnsafe(2);
|
|
138
|
-
const strValueBuffer = strValue.length === 0 ? Buffer.from([]) : stringWithLength(strValue);
|
|
139
|
-
headerBuffer.writeUInt16LE(valueBuffer.length + strValueBuffer.length, 0);
|
|
140
|
-
return Buffer.concat([
|
|
141
|
-
headerBuffer,
|
|
142
|
-
emptyBuffer,
|
|
143
|
-
magicBuffer,
|
|
144
|
-
channelBuffer,
|
|
145
|
-
emptyBuffer,
|
|
146
|
-
valueBuffer,
|
|
147
|
-
strValueBuffer
|
|
148
|
-
]);
|
|
149
|
-
};
|
|
150
|
-
exports.buildIntCommandPayload = buildIntCommandPayload;
|
|
151
|
-
const buildStringTypeCommandPayload = (strValue, strValueSub, channel = 255) => {
|
|
152
|
-
const emptyBuffer = Buffer.from([0x00, 0x00]);
|
|
153
|
-
const magicBuffer = Buffer.from([0x01, 0x00]);
|
|
154
|
-
const channelBuffer = Buffer.from([channel, 0x00]);
|
|
155
|
-
const someBuffer = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00]);
|
|
156
|
-
const strValueBuffer = stringWithLength(strValue);
|
|
157
|
-
const strValueSubBuffer = stringWithLength(strValueSub);
|
|
158
|
-
const headerBuffer = Buffer.allocUnsafe(2);
|
|
159
|
-
headerBuffer.writeUInt16LE(someBuffer.length + strValueBuffer.length + strValueSubBuffer.length, 0);
|
|
160
|
-
return Buffer.concat([
|
|
161
|
-
headerBuffer,
|
|
162
|
-
emptyBuffer,
|
|
163
|
-
magicBuffer,
|
|
164
|
-
channelBuffer,
|
|
165
|
-
emptyBuffer,
|
|
166
|
-
someBuffer,
|
|
167
|
-
strValueBuffer,
|
|
168
|
-
strValueSubBuffer
|
|
169
|
-
]);
|
|
170
|
-
};
|
|
171
|
-
exports.buildStringTypeCommandPayload = buildStringTypeCommandPayload;
|
|
172
|
-
const buildIntStringCommandPayload = (value, valueSub = 0, strValue = "", strValueSub = "", channel = 0) => {
|
|
173
|
-
const emptyBuffer = Buffer.from([0x00, 0x00]);
|
|
174
|
-
const magicBuffer = Buffer.from([0x01, 0x00]);
|
|
175
|
-
const channelBuffer = Buffer.from([channel, 0x00]);
|
|
176
|
-
const someintBuffer = Buffer.allocUnsafe(4);
|
|
177
|
-
someintBuffer.writeUInt32LE(valueSub, 0);
|
|
178
|
-
const valueBuffer = Buffer.allocUnsafe(4);
|
|
179
|
-
valueBuffer.writeUInt32LE(value, 0);
|
|
180
|
-
const strValueBuffer = strValue.length === 0 ? Buffer.from([]) : stringWithLength(strValue);
|
|
181
|
-
const strValueSubBuffer = strValueSub.length === 0 ? Buffer.from([]) : stringWithLength(strValueSub);
|
|
182
|
-
const headerBuffer = Buffer.allocUnsafe(2);
|
|
183
|
-
headerBuffer.writeUInt16LE(someintBuffer.length + valueBuffer.length + strValueBuffer.length + strValueSubBuffer.length, 0);
|
|
184
|
-
return Buffer.concat([
|
|
185
|
-
headerBuffer,
|
|
186
|
-
emptyBuffer,
|
|
187
|
-
magicBuffer,
|
|
188
|
-
channelBuffer,
|
|
189
|
-
emptyBuffer,
|
|
190
|
-
someintBuffer,
|
|
191
|
-
valueBuffer,
|
|
192
|
-
strValueBuffer,
|
|
193
|
-
strValueSubBuffer
|
|
194
|
-
]);
|
|
195
|
-
};
|
|
196
|
-
exports.buildIntStringCommandPayload = buildIntStringCommandPayload;
|
|
197
|
-
const sendMessage = async (socket, address, msgID, payload) => {
|
|
198
|
-
if (!payload)
|
|
199
|
-
payload = Buffer.from([]);
|
|
200
|
-
const payloadLen = Buffer.allocUnsafe(2);
|
|
201
|
-
payloadLen.writeUInt16BE(payload.length, 0);
|
|
202
|
-
const message = Buffer.concat([msgID, payloadLen, payload], 4 + payload.length);
|
|
203
|
-
return new Promise((resolve, reject) => {
|
|
204
|
-
socket.send(message, address.port, address.host, (err, bytes) => {
|
|
205
|
-
return err ? reject(err) : resolve(bytes);
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
};
|
|
209
|
-
exports.sendMessage = sendMessage;
|
|
210
|
-
const hasHeader = (msg, searchedType) => {
|
|
211
|
-
const header = Buffer.allocUnsafe(2);
|
|
212
|
-
msg.copy(header, 0, 0, 2);
|
|
213
|
-
return Buffer.compare(header, searchedType) === 0;
|
|
214
|
-
};
|
|
215
|
-
exports.hasHeader = hasHeader;
|
|
216
|
-
const buildCommandHeader = (seqNumber, commandType, p2pDataTypeHeader = null) => {
|
|
217
|
-
let dataTypeBuffer = types_1.P2PDataTypeHeader.DATA;
|
|
218
|
-
if (p2pDataTypeHeader !== null &&
|
|
219
|
-
(Buffer.compare(p2pDataTypeHeader, types_1.P2PDataTypeHeader.DATA) === 0 ||
|
|
220
|
-
Buffer.compare(p2pDataTypeHeader, types_1.P2PDataTypeHeader.BINARY) === 0 ||
|
|
221
|
-
Buffer.compare(p2pDataTypeHeader, types_1.P2PDataTypeHeader.CONTROL) === 0 ||
|
|
222
|
-
Buffer.compare(p2pDataTypeHeader, types_1.P2PDataTypeHeader.VIDEO) === 0)) {
|
|
223
|
-
dataTypeBuffer = p2pDataTypeHeader;
|
|
224
|
-
}
|
|
225
|
-
const seqAsBuffer = Buffer.allocUnsafe(2);
|
|
226
|
-
seqAsBuffer.writeUInt16BE(seqNumber, 0);
|
|
227
|
-
const magicString = Buffer.from(exports.MAGIC_WORD);
|
|
228
|
-
const commandTypeBuffer = Buffer.allocUnsafe(2);
|
|
229
|
-
commandTypeBuffer.writeUInt16LE(commandType, 0);
|
|
230
|
-
return Buffer.concat([dataTypeBuffer, seqAsBuffer, magicString, commandTypeBuffer]);
|
|
231
|
-
};
|
|
232
|
-
exports.buildCommandHeader = buildCommandHeader;
|
|
233
|
-
const buildCommandWithStringTypePayload = (value, channel = 0) => {
|
|
234
|
-
// type = 6
|
|
235
|
-
//setCommandWithString()
|
|
236
|
-
const headerBuffer = Buffer.allocUnsafe(2);
|
|
237
|
-
const emptyBuffer = Buffer.from([0x00, 0x00]);
|
|
238
|
-
const magicBuffer = Buffer.from([0x01, 0x00]);
|
|
239
|
-
const channelBuffer = Buffer.from([channel, 0x00]);
|
|
240
|
-
const jsonBuffer = Buffer.from(value);
|
|
241
|
-
headerBuffer.writeUInt16LE(jsonBuffer.length, 0);
|
|
242
|
-
return Buffer.concat([
|
|
243
|
-
headerBuffer,
|
|
244
|
-
emptyBuffer,
|
|
245
|
-
magicBuffer,
|
|
246
|
-
channelBuffer,
|
|
247
|
-
emptyBuffer,
|
|
248
|
-
jsonBuffer,
|
|
249
|
-
]);
|
|
250
|
-
};
|
|
251
|
-
exports.buildCommandWithStringTypePayload = buildCommandWithStringTypePayload;
|
|
252
|
-
const sortP2PMessageParts = (messages) => {
|
|
253
|
-
let completeMessage = Buffer.from([]);
|
|
254
|
-
Object.keys(messages).map(Number)
|
|
255
|
-
.sort((a, b) => a - b) // assure the seqNumbers are in correct order
|
|
256
|
-
.forEach((key) => {
|
|
257
|
-
completeMessage = Buffer.concat([completeMessage, messages[key]]);
|
|
258
|
-
});
|
|
259
|
-
return completeMessage;
|
|
260
|
-
};
|
|
261
|
-
exports.sortP2PMessageParts = sortP2PMessageParts;
|
|
262
|
-
const getRSAPrivateKey = (pem) => {
|
|
263
|
-
const key = new node_rsa_1.default();
|
|
264
|
-
if (pem.startsWith("-----BEGIN RSA PRIVATE KEY-----")) {
|
|
265
|
-
pem = pem.replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("-----END RSA PRIVATE KEY-----", "");
|
|
266
|
-
}
|
|
267
|
-
key.importKey(pem, "pkcs8");
|
|
268
|
-
key.setOptions({
|
|
269
|
-
encryptionScheme: "pkcs1"
|
|
270
|
-
});
|
|
271
|
-
return key;
|
|
272
|
-
};
|
|
273
|
-
exports.getRSAPrivateKey = getRSAPrivateKey;
|
|
274
|
-
const getNewRSAPrivateKey = () => {
|
|
275
|
-
const key = new node_rsa_1.default({ b: 1024 });
|
|
276
|
-
key.setOptions({
|
|
277
|
-
encryptionScheme: "pkcs1"
|
|
278
|
-
});
|
|
279
|
-
return key;
|
|
280
|
-
};
|
|
281
|
-
exports.getNewRSAPrivateKey = getNewRSAPrivateKey;
|
|
282
|
-
const decryptAESData = (hexkey, data) => {
|
|
283
|
-
const key = CryptoJS.enc.Hex.parse(hexkey);
|
|
284
|
-
const cipherParams = CryptoJS.lib.CipherParams.create({
|
|
285
|
-
ciphertext: CryptoJS.enc.Hex.parse(data.toString("hex"))
|
|
286
|
-
});
|
|
287
|
-
const decrypted = CryptoJS.AES.decrypt(cipherParams, key, {
|
|
288
|
-
mode: CryptoJS.mode.ECB,
|
|
289
|
-
padding: CryptoJS.pad.NoPadding
|
|
290
|
-
});
|
|
291
|
-
return Buffer.from(CryptoJS.enc.Hex.stringify(decrypted), "hex");
|
|
292
|
-
};
|
|
293
|
-
exports.decryptAESData = decryptAESData;
|
|
294
|
-
const findStartCode = (data) => {
|
|
295
|
-
if (data !== undefined && data.length > 0) {
|
|
296
|
-
if (data.length >= 4) {
|
|
297
|
-
const startcode = [...data.slice(0, 4)];
|
|
298
|
-
if ((startcode[0] === 0 && startcode[1] === 0 && startcode[2] === 1) || (startcode[0] === 0 && startcode[1] === 0 && startcode[2] === 0 && startcode[3] === 1))
|
|
299
|
-
return true;
|
|
300
|
-
}
|
|
301
|
-
else if (data.length === 3) {
|
|
302
|
-
const startcode = [...data.slice(0, 3)];
|
|
303
|
-
if ((startcode[0] === 0 && startcode[1] === 0 && startcode[2] === 1))
|
|
304
|
-
return true;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
return false;
|
|
308
|
-
};
|
|
309
|
-
exports.findStartCode = findStartCode;
|
|
310
|
-
const isIFrame = (data) => {
|
|
311
|
-
const validValues = [64, 66, 68, 78, 101, 103];
|
|
312
|
-
if (data !== undefined && data.length > 0) {
|
|
313
|
-
if (data.length >= 5) {
|
|
314
|
-
const startcode = [...data.slice(0, 5)];
|
|
315
|
-
if (validValues.includes(startcode[3]) || validValues.includes(startcode[4]))
|
|
316
|
-
return true;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
return false;
|
|
320
|
-
};
|
|
321
|
-
exports.isIFrame = isIFrame;
|
|
322
|
-
const decryptLockAESData = (key, iv, data) => {
|
|
323
|
-
const ekey = CryptoJS.enc.Hex.parse(key);
|
|
324
|
-
const eiv = CryptoJS.enc.Hex.parse(iv);
|
|
325
|
-
const cipherParams = CryptoJS.lib.CipherParams.create({
|
|
326
|
-
ciphertext: CryptoJS.enc.Hex.parse(data.toString("hex"))
|
|
327
|
-
});
|
|
328
|
-
const decrypted = CryptoJS.AES.decrypt(cipherParams, ekey, {
|
|
329
|
-
iv: eiv,
|
|
330
|
-
mode: CryptoJS.mode.CBC,
|
|
331
|
-
padding: CryptoJS.pad.Pkcs7
|
|
332
|
-
});
|
|
333
|
-
return Buffer.from(CryptoJS.enc.Hex.stringify(decrypted), "hex");
|
|
334
|
-
};
|
|
335
|
-
exports.decryptLockAESData = decryptLockAESData;
|
|
336
|
-
const encryptLockAESData = (key, iv, data) => {
|
|
337
|
-
const ekey = CryptoJS.enc.Hex.parse(key);
|
|
338
|
-
const eiv = CryptoJS.enc.Hex.parse(iv);
|
|
339
|
-
const encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Hex.parse(data.toString("hex")), ekey, {
|
|
340
|
-
iv: eiv,
|
|
341
|
-
mode: CryptoJS.mode.CBC,
|
|
342
|
-
padding: CryptoJS.pad.Pkcs7
|
|
343
|
-
});
|
|
344
|
-
return Buffer.from(CryptoJS.enc.Hex.stringify(encrypted.ciphertext), "hex");
|
|
345
|
-
};
|
|
346
|
-
exports.encryptLockAESData = encryptLockAESData;
|
|
347
|
-
const generateBasicLockAESKey = (adminID, stationSN) => {
|
|
348
|
-
const encoder = new TextEncoder();
|
|
349
|
-
const encOwnerID = encoder.encode(adminID);
|
|
350
|
-
const encStationSerial = encoder.encode(stationSN);
|
|
351
|
-
const array = [104, -83, -72, 38, -107, 99, -110, 17, -95, -121, 54, 57, -46, -98, -111, 89];
|
|
352
|
-
for (let i = 0; i < 16; i++) {
|
|
353
|
-
array[i] = (array[i] + encStationSerial[((encStationSerial[i] * 3) + 5) % 16] + encOwnerID[((encOwnerID[i] * 3) + 5) % 40]);
|
|
354
|
-
}
|
|
355
|
-
return Buffer.from(array).toString("hex");
|
|
356
|
-
};
|
|
357
|
-
exports.generateBasicLockAESKey = generateBasicLockAESKey;
|
|
358
|
-
const getCurrentTimeInSeconds = function () {
|
|
359
|
-
return Math.trunc(new Date().getTime() / 1000);
|
|
360
|
-
};
|
|
361
|
-
exports.getCurrentTimeInSeconds = getCurrentTimeInSeconds;
|
|
362
|
-
const generateLockSequence = (deviceType) => {
|
|
363
|
-
if (device_1.Device.isLockWifi(deviceType) || device_1.Device.isLockWifiNoFinger(deviceType))
|
|
364
|
-
return Math.trunc(Math.random() * 1000);
|
|
365
|
-
return (0, exports.getCurrentTimeInSeconds)();
|
|
366
|
-
};
|
|
367
|
-
exports.generateLockSequence = generateLockSequence;
|
|
368
|
-
const encodeLockPayload = (data) => {
|
|
369
|
-
const encoder = new TextEncoder();
|
|
370
|
-
const encData = encoder.encode(data);
|
|
371
|
-
const length = encData.length;
|
|
372
|
-
const old_buffer = Buffer.from(encData);
|
|
373
|
-
if (length % 16 == 0) {
|
|
374
|
-
return old_buffer;
|
|
375
|
-
}
|
|
376
|
-
const new_length = (Math.trunc(length / 16) + 1) * 16;
|
|
377
|
-
const new_buffer = Buffer.alloc(new_length);
|
|
378
|
-
old_buffer.copy(new_buffer, 0);
|
|
379
|
-
return new_buffer;
|
|
380
|
-
};
|
|
381
|
-
exports.encodeLockPayload = encodeLockPayload;
|
|
382
|
-
const getLockVectorBytes = (data) => {
|
|
383
|
-
const encoder = new TextEncoder();
|
|
384
|
-
const encData = encoder.encode(data);
|
|
385
|
-
const old_buffer = Buffer.from(encData);
|
|
386
|
-
if (encData.length >= 16)
|
|
387
|
-
return old_buffer.toString("hex");
|
|
388
|
-
const new_buffer = Buffer.alloc(16);
|
|
389
|
-
old_buffer.copy(new_buffer, 0);
|
|
390
|
-
return new_buffer.toString("hex");
|
|
391
|
-
};
|
|
392
|
-
exports.getLockVectorBytes = getLockVectorBytes;
|
|
393
|
-
const decodeLockPayload = (data) => {
|
|
394
|
-
const decoder = new TextDecoder();
|
|
395
|
-
return decoder.decode(data);
|
|
396
|
-
};
|
|
397
|
-
exports.decodeLockPayload = decodeLockPayload;
|
|
398
|
-
const decodeBase64 = (data) => {
|
|
399
|
-
return Buffer.from(data, "base64");
|
|
400
|
-
};
|
|
401
|
-
exports.decodeBase64 = decodeBase64;
|
|
402
|
-
const eslTimestamp = function (timestamp_in_sec = new Date().getTime() / 1000) {
|
|
403
|
-
const array = [];
|
|
404
|
-
for (let pos = 0; pos < 4; pos++) {
|
|
405
|
-
array[pos] = ((timestamp_in_sec >> (pos * 8)) & 255);
|
|
406
|
-
}
|
|
407
|
-
return array;
|
|
408
|
-
};
|
|
409
|
-
exports.eslTimestamp = eslTimestamp;
|
|
410
|
-
const generateAdvancedLockAESKey = () => {
|
|
411
|
-
const randomBytesArray = [...(0, crypto_1.randomBytes)(16)];
|
|
412
|
-
let result = "";
|
|
413
|
-
for (let pos = 0; pos < randomBytesArray.length; pos++) {
|
|
414
|
-
result += "0123456789ABCDEF".charAt((randomBytesArray[pos] >> 4) & 15);
|
|
415
|
-
result += "0123456789ABCDEF".charAt(randomBytesArray[pos] & 15);
|
|
416
|
-
}
|
|
417
|
-
return result;
|
|
418
|
-
};
|
|
419
|
-
exports.generateAdvancedLockAESKey = generateAdvancedLockAESKey;
|
|
420
|
-
const getVideoCodec = (data) => {
|
|
421
|
-
if (data !== undefined && data.length > 0) {
|
|
422
|
-
if (data.length >= 5) {
|
|
423
|
-
const h265Values = [38, 64, 66, 68, 78];
|
|
424
|
-
const startcode = [...data.slice(0, 5)];
|
|
425
|
-
if (h265Values.includes(startcode[3]) || h265Values.includes(startcode[4])) {
|
|
426
|
-
return types_1.VideoCodec.H265;
|
|
427
|
-
}
|
|
428
|
-
else if (startcode[3] === 103 || startcode[4] === 103) {
|
|
429
|
-
return types_1.VideoCodec.H264;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
return types_1.VideoCodec.H264;
|
|
433
|
-
}
|
|
434
|
-
return types_1.VideoCodec.UNKNOWN; // Maybe return h264 as Eufy does?
|
|
435
|
-
};
|
|
436
|
-
exports.getVideoCodec = getVideoCodec;
|
|
437
|
-
const checkT8420 = (serialNumber) => {
|
|
438
|
-
if (!(serialNumber !== undefined && serialNumber !== null && serialNumber.length > 0 && serialNumber.startsWith("T8420")) || serialNumber.length <= 7 || serialNumber[6] != "6") {
|
|
439
|
-
return false;
|
|
440
|
-
}
|
|
441
|
-
return true;
|
|
442
|
-
};
|
|
443
|
-
exports.checkT8420 = checkT8420;
|
|
444
|
-
const buildVoidCommandPayload = (channel = 255) => {
|
|
445
|
-
const headerBuffer = Buffer.from([0x00, 0x00]);
|
|
446
|
-
const emptyBuffer = Buffer.from([0x00, 0x00]);
|
|
447
|
-
const magicBuffer = Buffer.from([0x01, 0x00]);
|
|
448
|
-
const channelBuffer = Buffer.from([channel, 0x00]);
|
|
449
|
-
return Buffer.concat([
|
|
450
|
-
headerBuffer,
|
|
451
|
-
emptyBuffer,
|
|
452
|
-
magicBuffer,
|
|
453
|
-
channelBuffer,
|
|
454
|
-
emptyBuffer
|
|
455
|
-
]);
|
|
456
|
-
};
|
|
457
|
-
exports.buildVoidCommandPayload = buildVoidCommandPayload;
|
|
458
|
-
function isP2PQueueMessage(type) {
|
|
459
|
-
return type.payload !== undefined;
|
|
460
|
-
}
|
|
461
|
-
exports.isP2PQueueMessage = isP2PQueueMessage;
|
|
462
|
-
const encryptPayloadData = (data, key, iv) => {
|
|
463
|
-
const cipher = (0, crypto_1.createCipheriv)("aes-128-cbc", key, iv);
|
|
464
|
-
return Buffer.concat([
|
|
465
|
-
cipher.update(data),
|
|
466
|
-
cipher.final()
|
|
467
|
-
]);
|
|
468
|
-
};
|
|
469
|
-
exports.encryptPayloadData = encryptPayloadData;
|
|
470
|
-
const decryptPayloadData = (data, key, iv) => {
|
|
471
|
-
const cipher = (0, crypto_1.createDecipheriv)("aes-128-cbc", key, iv);
|
|
472
|
-
return Buffer.concat([
|
|
473
|
-
cipher.update(data),
|
|
474
|
-
cipher.final()
|
|
475
|
-
]);
|
|
476
|
-
};
|
|
477
|
-
exports.decryptPayloadData = decryptPayloadData;
|
|
478
|
-
const eufyKDF = (key) => {
|
|
479
|
-
const hash_length = 32;
|
|
480
|
-
const digest_length = 48;
|
|
481
|
-
const staticBuffer = Buffer.from("ECIES");
|
|
482
|
-
const steps = Math.ceil(digest_length / hash_length);
|
|
483
|
-
const buffer = Buffer.alloc(hash_length * steps);
|
|
484
|
-
let tmpBuffer = staticBuffer;
|
|
485
|
-
for (let step = 0; step < steps; ++step) {
|
|
486
|
-
tmpBuffer = (0, crypto_1.createHmac)("sha256", key).update(tmpBuffer).digest();
|
|
487
|
-
const digest = (0, crypto_1.createHmac)("sha256", key).update(Buffer.concat([tmpBuffer, staticBuffer])).digest();
|
|
488
|
-
digest.copy(buffer, hash_length * step);
|
|
489
|
-
}
|
|
490
|
-
return buffer.slice(0, digest_length);
|
|
491
|
-
};
|
|
492
|
-
exports.eufyKDF = eufyKDF;
|
|
493
|
-
const getAdvancedLockKey = (key, publicKey) => {
|
|
494
|
-
const ecdh = (0, crypto_1.createECDH)("prime256v1");
|
|
495
|
-
ecdh.generateKeys();
|
|
496
|
-
const secret = ecdh.computeSecret(Buffer.concat([Buffer.from("04", "hex"), Buffer.from(publicKey, "hex")]));
|
|
497
|
-
const randomValue = (0, crypto_1.randomBytes)(16);
|
|
498
|
-
const derivedKey = (0, exports.eufyKDF)(secret);
|
|
499
|
-
const encryptedData = (0, exports.encryptPayloadData)(key, derivedKey.slice(0, 16), randomValue);
|
|
500
|
-
const hmac = (0, crypto_1.createHmac)("sha256", derivedKey.slice(16));
|
|
501
|
-
hmac.update(randomValue);
|
|
502
|
-
hmac.update(encryptedData);
|
|
503
|
-
const hmacDigest = hmac.digest();
|
|
504
|
-
return Buffer.concat([Buffer.from(ecdh.getPublicKey("hex", "compressed"), "hex"), randomValue, encryptedData, hmacDigest]).toString("hex");
|
|
505
|
-
};
|
|
506
|
-
exports.getAdvancedLockKey = getAdvancedLockKey;
|
|
507
|
-
const getLockV12Key = (key, publicKey) => {
|
|
508
|
-
const ecdh = (0, crypto_1.createECDH)("prime256v1");
|
|
509
|
-
ecdh.generateKeys();
|
|
510
|
-
const secret = ecdh.computeSecret(Buffer.concat([Buffer.from("04", "hex"), Buffer.from(publicKey, "hex")]));
|
|
511
|
-
const randomValue = (0, crypto_1.randomBytes)(16);
|
|
512
|
-
const derivedKey = (0, exports.eufyKDF)(secret);
|
|
513
|
-
const encryptedData = (0, exports.encryptPayloadData)(Buffer.from(key, "hex"), derivedKey.slice(0, 16), randomValue);
|
|
514
|
-
const hmac = (0, crypto_1.createHmac)("sha256", derivedKey.slice(16));
|
|
515
|
-
hmac.update(randomValue);
|
|
516
|
-
hmac.update(encryptedData);
|
|
517
|
-
const hmacDigest = hmac.digest();
|
|
518
|
-
return Buffer.concat([Buffer.from(ecdh.getPublicKey("hex", "compressed"), "hex"), randomValue, encryptedData, hmacDigest]).toString("hex");
|
|
519
|
-
};
|
|
520
|
-
exports.getLockV12Key = getLockV12Key;
|
|
521
|
-
const buildTalkbackAudioFrameHeader = (audioData, channel = 0) => {
|
|
522
|
-
const audioDataLength = Buffer.allocUnsafe(4);
|
|
523
|
-
audioDataLength.writeUInt32LE(audioData.length);
|
|
524
|
-
const unknown1 = Buffer.alloc(1);
|
|
525
|
-
const audioType = Buffer.alloc(1);
|
|
526
|
-
const audioSeq = Buffer.alloc(2);
|
|
527
|
-
const audioTimestamp = Buffer.alloc(8);
|
|
528
|
-
const audioDataHeader = Buffer.concat([audioDataLength, unknown1, audioType, audioSeq, audioTimestamp]);
|
|
529
|
-
const bytesToRead = Buffer.allocUnsafe(4);
|
|
530
|
-
bytesToRead.writeUInt32LE(audioData.length + audioDataHeader.length);
|
|
531
|
-
const magicBuffer = Buffer.from([0x01, 0x00]);
|
|
532
|
-
const channelBuffer = Buffer.from([channel, 0x00]);
|
|
533
|
-
const emptyBuffer = Buffer.from([0x00, 0x00]);
|
|
534
|
-
return Buffer.concat([
|
|
535
|
-
bytesToRead,
|
|
536
|
-
magicBuffer,
|
|
537
|
-
channelBuffer,
|
|
538
|
-
emptyBuffer,
|
|
539
|
-
audioDataHeader
|
|
540
|
-
]);
|
|
541
|
-
};
|
|
542
|
-
exports.buildTalkbackAudioFrameHeader = buildTalkbackAudioFrameHeader;
|
|
543
|
-
const decodeP2PCloudIPs = (data) => {
|
|
544
|
-
const lookupTable = Buffer.from("4959433db5bf6da347534f6165e371e9677f02030badb3892b2f35c16b8b959711e5a70deff1050783fb9d3bc5c713171d1f2529d3df", "hex");
|
|
545
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
546
|
-
const [encoded, name = "name not included"] = data.split(":");
|
|
547
|
-
const output = Buffer.alloc(encoded.length / 2);
|
|
548
|
-
for (let i = 0; i <= data.length / 2; i++) {
|
|
549
|
-
let z = 0x39; // 57 // '9'
|
|
550
|
-
for (let j = 0; j < i; j++) {
|
|
551
|
-
z = z ^ output[j];
|
|
552
|
-
}
|
|
553
|
-
const x = (data.charCodeAt(i * 2 + 1) - "A".charCodeAt(0));
|
|
554
|
-
const y = (data.charCodeAt(i * 2) - "A".charCodeAt(0)) * 0x10;
|
|
555
|
-
output[i] = z ^ lookupTable[i % lookupTable.length] ^ x + y;
|
|
556
|
-
}
|
|
557
|
-
const result = [];
|
|
558
|
-
output.toString("utf8").split(",").forEach((ip) => {
|
|
559
|
-
if (ip !== "") {
|
|
560
|
-
result.push({ host: ip, port: 32100 });
|
|
561
|
-
}
|
|
562
|
-
});
|
|
563
|
-
return result;
|
|
564
|
-
};
|
|
565
|
-
exports.decodeP2PCloudIPs = decodeP2PCloudIPs;
|
|
566
|
-
const decodeSmartSafeData = function (deviceSN, data) {
|
|
567
|
-
const response = new ble_1.BleCommandFactory(data);
|
|
568
|
-
return {
|
|
569
|
-
versionCode: response.getVersionCode(),
|
|
570
|
-
dataType: response.getDataType(),
|
|
571
|
-
commandCode: response.getCommandCode(),
|
|
572
|
-
packageFlag: response.getPackageFlag(),
|
|
573
|
-
responseCode: response.getResponseCode(),
|
|
574
|
-
data: (0, exports.decryptPayloadData)(response.getData(), Buffer.from(deviceSN), Buffer.from(device_1.SmartSafe.IV, "hex"))
|
|
575
|
-
};
|
|
576
|
-
};
|
|
577
|
-
exports.decodeSmartSafeData = decodeSmartSafeData;
|
|
578
|
-
const getSmartSafeP2PCommand = function (deviceSN, user_id, command, intCommand, channel, sequence, data) {
|
|
579
|
-
const encPayload = (0, exports.encryptPayloadData)(data, Buffer.from(deviceSN), Buffer.from(device_1.SmartSafe.IV, "hex"));
|
|
580
|
-
const bleCommand = new ble_1.BleCommandFactory()
|
|
581
|
-
.setVersionCode(device_1.SmartSafe.VERSION_CODE)
|
|
582
|
-
.setCommandCode(intCommand)
|
|
583
|
-
.setDataType(-1)
|
|
584
|
-
.setData(encPayload)
|
|
585
|
-
.getSmartSafeCommand();
|
|
586
|
-
return {
|
|
587
|
-
commandType: types_1.CommandType.CMD_SET_PAYLOAD,
|
|
588
|
-
value: JSON.stringify({
|
|
589
|
-
account_id: user_id,
|
|
590
|
-
cmd: command,
|
|
591
|
-
mChannel: channel,
|
|
592
|
-
mValue3: 0,
|
|
593
|
-
payload: {
|
|
594
|
-
data: bleCommand.toString("hex"),
|
|
595
|
-
prj_id: command,
|
|
596
|
-
seq_num: sequence,
|
|
597
|
-
}
|
|
598
|
-
}),
|
|
599
|
-
channel: channel
|
|
600
|
-
};
|
|
601
|
-
};
|
|
602
|
-
exports.getSmartSafeP2PCommand = getSmartSafeP2PCommand;
|
|
603
|
-
const getLockP2PCommand = function (deviceSN, user_id, command, channel, lockPublicKey, payload) {
|
|
604
|
-
const key = (0, exports.generateAdvancedLockAESKey)();
|
|
605
|
-
const ecdhKey = (0, exports.getAdvancedLockKey)(key, lockPublicKey);
|
|
606
|
-
const iv = (0, exports.getLockVectorBytes)(deviceSN);
|
|
607
|
-
const encPayload = (0, exports.encryptLockAESData)(key, iv, Buffer.from(JSON.stringify(payload)));
|
|
608
|
-
return {
|
|
609
|
-
commandType: types_1.CommandType.CMD_SET_PAYLOAD,
|
|
610
|
-
value: JSON.stringify({
|
|
611
|
-
key: ecdhKey,
|
|
612
|
-
account_id: user_id,
|
|
613
|
-
cmd: command,
|
|
614
|
-
mChannel: channel,
|
|
615
|
-
mValue3: 0,
|
|
616
|
-
payload: encPayload.toString("base64")
|
|
617
|
-
}).replace(/=/g, "\\u003d"),
|
|
618
|
-
channel: channel,
|
|
619
|
-
aesKey: key
|
|
620
|
-
};
|
|
621
|
-
};
|
|
622
|
-
exports.getLockP2PCommand = getLockP2PCommand;
|
|
623
|
-
const getLockV12P2PCommand = function (deviceSN, user_id, command, channel, lockPublicKey, sequence, data) {
|
|
624
|
-
const key = (0, exports.generateAdvancedLockAESKey)();
|
|
625
|
-
const encryptedAesKey = (0, exports.getLockV12Key)(key, lockPublicKey);
|
|
626
|
-
const iv = (0, exports.getLockVectorBytes)(deviceSN);
|
|
627
|
-
const encPayload = (0, exports.encryptPayloadData)(data, Buffer.from(key, "hex"), Buffer.from(iv, "hex"));
|
|
628
|
-
const bleCommand = new ble_1.BleCommandFactory()
|
|
629
|
-
.setVersionCode(device_1.Lock.VERSION_CODE_LOCKV12)
|
|
630
|
-
.setCommandCode(Number.parseInt(types_1.ESLBleCommand[types_1.ESLCommand[command]])) //TODO: Change internal command identification?
|
|
631
|
-
.setDataType(-1)
|
|
632
|
-
.setData(encPayload)
|
|
633
|
-
.setAdditionalData(Buffer.from(encryptedAesKey, "hex"));
|
|
634
|
-
return {
|
|
635
|
-
aesKey: key,
|
|
636
|
-
bleCommand: bleCommand.getCommandCode(),
|
|
637
|
-
payload: {
|
|
638
|
-
commandType: types_1.CommandType.CMD_SET_PAYLOAD,
|
|
639
|
-
value: JSON.stringify({
|
|
640
|
-
account_id: user_id,
|
|
641
|
-
cmd: types_1.CommandType.CMD_SET_PAYLOAD_LOCKV12,
|
|
642
|
-
mChannel: channel,
|
|
643
|
-
mValue3: 0,
|
|
644
|
-
payload: {
|
|
645
|
-
apiCommand: command,
|
|
646
|
-
lock_payload: bleCommand.getLockV12Command().toString("hex"),
|
|
647
|
-
seq_num: sequence,
|
|
648
|
-
}
|
|
649
|
-
})
|
|
650
|
-
}
|
|
651
|
-
};
|
|
652
|
-
};
|
|
653
|
-
exports.getLockV12P2PCommand = getLockV12P2PCommand;
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.getLockV12P2PCommand = exports.getLockP2PCommand = exports.getSmartSafeP2PCommand = exports.decodeSmartSafeData = exports.decodeP2PCloudIPs = exports.buildTalkbackAudioFrameHeader = exports.getLockV12Key = exports.getAdvancedLockKey = exports.eufyKDF = exports.decryptPayloadData = exports.encryptPayloadData = exports.isP2PQueueMessage = exports.buildVoidCommandPayload = exports.checkT8420 = exports.getVideoCodec = exports.generateAdvancedLockAESKey = exports.eslTimestamp = exports.decodeBase64 = exports.decodeLockPayload = exports.getLockVectorBytes = exports.encodeLockPayload = exports.generateLockSequence = exports.getCurrentTimeInSeconds = exports.generateBasicLockAESKey = exports.encryptLockAESData = exports.decryptLockAESData = exports.isIFrame = exports.findStartCode = exports.decryptAESData = exports.getNewRSAPrivateKey = exports.getRSAPrivateKey = exports.sortP2PMessageParts = exports.buildCommandWithStringTypePayload = exports.buildCommandHeader = exports.hasHeader = exports.sendMessage = exports.buildIntStringCommandPayload = exports.buildStringTypeCommandPayload = exports.buildIntCommandPayload = exports.buildCheckCamPayload2 = exports.buildCheckCamPayload = exports.buildLookupWithKeyPayload3 = exports.buildLookupWithKeyPayload2 = exports.buildLookupWithKeyPayload = exports.getLocalIpAddress = exports.isPrivateIp = exports.MAGIC_WORD = void 0;
|
|
30
|
+
const node_rsa_1 = __importDefault(require("node-rsa"));
|
|
31
|
+
const CryptoJS = __importStar(require("crypto-js"));
|
|
32
|
+
const crypto_1 = require("crypto");
|
|
33
|
+
const os = __importStar(require("os"));
|
|
34
|
+
const types_1 = require("./types");
|
|
35
|
+
const device_1 = require("../http/device");
|
|
36
|
+
const ble_1 = require("./ble");
|
|
37
|
+
exports.MAGIC_WORD = "XZYH";
|
|
38
|
+
const isPrivateIp = (ip) => /^(::f{4}:)?10\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
|
39
|
+
/^(::f{4}:)?192\.168\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
|
40
|
+
/^(::f{4}:)?172\.(1[6-9]|2\d|30|31)\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
|
41
|
+
/^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
|
42
|
+
/^(::f{4}:)?169\.254\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
|
|
43
|
+
/^f[cd][0-9a-f]{2}:/i.test(ip) ||
|
|
44
|
+
/^fe80:/i.test(ip) ||
|
|
45
|
+
/^::1$/.test(ip) ||
|
|
46
|
+
/^::$/.test(ip);
|
|
47
|
+
exports.isPrivateIp = isPrivateIp;
|
|
48
|
+
const stringWithLength = (input, chunkLength = 128) => {
|
|
49
|
+
const stringAsBuffer = Buffer.from(input);
|
|
50
|
+
const bufferSize = stringAsBuffer.byteLength < chunkLength ? chunkLength : Math.ceil(stringAsBuffer.byteLength / chunkLength) * chunkLength;
|
|
51
|
+
const result = Buffer.alloc(bufferSize);
|
|
52
|
+
stringAsBuffer.copy(result);
|
|
53
|
+
return result;
|
|
54
|
+
};
|
|
55
|
+
const getLocalIpAddress = (init = "") => {
|
|
56
|
+
const ifaces = os.networkInterfaces();
|
|
57
|
+
let localAddress = init;
|
|
58
|
+
for (const name in ifaces) {
|
|
59
|
+
const iface = ifaces[name].filter(function (details) {
|
|
60
|
+
return details.family === "IPv4" && details.internal === false;
|
|
61
|
+
});
|
|
62
|
+
if (iface.length > 0) {
|
|
63
|
+
localAddress = iface[0].address;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return localAddress;
|
|
68
|
+
};
|
|
69
|
+
exports.getLocalIpAddress = getLocalIpAddress;
|
|
70
|
+
const p2pDidToBuffer = (p2pDid) => {
|
|
71
|
+
const p2pArray = p2pDid.split("-");
|
|
72
|
+
const buf1 = stringWithLength(p2pArray[0], 8);
|
|
73
|
+
const buf2 = Buffer.allocUnsafe(4);
|
|
74
|
+
buf2.writeUInt32BE(Number.parseInt(p2pArray[1]), 0);
|
|
75
|
+
const buf3 = stringWithLength(p2pArray[2], 8);
|
|
76
|
+
return Buffer.concat([buf1, buf2, buf3], 20);
|
|
77
|
+
};
|
|
78
|
+
const buildLookupWithKeyPayload = (socket, p2pDid, dskKey) => {
|
|
79
|
+
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
|
|
80
|
+
const addressInfo = socket.address();
|
|
81
|
+
const port = addressInfo.port;
|
|
82
|
+
const portAsBuffer = Buffer.allocUnsafe(2);
|
|
83
|
+
portAsBuffer.writeUInt16LE(port, 0);
|
|
84
|
+
//const ip = socket.address().address;
|
|
85
|
+
const ip = (0, exports.getLocalIpAddress)(addressInfo.address);
|
|
86
|
+
const temp_buff = [];
|
|
87
|
+
ip.split(".").reverse().forEach(element => {
|
|
88
|
+
temp_buff.push(Number.parseInt(element));
|
|
89
|
+
});
|
|
90
|
+
const ipAsBuffer = Buffer.from(temp_buff);
|
|
91
|
+
const splitter = Buffer.from([0x00, 0x02]);
|
|
92
|
+
const magic = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00]);
|
|
93
|
+
const dskKeyAsBuffer = Buffer.from(dskKey);
|
|
94
|
+
const fourEmpty = Buffer.from([0x00, 0x00, 0x00, 0x00]);
|
|
95
|
+
return Buffer.concat([p2pDidBuffer, splitter, portAsBuffer, ipAsBuffer, magic, dskKeyAsBuffer, fourEmpty]);
|
|
96
|
+
};
|
|
97
|
+
exports.buildLookupWithKeyPayload = buildLookupWithKeyPayload;
|
|
98
|
+
const buildLookupWithKeyPayload2 = (p2pDid, dskKey) => {
|
|
99
|
+
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
|
|
100
|
+
const dskKeyAsBuffer = Buffer.from(dskKey);
|
|
101
|
+
const fourEmpty = Buffer.from([0x00, 0x00, 0x00, 0x00]);
|
|
102
|
+
return Buffer.concat([p2pDidBuffer, dskKeyAsBuffer, fourEmpty]);
|
|
103
|
+
};
|
|
104
|
+
exports.buildLookupWithKeyPayload2 = buildLookupWithKeyPayload2;
|
|
105
|
+
const buildLookupWithKeyPayload3 = (p2pDid, address, data) => {
|
|
106
|
+
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
|
|
107
|
+
const portAsBuffer = Buffer.allocUnsafe(2);
|
|
108
|
+
portAsBuffer.writeUInt16LE(address.port, 0);
|
|
109
|
+
const temp_buff = [];
|
|
110
|
+
address.host.split(".").reverse().forEach(element => {
|
|
111
|
+
temp_buff.push(Number.parseInt(element));
|
|
112
|
+
});
|
|
113
|
+
const ipAsBuffer = Buffer.from(temp_buff);
|
|
114
|
+
const splitter = Buffer.from([0x00, 0x02]);
|
|
115
|
+
const eightEmpty = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
|
116
|
+
return Buffer.concat([p2pDidBuffer, splitter, portAsBuffer, ipAsBuffer, eightEmpty, data]);
|
|
117
|
+
};
|
|
118
|
+
exports.buildLookupWithKeyPayload3 = buildLookupWithKeyPayload3;
|
|
119
|
+
const buildCheckCamPayload = (p2pDid) => {
|
|
120
|
+
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
|
|
121
|
+
const magic = Buffer.from([0x00, 0x00, 0x00]);
|
|
122
|
+
return Buffer.concat([p2pDidBuffer, magic]);
|
|
123
|
+
};
|
|
124
|
+
exports.buildCheckCamPayload = buildCheckCamPayload;
|
|
125
|
+
const buildCheckCamPayload2 = (p2pDid, data) => {
|
|
126
|
+
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
|
|
127
|
+
const magic = Buffer.from([0x00, 0x00, 0x00, 0x00]);
|
|
128
|
+
return Buffer.concat([data, p2pDidBuffer, magic]);
|
|
129
|
+
};
|
|
130
|
+
exports.buildCheckCamPayload2 = buildCheckCamPayload2;
|
|
131
|
+
const buildIntCommandPayload = (value, strValue = "", channel = 255) => {
|
|
132
|
+
const emptyBuffer = Buffer.from([0x00, 0x00]);
|
|
133
|
+
const magicBuffer = Buffer.from([0x01, 0x00]);
|
|
134
|
+
const channelBuffer = Buffer.from([channel, 0x00]);
|
|
135
|
+
const valueBuffer = Buffer.allocUnsafe(4);
|
|
136
|
+
valueBuffer.writeUInt32LE(value, 0);
|
|
137
|
+
const headerBuffer = Buffer.allocUnsafe(2);
|
|
138
|
+
const strValueBuffer = strValue.length === 0 ? Buffer.from([]) : stringWithLength(strValue);
|
|
139
|
+
headerBuffer.writeUInt16LE(valueBuffer.length + strValueBuffer.length, 0);
|
|
140
|
+
return Buffer.concat([
|
|
141
|
+
headerBuffer,
|
|
142
|
+
emptyBuffer,
|
|
143
|
+
magicBuffer,
|
|
144
|
+
channelBuffer,
|
|
145
|
+
emptyBuffer,
|
|
146
|
+
valueBuffer,
|
|
147
|
+
strValueBuffer
|
|
148
|
+
]);
|
|
149
|
+
};
|
|
150
|
+
exports.buildIntCommandPayload = buildIntCommandPayload;
|
|
151
|
+
const buildStringTypeCommandPayload = (strValue, strValueSub, channel = 255) => {
|
|
152
|
+
const emptyBuffer = Buffer.from([0x00, 0x00]);
|
|
153
|
+
const magicBuffer = Buffer.from([0x01, 0x00]);
|
|
154
|
+
const channelBuffer = Buffer.from([channel, 0x00]);
|
|
155
|
+
const someBuffer = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00]);
|
|
156
|
+
const strValueBuffer = stringWithLength(strValue);
|
|
157
|
+
const strValueSubBuffer = stringWithLength(strValueSub);
|
|
158
|
+
const headerBuffer = Buffer.allocUnsafe(2);
|
|
159
|
+
headerBuffer.writeUInt16LE(someBuffer.length + strValueBuffer.length + strValueSubBuffer.length, 0);
|
|
160
|
+
return Buffer.concat([
|
|
161
|
+
headerBuffer,
|
|
162
|
+
emptyBuffer,
|
|
163
|
+
magicBuffer,
|
|
164
|
+
channelBuffer,
|
|
165
|
+
emptyBuffer,
|
|
166
|
+
someBuffer,
|
|
167
|
+
strValueBuffer,
|
|
168
|
+
strValueSubBuffer
|
|
169
|
+
]);
|
|
170
|
+
};
|
|
171
|
+
exports.buildStringTypeCommandPayload = buildStringTypeCommandPayload;
|
|
172
|
+
const buildIntStringCommandPayload = (value, valueSub = 0, strValue = "", strValueSub = "", channel = 0) => {
|
|
173
|
+
const emptyBuffer = Buffer.from([0x00, 0x00]);
|
|
174
|
+
const magicBuffer = Buffer.from([0x01, 0x00]);
|
|
175
|
+
const channelBuffer = Buffer.from([channel, 0x00]);
|
|
176
|
+
const someintBuffer = Buffer.allocUnsafe(4);
|
|
177
|
+
someintBuffer.writeUInt32LE(valueSub, 0);
|
|
178
|
+
const valueBuffer = Buffer.allocUnsafe(4);
|
|
179
|
+
valueBuffer.writeUInt32LE(value, 0);
|
|
180
|
+
const strValueBuffer = strValue.length === 0 ? Buffer.from([]) : stringWithLength(strValue);
|
|
181
|
+
const strValueSubBuffer = strValueSub.length === 0 ? Buffer.from([]) : stringWithLength(strValueSub);
|
|
182
|
+
const headerBuffer = Buffer.allocUnsafe(2);
|
|
183
|
+
headerBuffer.writeUInt16LE(someintBuffer.length + valueBuffer.length + strValueBuffer.length + strValueSubBuffer.length, 0);
|
|
184
|
+
return Buffer.concat([
|
|
185
|
+
headerBuffer,
|
|
186
|
+
emptyBuffer,
|
|
187
|
+
magicBuffer,
|
|
188
|
+
channelBuffer,
|
|
189
|
+
emptyBuffer,
|
|
190
|
+
someintBuffer,
|
|
191
|
+
valueBuffer,
|
|
192
|
+
strValueBuffer,
|
|
193
|
+
strValueSubBuffer
|
|
194
|
+
]);
|
|
195
|
+
};
|
|
196
|
+
exports.buildIntStringCommandPayload = buildIntStringCommandPayload;
|
|
197
|
+
const sendMessage = async (socket, address, msgID, payload) => {
|
|
198
|
+
if (!payload)
|
|
199
|
+
payload = Buffer.from([]);
|
|
200
|
+
const payloadLen = Buffer.allocUnsafe(2);
|
|
201
|
+
payloadLen.writeUInt16BE(payload.length, 0);
|
|
202
|
+
const message = Buffer.concat([msgID, payloadLen, payload], 4 + payload.length);
|
|
203
|
+
return new Promise((resolve, reject) => {
|
|
204
|
+
socket.send(message, address.port, address.host, (err, bytes) => {
|
|
205
|
+
return err ? reject(err) : resolve(bytes);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
};
|
|
209
|
+
exports.sendMessage = sendMessage;
|
|
210
|
+
const hasHeader = (msg, searchedType) => {
|
|
211
|
+
const header = Buffer.allocUnsafe(2);
|
|
212
|
+
msg.copy(header, 0, 0, 2);
|
|
213
|
+
return Buffer.compare(header, searchedType) === 0;
|
|
214
|
+
};
|
|
215
|
+
exports.hasHeader = hasHeader;
|
|
216
|
+
const buildCommandHeader = (seqNumber, commandType, p2pDataTypeHeader = null) => {
|
|
217
|
+
let dataTypeBuffer = types_1.P2PDataTypeHeader.DATA;
|
|
218
|
+
if (p2pDataTypeHeader !== null &&
|
|
219
|
+
(Buffer.compare(p2pDataTypeHeader, types_1.P2PDataTypeHeader.DATA) === 0 ||
|
|
220
|
+
Buffer.compare(p2pDataTypeHeader, types_1.P2PDataTypeHeader.BINARY) === 0 ||
|
|
221
|
+
Buffer.compare(p2pDataTypeHeader, types_1.P2PDataTypeHeader.CONTROL) === 0 ||
|
|
222
|
+
Buffer.compare(p2pDataTypeHeader, types_1.P2PDataTypeHeader.VIDEO) === 0)) {
|
|
223
|
+
dataTypeBuffer = p2pDataTypeHeader;
|
|
224
|
+
}
|
|
225
|
+
const seqAsBuffer = Buffer.allocUnsafe(2);
|
|
226
|
+
seqAsBuffer.writeUInt16BE(seqNumber, 0);
|
|
227
|
+
const magicString = Buffer.from(exports.MAGIC_WORD);
|
|
228
|
+
const commandTypeBuffer = Buffer.allocUnsafe(2);
|
|
229
|
+
commandTypeBuffer.writeUInt16LE(commandType, 0);
|
|
230
|
+
return Buffer.concat([dataTypeBuffer, seqAsBuffer, magicString, commandTypeBuffer]);
|
|
231
|
+
};
|
|
232
|
+
exports.buildCommandHeader = buildCommandHeader;
|
|
233
|
+
const buildCommandWithStringTypePayload = (value, channel = 0) => {
|
|
234
|
+
// type = 6
|
|
235
|
+
//setCommandWithString()
|
|
236
|
+
const headerBuffer = Buffer.allocUnsafe(2);
|
|
237
|
+
const emptyBuffer = Buffer.from([0x00, 0x00]);
|
|
238
|
+
const magicBuffer = Buffer.from([0x01, 0x00]);
|
|
239
|
+
const channelBuffer = Buffer.from([channel, 0x00]);
|
|
240
|
+
const jsonBuffer = Buffer.from(value);
|
|
241
|
+
headerBuffer.writeUInt16LE(jsonBuffer.length, 0);
|
|
242
|
+
return Buffer.concat([
|
|
243
|
+
headerBuffer,
|
|
244
|
+
emptyBuffer,
|
|
245
|
+
magicBuffer,
|
|
246
|
+
channelBuffer,
|
|
247
|
+
emptyBuffer,
|
|
248
|
+
jsonBuffer,
|
|
249
|
+
]);
|
|
250
|
+
};
|
|
251
|
+
exports.buildCommandWithStringTypePayload = buildCommandWithStringTypePayload;
|
|
252
|
+
const sortP2PMessageParts = (messages) => {
|
|
253
|
+
let completeMessage = Buffer.from([]);
|
|
254
|
+
Object.keys(messages).map(Number)
|
|
255
|
+
.sort((a, b) => a - b) // assure the seqNumbers are in correct order
|
|
256
|
+
.forEach((key) => {
|
|
257
|
+
completeMessage = Buffer.concat([completeMessage, messages[key]]);
|
|
258
|
+
});
|
|
259
|
+
return completeMessage;
|
|
260
|
+
};
|
|
261
|
+
exports.sortP2PMessageParts = sortP2PMessageParts;
|
|
262
|
+
const getRSAPrivateKey = (pem) => {
|
|
263
|
+
const key = new node_rsa_1.default();
|
|
264
|
+
if (pem.startsWith("-----BEGIN RSA PRIVATE KEY-----")) {
|
|
265
|
+
pem = pem.replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("-----END RSA PRIVATE KEY-----", "");
|
|
266
|
+
}
|
|
267
|
+
key.importKey(pem, "pkcs8");
|
|
268
|
+
key.setOptions({
|
|
269
|
+
encryptionScheme: "pkcs1"
|
|
270
|
+
});
|
|
271
|
+
return key;
|
|
272
|
+
};
|
|
273
|
+
exports.getRSAPrivateKey = getRSAPrivateKey;
|
|
274
|
+
const getNewRSAPrivateKey = () => {
|
|
275
|
+
const key = new node_rsa_1.default({ b: 1024 });
|
|
276
|
+
key.setOptions({
|
|
277
|
+
encryptionScheme: "pkcs1"
|
|
278
|
+
});
|
|
279
|
+
return key;
|
|
280
|
+
};
|
|
281
|
+
exports.getNewRSAPrivateKey = getNewRSAPrivateKey;
|
|
282
|
+
const decryptAESData = (hexkey, data) => {
|
|
283
|
+
const key = CryptoJS.enc.Hex.parse(hexkey);
|
|
284
|
+
const cipherParams = CryptoJS.lib.CipherParams.create({
|
|
285
|
+
ciphertext: CryptoJS.enc.Hex.parse(data.toString("hex"))
|
|
286
|
+
});
|
|
287
|
+
const decrypted = CryptoJS.AES.decrypt(cipherParams, key, {
|
|
288
|
+
mode: CryptoJS.mode.ECB,
|
|
289
|
+
padding: CryptoJS.pad.NoPadding
|
|
290
|
+
});
|
|
291
|
+
return Buffer.from(CryptoJS.enc.Hex.stringify(decrypted), "hex");
|
|
292
|
+
};
|
|
293
|
+
exports.decryptAESData = decryptAESData;
|
|
294
|
+
const findStartCode = (data) => {
|
|
295
|
+
if (data !== undefined && data.length > 0) {
|
|
296
|
+
if (data.length >= 4) {
|
|
297
|
+
const startcode = [...data.slice(0, 4)];
|
|
298
|
+
if ((startcode[0] === 0 && startcode[1] === 0 && startcode[2] === 1) || (startcode[0] === 0 && startcode[1] === 0 && startcode[2] === 0 && startcode[3] === 1))
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
else if (data.length === 3) {
|
|
302
|
+
const startcode = [...data.slice(0, 3)];
|
|
303
|
+
if ((startcode[0] === 0 && startcode[1] === 0 && startcode[2] === 1))
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return false;
|
|
308
|
+
};
|
|
309
|
+
exports.findStartCode = findStartCode;
|
|
310
|
+
const isIFrame = (data) => {
|
|
311
|
+
const validValues = [64, 66, 68, 78, 101, 103];
|
|
312
|
+
if (data !== undefined && data.length > 0) {
|
|
313
|
+
if (data.length >= 5) {
|
|
314
|
+
const startcode = [...data.slice(0, 5)];
|
|
315
|
+
if (validValues.includes(startcode[3]) || validValues.includes(startcode[4]))
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return false;
|
|
320
|
+
};
|
|
321
|
+
exports.isIFrame = isIFrame;
|
|
322
|
+
const decryptLockAESData = (key, iv, data) => {
|
|
323
|
+
const ekey = CryptoJS.enc.Hex.parse(key);
|
|
324
|
+
const eiv = CryptoJS.enc.Hex.parse(iv);
|
|
325
|
+
const cipherParams = CryptoJS.lib.CipherParams.create({
|
|
326
|
+
ciphertext: CryptoJS.enc.Hex.parse(data.toString("hex"))
|
|
327
|
+
});
|
|
328
|
+
const decrypted = CryptoJS.AES.decrypt(cipherParams, ekey, {
|
|
329
|
+
iv: eiv,
|
|
330
|
+
mode: CryptoJS.mode.CBC,
|
|
331
|
+
padding: CryptoJS.pad.Pkcs7
|
|
332
|
+
});
|
|
333
|
+
return Buffer.from(CryptoJS.enc.Hex.stringify(decrypted), "hex");
|
|
334
|
+
};
|
|
335
|
+
exports.decryptLockAESData = decryptLockAESData;
|
|
336
|
+
const encryptLockAESData = (key, iv, data) => {
|
|
337
|
+
const ekey = CryptoJS.enc.Hex.parse(key);
|
|
338
|
+
const eiv = CryptoJS.enc.Hex.parse(iv);
|
|
339
|
+
const encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Hex.parse(data.toString("hex")), ekey, {
|
|
340
|
+
iv: eiv,
|
|
341
|
+
mode: CryptoJS.mode.CBC,
|
|
342
|
+
padding: CryptoJS.pad.Pkcs7
|
|
343
|
+
});
|
|
344
|
+
return Buffer.from(CryptoJS.enc.Hex.stringify(encrypted.ciphertext), "hex");
|
|
345
|
+
};
|
|
346
|
+
exports.encryptLockAESData = encryptLockAESData;
|
|
347
|
+
const generateBasicLockAESKey = (adminID, stationSN) => {
|
|
348
|
+
const encoder = new TextEncoder();
|
|
349
|
+
const encOwnerID = encoder.encode(adminID);
|
|
350
|
+
const encStationSerial = encoder.encode(stationSN);
|
|
351
|
+
const array = [104, -83, -72, 38, -107, 99, -110, 17, -95, -121, 54, 57, -46, -98, -111, 89];
|
|
352
|
+
for (let i = 0; i < 16; i++) {
|
|
353
|
+
array[i] = (array[i] + encStationSerial[((encStationSerial[i] * 3) + 5) % 16] + encOwnerID[((encOwnerID[i] * 3) + 5) % 40]);
|
|
354
|
+
}
|
|
355
|
+
return Buffer.from(array).toString("hex");
|
|
356
|
+
};
|
|
357
|
+
exports.generateBasicLockAESKey = generateBasicLockAESKey;
|
|
358
|
+
const getCurrentTimeInSeconds = function () {
|
|
359
|
+
return Math.trunc(new Date().getTime() / 1000);
|
|
360
|
+
};
|
|
361
|
+
exports.getCurrentTimeInSeconds = getCurrentTimeInSeconds;
|
|
362
|
+
const generateLockSequence = (deviceType) => {
|
|
363
|
+
if (device_1.Device.isLockWifi(deviceType) || device_1.Device.isLockWifiNoFinger(deviceType))
|
|
364
|
+
return Math.trunc(Math.random() * 1000);
|
|
365
|
+
return (0, exports.getCurrentTimeInSeconds)();
|
|
366
|
+
};
|
|
367
|
+
exports.generateLockSequence = generateLockSequence;
|
|
368
|
+
const encodeLockPayload = (data) => {
|
|
369
|
+
const encoder = new TextEncoder();
|
|
370
|
+
const encData = encoder.encode(data);
|
|
371
|
+
const length = encData.length;
|
|
372
|
+
const old_buffer = Buffer.from(encData);
|
|
373
|
+
if (length % 16 == 0) {
|
|
374
|
+
return old_buffer;
|
|
375
|
+
}
|
|
376
|
+
const new_length = (Math.trunc(length / 16) + 1) * 16;
|
|
377
|
+
const new_buffer = Buffer.alloc(new_length);
|
|
378
|
+
old_buffer.copy(new_buffer, 0);
|
|
379
|
+
return new_buffer;
|
|
380
|
+
};
|
|
381
|
+
exports.encodeLockPayload = encodeLockPayload;
|
|
382
|
+
const getLockVectorBytes = (data) => {
|
|
383
|
+
const encoder = new TextEncoder();
|
|
384
|
+
const encData = encoder.encode(data);
|
|
385
|
+
const old_buffer = Buffer.from(encData);
|
|
386
|
+
if (encData.length >= 16)
|
|
387
|
+
return old_buffer.toString("hex");
|
|
388
|
+
const new_buffer = Buffer.alloc(16);
|
|
389
|
+
old_buffer.copy(new_buffer, 0);
|
|
390
|
+
return new_buffer.toString("hex");
|
|
391
|
+
};
|
|
392
|
+
exports.getLockVectorBytes = getLockVectorBytes;
|
|
393
|
+
const decodeLockPayload = (data) => {
|
|
394
|
+
const decoder = new TextDecoder();
|
|
395
|
+
return decoder.decode(data);
|
|
396
|
+
};
|
|
397
|
+
exports.decodeLockPayload = decodeLockPayload;
|
|
398
|
+
const decodeBase64 = (data) => {
|
|
399
|
+
return Buffer.from(data, "base64");
|
|
400
|
+
};
|
|
401
|
+
exports.decodeBase64 = decodeBase64;
|
|
402
|
+
const eslTimestamp = function (timestamp_in_sec = new Date().getTime() / 1000) {
|
|
403
|
+
const array = [];
|
|
404
|
+
for (let pos = 0; pos < 4; pos++) {
|
|
405
|
+
array[pos] = ((timestamp_in_sec >> (pos * 8)) & 255);
|
|
406
|
+
}
|
|
407
|
+
return array;
|
|
408
|
+
};
|
|
409
|
+
exports.eslTimestamp = eslTimestamp;
|
|
410
|
+
const generateAdvancedLockAESKey = () => {
|
|
411
|
+
const randomBytesArray = [...(0, crypto_1.randomBytes)(16)];
|
|
412
|
+
let result = "";
|
|
413
|
+
for (let pos = 0; pos < randomBytesArray.length; pos++) {
|
|
414
|
+
result += "0123456789ABCDEF".charAt((randomBytesArray[pos] >> 4) & 15);
|
|
415
|
+
result += "0123456789ABCDEF".charAt(randomBytesArray[pos] & 15);
|
|
416
|
+
}
|
|
417
|
+
return result;
|
|
418
|
+
};
|
|
419
|
+
exports.generateAdvancedLockAESKey = generateAdvancedLockAESKey;
|
|
420
|
+
const getVideoCodec = (data) => {
|
|
421
|
+
if (data !== undefined && data.length > 0) {
|
|
422
|
+
if (data.length >= 5) {
|
|
423
|
+
const h265Values = [38, 64, 66, 68, 78];
|
|
424
|
+
const startcode = [...data.slice(0, 5)];
|
|
425
|
+
if (h265Values.includes(startcode[3]) || h265Values.includes(startcode[4])) {
|
|
426
|
+
return types_1.VideoCodec.H265;
|
|
427
|
+
}
|
|
428
|
+
else if (startcode[3] === 103 || startcode[4] === 103) {
|
|
429
|
+
return types_1.VideoCodec.H264;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return types_1.VideoCodec.H264;
|
|
433
|
+
}
|
|
434
|
+
return types_1.VideoCodec.UNKNOWN; // Maybe return h264 as Eufy does?
|
|
435
|
+
};
|
|
436
|
+
exports.getVideoCodec = getVideoCodec;
|
|
437
|
+
const checkT8420 = (serialNumber) => {
|
|
438
|
+
if (!(serialNumber !== undefined && serialNumber !== null && serialNumber.length > 0 && serialNumber.startsWith("T8420")) || serialNumber.length <= 7 || serialNumber[6] != "6") {
|
|
439
|
+
return false;
|
|
440
|
+
}
|
|
441
|
+
return true;
|
|
442
|
+
};
|
|
443
|
+
exports.checkT8420 = checkT8420;
|
|
444
|
+
const buildVoidCommandPayload = (channel = 255) => {
|
|
445
|
+
const headerBuffer = Buffer.from([0x00, 0x00]);
|
|
446
|
+
const emptyBuffer = Buffer.from([0x00, 0x00]);
|
|
447
|
+
const magicBuffer = Buffer.from([0x01, 0x00]);
|
|
448
|
+
const channelBuffer = Buffer.from([channel, 0x00]);
|
|
449
|
+
return Buffer.concat([
|
|
450
|
+
headerBuffer,
|
|
451
|
+
emptyBuffer,
|
|
452
|
+
magicBuffer,
|
|
453
|
+
channelBuffer,
|
|
454
|
+
emptyBuffer
|
|
455
|
+
]);
|
|
456
|
+
};
|
|
457
|
+
exports.buildVoidCommandPayload = buildVoidCommandPayload;
|
|
458
|
+
function isP2PQueueMessage(type) {
|
|
459
|
+
return type.payload !== undefined;
|
|
460
|
+
}
|
|
461
|
+
exports.isP2PQueueMessage = isP2PQueueMessage;
|
|
462
|
+
const encryptPayloadData = (data, key, iv) => {
|
|
463
|
+
const cipher = (0, crypto_1.createCipheriv)("aes-128-cbc", key, iv);
|
|
464
|
+
return Buffer.concat([
|
|
465
|
+
cipher.update(data),
|
|
466
|
+
cipher.final()
|
|
467
|
+
]);
|
|
468
|
+
};
|
|
469
|
+
exports.encryptPayloadData = encryptPayloadData;
|
|
470
|
+
const decryptPayloadData = (data, key, iv) => {
|
|
471
|
+
const cipher = (0, crypto_1.createDecipheriv)("aes-128-cbc", key, iv);
|
|
472
|
+
return Buffer.concat([
|
|
473
|
+
cipher.update(data),
|
|
474
|
+
cipher.final()
|
|
475
|
+
]);
|
|
476
|
+
};
|
|
477
|
+
exports.decryptPayloadData = decryptPayloadData;
|
|
478
|
+
const eufyKDF = (key) => {
|
|
479
|
+
const hash_length = 32;
|
|
480
|
+
const digest_length = 48;
|
|
481
|
+
const staticBuffer = Buffer.from("ECIES");
|
|
482
|
+
const steps = Math.ceil(digest_length / hash_length);
|
|
483
|
+
const buffer = Buffer.alloc(hash_length * steps);
|
|
484
|
+
let tmpBuffer = staticBuffer;
|
|
485
|
+
for (let step = 0; step < steps; ++step) {
|
|
486
|
+
tmpBuffer = (0, crypto_1.createHmac)("sha256", key).update(tmpBuffer).digest();
|
|
487
|
+
const digest = (0, crypto_1.createHmac)("sha256", key).update(Buffer.concat([tmpBuffer, staticBuffer])).digest();
|
|
488
|
+
digest.copy(buffer, hash_length * step);
|
|
489
|
+
}
|
|
490
|
+
return buffer.slice(0, digest_length);
|
|
491
|
+
};
|
|
492
|
+
exports.eufyKDF = eufyKDF;
|
|
493
|
+
const getAdvancedLockKey = (key, publicKey) => {
|
|
494
|
+
const ecdh = (0, crypto_1.createECDH)("prime256v1");
|
|
495
|
+
ecdh.generateKeys();
|
|
496
|
+
const secret = ecdh.computeSecret(Buffer.concat([Buffer.from("04", "hex"), Buffer.from(publicKey, "hex")]));
|
|
497
|
+
const randomValue = (0, crypto_1.randomBytes)(16);
|
|
498
|
+
const derivedKey = (0, exports.eufyKDF)(secret);
|
|
499
|
+
const encryptedData = (0, exports.encryptPayloadData)(key, derivedKey.slice(0, 16), randomValue);
|
|
500
|
+
const hmac = (0, crypto_1.createHmac)("sha256", derivedKey.slice(16));
|
|
501
|
+
hmac.update(randomValue);
|
|
502
|
+
hmac.update(encryptedData);
|
|
503
|
+
const hmacDigest = hmac.digest();
|
|
504
|
+
return Buffer.concat([Buffer.from(ecdh.getPublicKey("hex", "compressed"), "hex"), randomValue, encryptedData, hmacDigest]).toString("hex");
|
|
505
|
+
};
|
|
506
|
+
exports.getAdvancedLockKey = getAdvancedLockKey;
|
|
507
|
+
const getLockV12Key = (key, publicKey) => {
|
|
508
|
+
const ecdh = (0, crypto_1.createECDH)("prime256v1");
|
|
509
|
+
ecdh.generateKeys();
|
|
510
|
+
const secret = ecdh.computeSecret(Buffer.concat([Buffer.from("04", "hex"), Buffer.from(publicKey, "hex")]));
|
|
511
|
+
const randomValue = (0, crypto_1.randomBytes)(16);
|
|
512
|
+
const derivedKey = (0, exports.eufyKDF)(secret);
|
|
513
|
+
const encryptedData = (0, exports.encryptPayloadData)(Buffer.from(key, "hex"), derivedKey.slice(0, 16), randomValue);
|
|
514
|
+
const hmac = (0, crypto_1.createHmac)("sha256", derivedKey.slice(16));
|
|
515
|
+
hmac.update(randomValue);
|
|
516
|
+
hmac.update(encryptedData);
|
|
517
|
+
const hmacDigest = hmac.digest();
|
|
518
|
+
return Buffer.concat([Buffer.from(ecdh.getPublicKey("hex", "compressed"), "hex"), randomValue, encryptedData, hmacDigest]).toString("hex");
|
|
519
|
+
};
|
|
520
|
+
exports.getLockV12Key = getLockV12Key;
|
|
521
|
+
const buildTalkbackAudioFrameHeader = (audioData, channel = 0) => {
|
|
522
|
+
const audioDataLength = Buffer.allocUnsafe(4);
|
|
523
|
+
audioDataLength.writeUInt32LE(audioData.length);
|
|
524
|
+
const unknown1 = Buffer.alloc(1);
|
|
525
|
+
const audioType = Buffer.alloc(1);
|
|
526
|
+
const audioSeq = Buffer.alloc(2);
|
|
527
|
+
const audioTimestamp = Buffer.alloc(8);
|
|
528
|
+
const audioDataHeader = Buffer.concat([audioDataLength, unknown1, audioType, audioSeq, audioTimestamp]);
|
|
529
|
+
const bytesToRead = Buffer.allocUnsafe(4);
|
|
530
|
+
bytesToRead.writeUInt32LE(audioData.length + audioDataHeader.length);
|
|
531
|
+
const magicBuffer = Buffer.from([0x01, 0x00]);
|
|
532
|
+
const channelBuffer = Buffer.from([channel, 0x00]);
|
|
533
|
+
const emptyBuffer = Buffer.from([0x00, 0x00]);
|
|
534
|
+
return Buffer.concat([
|
|
535
|
+
bytesToRead,
|
|
536
|
+
magicBuffer,
|
|
537
|
+
channelBuffer,
|
|
538
|
+
emptyBuffer,
|
|
539
|
+
audioDataHeader
|
|
540
|
+
]);
|
|
541
|
+
};
|
|
542
|
+
exports.buildTalkbackAudioFrameHeader = buildTalkbackAudioFrameHeader;
|
|
543
|
+
const decodeP2PCloudIPs = (data) => {
|
|
544
|
+
const lookupTable = Buffer.from("4959433db5bf6da347534f6165e371e9677f02030badb3892b2f35c16b8b959711e5a70deff1050783fb9d3bc5c713171d1f2529d3df", "hex");
|
|
545
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
546
|
+
const [encoded, name = "name not included"] = data.split(":");
|
|
547
|
+
const output = Buffer.alloc(encoded.length / 2);
|
|
548
|
+
for (let i = 0; i <= data.length / 2; i++) {
|
|
549
|
+
let z = 0x39; // 57 // '9'
|
|
550
|
+
for (let j = 0; j < i; j++) {
|
|
551
|
+
z = z ^ output[j];
|
|
552
|
+
}
|
|
553
|
+
const x = (data.charCodeAt(i * 2 + 1) - "A".charCodeAt(0));
|
|
554
|
+
const y = (data.charCodeAt(i * 2) - "A".charCodeAt(0)) * 0x10;
|
|
555
|
+
output[i] = z ^ lookupTable[i % lookupTable.length] ^ x + y;
|
|
556
|
+
}
|
|
557
|
+
const result = [];
|
|
558
|
+
output.toString("utf8").split(",").forEach((ip) => {
|
|
559
|
+
if (ip !== "") {
|
|
560
|
+
result.push({ host: ip, port: 32100 });
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
return result;
|
|
564
|
+
};
|
|
565
|
+
exports.decodeP2PCloudIPs = decodeP2PCloudIPs;
|
|
566
|
+
const decodeSmartSafeData = function (deviceSN, data) {
|
|
567
|
+
const response = new ble_1.BleCommandFactory(data);
|
|
568
|
+
return {
|
|
569
|
+
versionCode: response.getVersionCode(),
|
|
570
|
+
dataType: response.getDataType(),
|
|
571
|
+
commandCode: response.getCommandCode(),
|
|
572
|
+
packageFlag: response.getPackageFlag(),
|
|
573
|
+
responseCode: response.getResponseCode(),
|
|
574
|
+
data: (0, exports.decryptPayloadData)(response.getData(), Buffer.from(deviceSN), Buffer.from(device_1.SmartSafe.IV, "hex"))
|
|
575
|
+
};
|
|
576
|
+
};
|
|
577
|
+
exports.decodeSmartSafeData = decodeSmartSafeData;
|
|
578
|
+
const getSmartSafeP2PCommand = function (deviceSN, user_id, command, intCommand, channel, sequence, data) {
|
|
579
|
+
const encPayload = (0, exports.encryptPayloadData)(data, Buffer.from(deviceSN), Buffer.from(device_1.SmartSafe.IV, "hex"));
|
|
580
|
+
const bleCommand = new ble_1.BleCommandFactory()
|
|
581
|
+
.setVersionCode(device_1.SmartSafe.VERSION_CODE)
|
|
582
|
+
.setCommandCode(intCommand)
|
|
583
|
+
.setDataType(-1)
|
|
584
|
+
.setData(encPayload)
|
|
585
|
+
.getSmartSafeCommand();
|
|
586
|
+
return {
|
|
587
|
+
commandType: types_1.CommandType.CMD_SET_PAYLOAD,
|
|
588
|
+
value: JSON.stringify({
|
|
589
|
+
account_id: user_id,
|
|
590
|
+
cmd: command,
|
|
591
|
+
mChannel: channel,
|
|
592
|
+
mValue3: 0,
|
|
593
|
+
payload: {
|
|
594
|
+
data: bleCommand.toString("hex"),
|
|
595
|
+
prj_id: command,
|
|
596
|
+
seq_num: sequence,
|
|
597
|
+
}
|
|
598
|
+
}),
|
|
599
|
+
channel: channel
|
|
600
|
+
};
|
|
601
|
+
};
|
|
602
|
+
exports.getSmartSafeP2PCommand = getSmartSafeP2PCommand;
|
|
603
|
+
const getLockP2PCommand = function (deviceSN, user_id, command, channel, lockPublicKey, payload) {
|
|
604
|
+
const key = (0, exports.generateAdvancedLockAESKey)();
|
|
605
|
+
const ecdhKey = (0, exports.getAdvancedLockKey)(key, lockPublicKey);
|
|
606
|
+
const iv = (0, exports.getLockVectorBytes)(deviceSN);
|
|
607
|
+
const encPayload = (0, exports.encryptLockAESData)(key, iv, Buffer.from(JSON.stringify(payload)));
|
|
608
|
+
return {
|
|
609
|
+
commandType: types_1.CommandType.CMD_SET_PAYLOAD,
|
|
610
|
+
value: JSON.stringify({
|
|
611
|
+
key: ecdhKey,
|
|
612
|
+
account_id: user_id,
|
|
613
|
+
cmd: command,
|
|
614
|
+
mChannel: channel,
|
|
615
|
+
mValue3: 0,
|
|
616
|
+
payload: encPayload.toString("base64")
|
|
617
|
+
}).replace(/=/g, "\\u003d"),
|
|
618
|
+
channel: channel,
|
|
619
|
+
aesKey: key
|
|
620
|
+
};
|
|
621
|
+
};
|
|
622
|
+
exports.getLockP2PCommand = getLockP2PCommand;
|
|
623
|
+
const getLockV12P2PCommand = function (deviceSN, user_id, command, channel, lockPublicKey, sequence, data) {
|
|
624
|
+
const key = (0, exports.generateAdvancedLockAESKey)();
|
|
625
|
+
const encryptedAesKey = (0, exports.getLockV12Key)(key, lockPublicKey);
|
|
626
|
+
const iv = (0, exports.getLockVectorBytes)(deviceSN);
|
|
627
|
+
const encPayload = (0, exports.encryptPayloadData)(data, Buffer.from(key, "hex"), Buffer.from(iv, "hex"));
|
|
628
|
+
const bleCommand = new ble_1.BleCommandFactory()
|
|
629
|
+
.setVersionCode(device_1.Lock.VERSION_CODE_LOCKV12)
|
|
630
|
+
.setCommandCode(Number.parseInt(types_1.ESLBleCommand[types_1.ESLCommand[command]])) //TODO: Change internal command identification?
|
|
631
|
+
.setDataType(-1)
|
|
632
|
+
.setData(encPayload)
|
|
633
|
+
.setAdditionalData(Buffer.from(encryptedAesKey, "hex"));
|
|
634
|
+
return {
|
|
635
|
+
aesKey: key,
|
|
636
|
+
bleCommand: bleCommand.getCommandCode(),
|
|
637
|
+
payload: {
|
|
638
|
+
commandType: types_1.CommandType.CMD_SET_PAYLOAD,
|
|
639
|
+
value: JSON.stringify({
|
|
640
|
+
account_id: user_id,
|
|
641
|
+
cmd: types_1.CommandType.CMD_SET_PAYLOAD_LOCKV12,
|
|
642
|
+
mChannel: channel,
|
|
643
|
+
mValue3: 0,
|
|
644
|
+
payload: {
|
|
645
|
+
apiCommand: command,
|
|
646
|
+
lock_payload: bleCommand.getLockV12Command().toString("hex"),
|
|
647
|
+
seq_num: sequence,
|
|
648
|
+
}
|
|
649
|
+
})
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
};
|
|
653
|
+
exports.getLockV12P2PCommand = getLockV12P2PCommand;
|
|
654
654
|
//# sourceMappingURL=utils.js.map
|