@vex-chat/libvex 5.2.0 → 5.3.1
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/CLA.md +38 -0
- package/LICENSE-COMMERCIAL +10 -0
- package/LICENSING.md +15 -0
- package/README.md +8 -2
- package/dist/Client.d.ts +39 -3
- package/dist/Client.d.ts.map +1 -1
- package/dist/Client.js +961 -480
- package/dist/Client.js.map +1 -1
- package/dist/Storage.d.ts +5 -0
- package/dist/Storage.d.ts.map +1 -1
- package/dist/Storage.js +5 -0
- package/dist/Storage.js.map +1 -1
- package/dist/__tests__/harness/memory-storage.d.ts +7 -2
- package/dist/__tests__/harness/memory-storage.d.ts.map +1 -1
- package/dist/__tests__/harness/memory-storage.js +44 -29
- package/dist/__tests__/harness/memory-storage.js.map +1 -1
- package/dist/codec.d.ts +9 -9
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +17 -19
- package/dist/codec.js.map +1 -1
- package/dist/codecs.d.ts +5 -0
- package/dist/codecs.d.ts.map +1 -1
- package/dist/codecs.js +5 -0
- package/dist/codecs.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/keystore/memory.d.ts +5 -0
- package/dist/keystore/memory.d.ts.map +1 -1
- package/dist/keystore/memory.js +5 -0
- package/dist/keystore/memory.js.map +1 -1
- package/dist/keystore/node.d.ts +5 -0
- package/dist/keystore/node.d.ts.map +1 -1
- package/dist/keystore/node.js +16 -8
- package/dist/keystore/node.js.map +1 -1
- package/dist/preset/common.d.ts +5 -0
- package/dist/preset/common.d.ts.map +1 -1
- package/dist/preset/common.js +5 -0
- package/dist/preset/common.js.map +1 -1
- package/dist/preset/node.d.ts +5 -0
- package/dist/preset/node.d.ts.map +1 -1
- package/dist/preset/node.js +9 -1
- package/dist/preset/node.js.map +1 -1
- package/dist/preset/test.d.ts +5 -0
- package/dist/preset/test.d.ts.map +1 -1
- package/dist/preset/test.js +9 -1
- package/dist/preset/test.js.map +1 -1
- package/dist/storage/node/http-agents.d.ts +5 -0
- package/dist/storage/node/http-agents.d.ts.map +1 -1
- package/dist/storage/node/http-agents.js +5 -0
- package/dist/storage/node/http-agents.js.map +1 -1
- package/dist/storage/node.d.ts +6 -1
- package/dist/storage/node.d.ts.map +1 -1
- package/dist/storage/node.js +7 -4
- package/dist/storage/node.js.map +1 -1
- package/dist/storage/schema.d.ts +5 -0
- package/dist/storage/schema.d.ts.map +1 -1
- package/dist/storage/schema.js +5 -0
- package/dist/storage/schema.js.map +1 -1
- package/dist/storage/sqlite.d.ts +22 -4
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +172 -98
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/transport/types.d.ts +5 -0
- package/dist/transport/types.d.ts.map +1 -1
- package/dist/transport/types.js +5 -0
- package/dist/transport/types.js.map +1 -1
- package/dist/transport/websocket.d.ts +5 -0
- package/dist/transport/websocket.d.ts.map +1 -1
- package/dist/transport/websocket.js +5 -0
- package/dist/transport/websocket.js.map +1 -1
- package/dist/types/crypto.d.ts +5 -0
- package/dist/types/crypto.d.ts.map +1 -1
- package/dist/types/crypto.js +3 -5
- package/dist/types/crypto.js.map +1 -1
- package/dist/types/identity.d.ts +5 -0
- package/dist/types/identity.d.ts.map +1 -1
- package/dist/types/identity.js +3 -2
- package/dist/types/identity.js.map +1 -1
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -1
- package/dist/utils/capitalize.d.ts +5 -0
- package/dist/utils/capitalize.d.ts.map +1 -1
- package/dist/utils/capitalize.js +5 -0
- package/dist/utils/capitalize.js.map +1 -1
- package/dist/utils/fipsMailExtra.d.ts +30 -0
- package/dist/utils/fipsMailExtra.d.ts.map +1 -0
- package/dist/utils/fipsMailExtra.js +114 -0
- package/dist/utils/fipsMailExtra.js.map +1 -0
- package/dist/utils/formatBytes.d.ts +5 -0
- package/dist/utils/formatBytes.d.ts.map +1 -1
- package/dist/utils/formatBytes.js +5 -0
- package/dist/utils/formatBytes.js.map +1 -1
- package/dist/utils/resolveAtRestAesKey.d.ts +13 -0
- package/dist/utils/resolveAtRestAesKey.d.ts.map +1 -0
- package/dist/utils/resolveAtRestAesKey.js +26 -0
- package/dist/utils/resolveAtRestAesKey.js.map +1 -0
- package/dist/utils/sqlSessionToCrypto.d.ts +5 -0
- package/dist/utils/sqlSessionToCrypto.d.ts.map +1 -1
- package/dist/utils/sqlSessionToCrypto.js +5 -0
- package/dist/utils/sqlSessionToCrypto.js.map +1 -1
- package/dist/utils/uint8uuid.d.ts +5 -0
- package/dist/utils/uint8uuid.d.ts.map +1 -1
- package/dist/utils/uint8uuid.js +5 -0
- package/dist/utils/uint8uuid.js.map +1 -1
- package/package.json +14 -4
- package/src/Client.ts +1239 -619
- package/src/Storage.ts +6 -0
- package/src/__tests__/codec.test.ts +6 -0
- package/src/__tests__/harness/fixtures.ts +6 -0
- package/src/__tests__/harness/memory-storage.ts +72 -52
- package/src/__tests__/harness/platform-transports.ts +6 -0
- package/src/__tests__/harness/poison-node-imports.ts +6 -0
- package/src/__tests__/harness/shared-suite.ts +288 -124
- package/src/__tests__/platform-browser.test.ts +15 -1
- package/src/__tests__/platform-node.test.ts +17 -3
- package/src/codec.ts +21 -8
- package/src/codecs.ts +6 -0
- package/src/index.ts +6 -0
- package/src/keystore/memory.ts +6 -0
- package/src/keystore/node.ts +27 -13
- package/src/preset/common.ts +6 -0
- package/src/preset/node.ts +14 -1
- package/src/preset/test.ts +14 -1
- package/src/storage/node/http-agents.ts +6 -0
- package/src/storage/node.ts +11 -4
- package/src/storage/schema.ts +6 -0
- package/src/storage/sqlite.ts +208 -135
- package/src/transport/types.ts +6 -0
- package/src/transport/websocket.ts +6 -0
- package/src/types/crypto.ts +6 -0
- package/src/types/identity.ts +6 -0
- package/src/types/index.ts +6 -0
- package/src/utils/capitalize.ts +6 -0
- package/src/utils/fipsMailExtra.ts +164 -0
- package/src/utils/formatBytes.ts +6 -0
- package/src/utils/resolveAtRestAesKey.ts +39 -0
- package/src/utils/sqlSessionToCrypto.ts +6 -0
- package/src/utils/uint8uuid.ts +6 -0
package/src/Storage.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2020-2026 Vex Heavy Industries LLC
|
|
3
|
+
* Licensed under AGPL-3.0. See LICENSE for details.
|
|
4
|
+
* Commercial licenses available at vex.wtf
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import type { Message } from "../../index.js";
|
|
2
8
|
import type { Storage } from "../../Storage.js";
|
|
3
9
|
import type {
|
|
@@ -8,12 +14,13 @@ import type {
|
|
|
8
14
|
import type { Device, PreKeysSQL, SessionSQL } from "@vex-chat/types";
|
|
9
15
|
|
|
10
16
|
import {
|
|
11
|
-
|
|
17
|
+
getCryptoProfile,
|
|
12
18
|
xBoxKeyPairFromSecret,
|
|
13
|
-
|
|
19
|
+
xBoxKeyPairFromSecretAsync,
|
|
14
20
|
xSecretbox,
|
|
21
|
+
xSecretboxAsync,
|
|
15
22
|
xSecretboxOpen,
|
|
16
|
-
|
|
23
|
+
xSecretboxOpenAsync,
|
|
17
24
|
XUtils,
|
|
18
25
|
} from "@vex-chat/crypto";
|
|
19
26
|
|
|
@@ -28,7 +35,7 @@ import { EventEmitter } from "eventemitter3";
|
|
|
28
35
|
export class MemoryStorage extends EventEmitter implements Storage {
|
|
29
36
|
public ready = false;
|
|
30
37
|
private readonly devices: Device[] = [];
|
|
31
|
-
private readonly
|
|
38
|
+
private readonly atRestAesKey: Uint8Array;
|
|
32
39
|
private messages: Message[] = [];
|
|
33
40
|
private nextOtkIndex = 1;
|
|
34
41
|
private nextPreKeyIndex = 1;
|
|
@@ -36,13 +43,12 @@ export class MemoryStorage extends EventEmitter implements Storage {
|
|
|
36
43
|
private preKeys: any[] = [];
|
|
37
44
|
private sessions: SessionSQL[] = [];
|
|
38
45
|
|
|
39
|
-
constructor(
|
|
46
|
+
constructor(atRestAesKey: Uint8Array) {
|
|
40
47
|
super();
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
this.idKeys = idKeys;
|
|
48
|
+
if (atRestAesKey.length !== 32) {
|
|
49
|
+
throw new Error("MemoryStorage requires a 32-byte atRestAes key.");
|
|
50
|
+
}
|
|
51
|
+
this.atRestAesKey = atRestAesKey;
|
|
46
52
|
}
|
|
47
53
|
|
|
48
54
|
close(): Promise<void> {
|
|
@@ -84,49 +90,51 @@ export class MemoryStorage extends EventEmitter implements Storage {
|
|
|
84
90
|
);
|
|
85
91
|
}
|
|
86
92
|
|
|
87
|
-
getGroupHistory(channelID: string): Promise<Message[]> {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
.filter((m) => m.group === channelID)
|
|
91
|
-
.map((m) => this.decryptMessage(m)),
|
|
92
|
-
);
|
|
93
|
+
async getGroupHistory(channelID: string): Promise<Message[]> {
|
|
94
|
+
const rows = this.messages.filter((m) => m.group === channelID);
|
|
95
|
+
return Promise.all(rows.map((m) => this.decryptMessage(m)));
|
|
93
96
|
}
|
|
94
97
|
|
|
95
|
-
getMessageHistory(userID: string): Promise<Message[]> {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
m.readerID === userID &&
|
|
105
|
-
!m.group),
|
|
106
|
-
)
|
|
107
|
-
.map((m) => this.decryptMessage(m)),
|
|
98
|
+
async getMessageHistory(userID: string): Promise<Message[]> {
|
|
99
|
+
const rows = this.messages.filter(
|
|
100
|
+
(m) =>
|
|
101
|
+
(m.direction === "incoming" &&
|
|
102
|
+
m.authorID === userID &&
|
|
103
|
+
!m.group) ||
|
|
104
|
+
(m.direction === "outgoing" &&
|
|
105
|
+
m.readerID === userID &&
|
|
106
|
+
!m.group),
|
|
108
107
|
);
|
|
108
|
+
return Promise.all(rows.map((m) => this.decryptMessage(m)));
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
getOneTimeKey(index: number): Promise<null | PreKeysCrypto> {
|
|
111
|
+
async getOneTimeKey(index: number): Promise<null | PreKeysCrypto> {
|
|
112
112
|
const otk = this.oneTimeKeys.find((k) => k.index === index);
|
|
113
113
|
if (!otk || !otk.privateKey) return Promise.resolve(null);
|
|
114
|
-
|
|
114
|
+
const sk = XUtils.decodeHex(otk.privateKey);
|
|
115
|
+
return {
|
|
115
116
|
index: otk.index,
|
|
116
|
-
keyPair:
|
|
117
|
+
keyPair:
|
|
118
|
+
getCryptoProfile() === "fips"
|
|
119
|
+
? await xBoxKeyPairFromSecretAsync(sk)
|
|
120
|
+
: xBoxKeyPairFromSecret(sk),
|
|
117
121
|
signature: XUtils.decodeHex(otk.signature),
|
|
118
|
-
}
|
|
122
|
+
};
|
|
119
123
|
}
|
|
120
124
|
|
|
121
|
-
getPreKeys(): Promise<null | PreKeysCrypto> {
|
|
125
|
+
async getPreKeys(): Promise<null | PreKeysCrypto> {
|
|
122
126
|
if (this.preKeys.length === 0) return Promise.resolve(null);
|
|
123
127
|
const pk = this.preKeys[0];
|
|
124
128
|
if (!pk.privateKey) return Promise.resolve(null);
|
|
125
|
-
|
|
129
|
+
const sk = XUtils.decodeHex(pk.privateKey);
|
|
130
|
+
return {
|
|
126
131
|
index: pk.index,
|
|
127
|
-
keyPair:
|
|
132
|
+
keyPair:
|
|
133
|
+
getCryptoProfile() === "fips"
|
|
134
|
+
? await xBoxKeyPairFromSecretAsync(sk)
|
|
135
|
+
: xBoxKeyPairFromSecret(sk),
|
|
128
136
|
signature: XUtils.decodeHex(pk.signature),
|
|
129
|
-
}
|
|
137
|
+
};
|
|
130
138
|
}
|
|
131
139
|
|
|
132
140
|
getSessionByDeviceID(deviceID: string): Promise<null | SessionCrypto> {
|
|
@@ -182,17 +190,22 @@ export class MemoryStorage extends EventEmitter implements Storage {
|
|
|
182
190
|
return Promise.resolve();
|
|
183
191
|
}
|
|
184
192
|
|
|
185
|
-
saveMessage(message: Message): Promise<void> {
|
|
193
|
+
async saveMessage(message: Message): Promise<void> {
|
|
186
194
|
const copy = { ...message };
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
195
|
+
const fips = getCryptoProfile() === "fips";
|
|
196
|
+
const ct = fips
|
|
197
|
+
? await xSecretboxAsync(
|
|
198
|
+
XUtils.decodeUTF8(message.message),
|
|
199
|
+
XUtils.decodeHex(message.nonce),
|
|
200
|
+
this.atRestAesKey,
|
|
201
|
+
)
|
|
202
|
+
: xSecretbox(
|
|
203
|
+
XUtils.decodeUTF8(message.message),
|
|
204
|
+
XUtils.decodeHex(message.nonce),
|
|
205
|
+
this.atRestAesKey,
|
|
206
|
+
);
|
|
207
|
+
copy.message = XUtils.encodeHex(ct);
|
|
194
208
|
this.messages.push(copy);
|
|
195
|
-
return Promise.resolve();
|
|
196
209
|
}
|
|
197
210
|
|
|
198
211
|
savePreKeys(
|
|
@@ -227,14 +240,21 @@ export class MemoryStorage extends EventEmitter implements Storage {
|
|
|
227
240
|
return Promise.resolve();
|
|
228
241
|
}
|
|
229
242
|
|
|
230
|
-
private decryptMessage(msg: Message): Message {
|
|
243
|
+
private async decryptMessage(msg: Message): Promise<Message> {
|
|
231
244
|
const copy = { ...msg };
|
|
232
245
|
if (copy.decrypted) {
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
246
|
+
const fips = getCryptoProfile() === "fips";
|
|
247
|
+
const dec = fips
|
|
248
|
+
? await xSecretboxOpenAsync(
|
|
249
|
+
XUtils.decodeHex(copy.message),
|
|
250
|
+
XUtils.decodeHex(copy.nonce),
|
|
251
|
+
this.atRestAesKey,
|
|
252
|
+
)
|
|
253
|
+
: xSecretboxOpen(
|
|
254
|
+
XUtils.decodeHex(copy.message),
|
|
255
|
+
XUtils.decodeHex(copy.nonce),
|
|
256
|
+
this.atRestAesKey,
|
|
257
|
+
);
|
|
238
258
|
if (dec) copy.message = XUtils.encodeUTF8(dec);
|
|
239
259
|
}
|
|
240
260
|
return copy;
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2020-2026 Vex Heavy Industries LLC
|
|
3
|
+
* Licensed under AGPL-3.0. See LICENSE for details.
|
|
4
|
+
* Commercial licenses available at vex.wtf
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
/**
|
|
2
8
|
* Shared test transport utilities — kept as a module boundary for
|
|
3
9
|
* platform-specific test setup.
|