core-3nweb-client-lib 0.49.6 → 0.49.8
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/build/api-defs/asmail.d.ts +1 -0
- package/build/api-defs/files.d.ts +11 -5
- package/build/core/asmail/delivery/common.d.ts +8 -28
- package/build/core/asmail/delivery/common.js +1 -47
- package/build/core/asmail/delivery/index.js +3 -3
- package/build/core/asmail/delivery/per-recipient-wip.js +3 -2
- package/build/core/asmail/inbox/index.d.ts +8 -32
- package/build/core/asmail/inbox/index.js +120 -170
- package/build/core/asmail/inbox/msg-indexing/dataset/v0/sql-db-v-none.d.ts +11 -0
- package/build/{lib-client/xsp-fs/util/for-arrays.js → core/asmail/inbox/msg-indexing/dataset/v0/sql-db-v-none.js} +7 -13
- package/build/core/asmail/inbox/msg-indexing/dataset/v1/logs.d.ts +33 -0
- package/build/core/asmail/inbox/msg-indexing/dataset/v1/logs.js +72 -0
- package/build/core/asmail/inbox/msg-indexing/dataset/v1/sql-db.d.ts +28 -0
- package/build/core/asmail/inbox/msg-indexing/dataset/v1/sql-db.js +477 -0
- package/build/core/asmail/inbox/msg-indexing/index.d.ts +12 -26
- package/build/core/asmail/inbox/msg-indexing/index.js +47 -68
- package/build/core/asmail/inbox/msg-on-disk.d.ts +0 -5
- package/build/core/asmail/inbox/msg-on-disk.js +2 -24
- package/build/core/asmail/index.js +8 -7
- package/build/core/asmail/msg/common.d.ts +0 -1
- package/build/core/asmail/msg/common.js +1 -1
- package/build/core/index.js +7 -4
- package/build/core/keyring/common.d.ts +1 -0
- package/build/core/keyring/common.js +2 -1
- package/build/core/keyring/index.d.ts +7 -44
- package/build/core/keyring/index.js +88 -222
- package/build/core/keyring/introductory-keys/published-intro-key.d.ts +17 -0
- package/build/core/keyring/introductory-keys/published-intro-key.js +190 -0
- package/build/core/keyring/peer-keys/dataset/v1/json-files.d.ts +105 -0
- package/build/core/keyring/peer-keys/dataset/v1/json-files.js +89 -0
- package/build/core/keyring/peer-keys/dataset/v2/logs.d.ts +43 -0
- package/build/core/keyring/peer-keys/dataset/v2/logs.js +116 -0
- package/build/core/keyring/peer-keys/dataset/v2/peer-keys-db.d.ts +73 -0
- package/build/core/keyring/peer-keys/dataset/v2/peer-keys-db.js +543 -0
- package/build/core/keyring/peer-keys/index.d.ts +24 -0
- package/build/core/keyring/peer-keys/index.js +208 -0
- package/build/core/storage/synced/obj-files.js +10 -3
- package/build/core/storage/synced/obj-status.d.ts +1 -1
- package/build/core/storage/synced/obj-status.js +8 -2
- package/build/core/storage/synced/storage.d.ts +4 -4
- package/build/core/storage/system-folders/apps-data.d.ts +0 -1
- package/build/core/storage/system-folders/apps-data.js +2 -6
- package/build/lib-client/asmail/recipient.d.ts +1 -0
- package/build/lib-client/asmail/recipient.js +11 -0
- package/build/lib-client/fs-utils/fs-sync-utils.d.ts +1 -1
- package/build/lib-client/fs-utils/fs-sync-utils.js +70 -13
- package/build/lib-client/xsp-fs/folder-node.js +13 -3
- package/build/lib-client/xsp-fs/fs.js +3 -1
- package/build/lib-client/xsp-fs/node-in-fs.d.ts +1 -0
- package/build/lib-client/xsp-fs/node-in-fs.js +7 -2
- package/build/lib-client/xsp-fs/node-persistence.js +1 -3
- package/build/lib-client/xsp-fs/xsp-payload-v2.js +1 -2
- package/build/lib-common/dataset-sync/per-device-json-array-logs.d.ts +58 -0
- package/build/lib-common/dataset-sync/per-device-json-array-logs.js +432 -0
- package/build/lib-common/dataset-sync/single-file.d.ts +10 -0
- package/build/lib-common/dataset-sync/single-file.js +77 -0
- package/build/lib-common/number-line.d.ts +10 -0
- package/build/lib-common/number-line.js +66 -0
- package/build/lib-common/objs-on-disk/obj-version-file.d.ts +1 -1
- package/build/lib-common/objs-on-disk/obj-version-file.js +3 -3
- package/build/lib-common/rng-def.d.ts +1 -0
- package/build/lib-common/rng-def.js +8 -0
- package/build/lib-sqlite-on-3nstorage/for-sqlite.d.ts +38 -0
- package/build/lib-sqlite-on-3nstorage/for-sqlite.js +162 -0
- package/build/lib-sqlite-on-3nstorage/index.d.ts +18 -5
- package/build/lib-sqlite-on-3nstorage/index.js +49 -26
- package/build/tests/caps-api/file-sink-checks/splice.js +72 -1
- package/build/tests/caps-api/fs-checks/sync-on-one-dev/upload.js +27 -1
- package/build/tests/caps-api/fs-checks/sync-with-two-devs/update-propagation.js +12 -3
- package/build/tests/computer.3nweb.core/inbox/msg-indexing.js +16 -12
- package/build/tests/computer.3nweb.core/keyrings.js +113 -28
- package/build/tests/jasmine.js +2 -2
- package/build/tests/units/number-line.js +9 -9
- package/package.json +2 -1
- package/build/core/asmail/inbox/msg-indexing/logs-n-entries.d.ts +0 -52
- package/build/core/asmail/inbox/msg-indexing/logs-n-entries.js +0 -333
- package/build/core/asmail/inbox/msg-indexing/sql-indexing.d.ts +0 -4
- package/build/core/asmail/inbox/msg-indexing/sql-indexing.js +0 -319
- package/build/core/keyring/correspondent-keys.d.ts +0 -149
- package/build/core/keyring/correspondent-keys.js +0 -403
- package/build/core/keyring/id-to-email-map.d.ts +0 -38
- package/build/core/keyring/id-to-email-map.js +0 -105
- package/build/core/keyring/keyring-storage.d.ts +0 -9
- package/build/core/keyring/keyring-storage.js +0 -54
- package/build/core/keyring/published-intro-key.d.ts +0 -45
- package/build/core/keyring/published-intro-key.js +0 -200
- package/build/lib-client/xsp-fs/util/for-arrays.d.ts +0 -1
|
@@ -1,403 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
Copyright (C) 2015 - 2018, 2022, 2026 3NSoft Inc.
|
|
4
|
-
|
|
5
|
-
This program is free software: you can redistribute it and/or modify it under
|
|
6
|
-
the terms of the GNU General Public License as published by the Free Software
|
|
7
|
-
Foundation, either version 3 of the License, or (at your option) any later
|
|
8
|
-
version.
|
|
9
|
-
|
|
10
|
-
This program is distributed in the hope that it will be useful, but
|
|
11
|
-
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
13
|
-
See the GNU General Public License for more details.
|
|
14
|
-
|
|
15
|
-
You should have received a copy of the GNU General Public License along with
|
|
16
|
-
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
-
*/
|
|
18
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.CorrespondentKeys = void 0;
|
|
20
|
-
exports.msgMasterDecryptor = msgMasterDecryptor;
|
|
21
|
-
/**
|
|
22
|
-
* This file contains functionality, used inside keyring.
|
|
23
|
-
*/
|
|
24
|
-
const common_1 = require("./common");
|
|
25
|
-
const ecma_nacl_1 = require("ecma-nacl");
|
|
26
|
-
const buffer_utils_1 = require("../../lib-common/buffer-utils");
|
|
27
|
-
const error_1 = require("../../lib-common/exceptions/error");
|
|
28
|
-
const async_cryptor_wrap_1 = require("../../lib-common/async-cryptor-wrap");
|
|
29
|
-
const cryptor_work_labels_1 = require("../../lib-client/cryptor-work-labels");
|
|
30
|
-
const rng_def_1 = require("../../lib-common/rng-def");
|
|
31
|
-
async function generatePids(random) {
|
|
32
|
-
const pids = [];
|
|
33
|
-
for (let i = 0; i < 5; i += 1) {
|
|
34
|
-
pids[i] = await (0, rng_def_1.stringOfB64UrlSafeChars)(common_1.PID_LENGTH, random);
|
|
35
|
-
}
|
|
36
|
-
return pids;
|
|
37
|
-
}
|
|
38
|
-
function msgMasterDecryptor(cryptor, skey, pkey) {
|
|
39
|
-
const msgMasterKey = calcMsgMasterKey(skey, pkey);
|
|
40
|
-
const workLabel = cryptor_work_labels_1.cryptoWorkLabels.makeRandom('asmail');
|
|
41
|
-
const masterDecr = (0, async_cryptor_wrap_1.makeDecryptor)(cryptor, workLabel, msgMasterKey);
|
|
42
|
-
msgMasterKey.fill(0);
|
|
43
|
-
return masterDecr;
|
|
44
|
-
}
|
|
45
|
-
function calcMsgMasterKey(skey, pkey) {
|
|
46
|
-
if (skey.alg === ecma_nacl_1.box.JWK_ALG_NAME) {
|
|
47
|
-
const sk = (0, common_1.extractSKeyBytes)(skey);
|
|
48
|
-
const pk = (0, common_1.extractKeyBytes)(pkey);
|
|
49
|
-
const dhShared = ecma_nacl_1.box.calc_dhshared_key(pk, sk);
|
|
50
|
-
sk.fill(0);
|
|
51
|
-
pk.fill(0);
|
|
52
|
-
return dhShared;
|
|
53
|
-
}
|
|
54
|
-
throw new Error(`Unsupported algorithm ${skey.alg}`);
|
|
55
|
-
}
|
|
56
|
-
function calcMsgMasterKeyB64(skey, pkey) {
|
|
57
|
-
return buffer_utils_1.base64.pack(calcMsgMasterKey(skey, pkey));
|
|
58
|
-
}
|
|
59
|
-
const MIN_PERIOD_FOR_PAIR = 15 * 60 * 1000;
|
|
60
|
-
class CorrespondentKeys {
|
|
61
|
-
get correspondent() {
|
|
62
|
-
return this.keys.correspondent;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* @param keyring in which these keys are hanging.
|
|
66
|
-
* @param address of this correspondent.
|
|
67
|
-
* Either serialData, or an address should be defined, not both.
|
|
68
|
-
* @param serialData from which this object should be reconstructed.
|
|
69
|
-
* Either serialData, or an address should be defined, not both.
|
|
70
|
-
*/
|
|
71
|
-
constructor(keyring, random, address, serialData) {
|
|
72
|
-
this.keyring = keyring;
|
|
73
|
-
this.random = random;
|
|
74
|
-
this.keys = undefined;
|
|
75
|
-
if (address) {
|
|
76
|
-
this.keys = {
|
|
77
|
-
correspondent: address,
|
|
78
|
-
sendingPair: null,
|
|
79
|
-
receptionPairs: {
|
|
80
|
-
suggested: null,
|
|
81
|
-
inUse: null,
|
|
82
|
-
old: null
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
const data = JSON.parse(serialData);
|
|
88
|
-
// TODO checks of deserialized json data
|
|
89
|
-
this.keys = data;
|
|
90
|
-
}
|
|
91
|
-
Object.seal(this);
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* This attaches all keys into ring's maps.
|
|
95
|
-
* Theis method should be called only once, and only on a deserialized
|
|
96
|
-
* object.
|
|
97
|
-
*/
|
|
98
|
-
mapAllKeysIntoRing() {
|
|
99
|
-
// index key pairs
|
|
100
|
-
const pairs = [
|
|
101
|
-
this.keys.receptionPairs.suggested,
|
|
102
|
-
this.keys.receptionPairs.inUse,
|
|
103
|
-
this.keys.receptionPairs.old
|
|
104
|
-
];
|
|
105
|
-
const email = this.correspondent;
|
|
106
|
-
pairs.forEach(pair => {
|
|
107
|
-
if (!pair) {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
pair.pids.forEach(pid => this.keyring.pairIdToEmailMap.addPair(pid, email));
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* @return json object for serialization.
|
|
115
|
-
*/
|
|
116
|
-
serialForm() {
|
|
117
|
-
return JSON.stringify(this.keys);
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* This function generates new suggested reception pair, but only if there
|
|
121
|
-
* is currently none.
|
|
122
|
-
* If there is previous suggested pair, it shall be returned.
|
|
123
|
-
*/
|
|
124
|
-
async suggestPair() {
|
|
125
|
-
// reuse previously suggested pair
|
|
126
|
-
if (this.keys.receptionPairs.suggested) {
|
|
127
|
-
return toSuggestedPair(this.keys.receptionPairs.suggested);
|
|
128
|
-
}
|
|
129
|
-
if (!this.shouldSuggestNewPair()) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
// generate new suggested pair
|
|
133
|
-
const corrPKey = this.keys.sendingPair.recipientPKey;
|
|
134
|
-
const isSenderIntroKey = (this.keys.sendingPair.type === 'intro');
|
|
135
|
-
const recipientKey = await (0, common_1.generateKeyPair)(this.random);
|
|
136
|
-
const msgMasterKey = calcMsgMasterKeyB64(recipientKey.skey, corrPKey);
|
|
137
|
-
const pair = {
|
|
138
|
-
pids: await generatePids(this.random),
|
|
139
|
-
recipientKey,
|
|
140
|
-
senderPKey: corrPKey,
|
|
141
|
-
isSenderIntroKey,
|
|
142
|
-
msgMasterKey,
|
|
143
|
-
timestamp: Date.now()
|
|
144
|
-
};
|
|
145
|
-
this.keys.receptionPairs.suggested = pair;
|
|
146
|
-
// add pair to index
|
|
147
|
-
this.keyring.pairIdToEmailMap.addPairs(pair.pids, this.correspondent);
|
|
148
|
-
this.keyring.saveChanges();
|
|
149
|
-
return toSuggestedPair(this.keys.receptionPairs.suggested);
|
|
150
|
-
}
|
|
151
|
-
shouldSuggestNewPair() {
|
|
152
|
-
if (!this.keys.sendingPair) {
|
|
153
|
-
throw new Error("Sending pair should be set before calling this function.");
|
|
154
|
-
}
|
|
155
|
-
if (this.keys.sendingPair.type === 'intro') {
|
|
156
|
-
return true;
|
|
157
|
-
}
|
|
158
|
-
if (!this.keys.sendingPair.sentMsgs) {
|
|
159
|
-
return false;
|
|
160
|
-
}
|
|
161
|
-
const now = Date.now();
|
|
162
|
-
if ((this.keys.sendingPair.timestamp + MIN_PERIOD_FOR_PAIR) > now) {
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
165
|
-
return true;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* This marks suggested reception pair as being in use.
|
|
169
|
-
* Suggested pair is moved into category in-use, while in-use pair is
|
|
170
|
-
* reclassified as old.
|
|
171
|
-
* @param pair
|
|
172
|
-
*/
|
|
173
|
-
markPairAsInUse(pair) {
|
|
174
|
-
if (this.keys.receptionPairs.suggested !== pair) {
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
const mp = this.keys.receptionPairs.inUse;
|
|
178
|
-
this.keys.receptionPairs.inUse = this.keys.receptionPairs.suggested;
|
|
179
|
-
this.keys.receptionPairs.suggested = null;
|
|
180
|
-
if (mp) {
|
|
181
|
-
const dp = this.keys.receptionPairs.old;
|
|
182
|
-
this.keys.receptionPairs.old = mp;
|
|
183
|
-
if (dp) {
|
|
184
|
-
this.tryToRemovePIDsFromIndex(dp.pids);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
tryToRemovePIDsFromIndex(pids) {
|
|
189
|
-
const pidSet = new Set(pids);
|
|
190
|
-
for (const pair of Object.values(this.keys.receptionPairs)) {
|
|
191
|
-
if (!pair) {
|
|
192
|
-
continue;
|
|
193
|
-
}
|
|
194
|
-
pair.pids.forEach(pid => pidSet.delete(pid));
|
|
195
|
-
}
|
|
196
|
-
for (const pid of pidSet) {
|
|
197
|
-
this.keyring.pairIdToEmailMap.removePair(pid, this.correspondent);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* This function is used internally in this.setSendingPair(p) function.
|
|
202
|
-
* @param kid
|
|
203
|
-
* @return a key for receiving, corresponding to given key id.
|
|
204
|
-
*/
|
|
205
|
-
findReceptionKey(kid) {
|
|
206
|
-
for (const fieldName of Object.keys(this.keys.receptionPairs)) {
|
|
207
|
-
const rp = this.keys.receptionPairs[fieldName];
|
|
208
|
-
if (!rp) {
|
|
209
|
-
continue;
|
|
210
|
-
}
|
|
211
|
-
if (rp.recipientKey.skey.kid === kid) {
|
|
212
|
-
return rp.recipientKey;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
const err = new Error("Key cannot be found");
|
|
216
|
-
err.unknownKid = true;
|
|
217
|
-
throw err;
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* This checks given pair and sets a new sending pair.
|
|
221
|
-
* @param pair
|
|
222
|
-
* @param usedPublishedIntro
|
|
223
|
-
*/
|
|
224
|
-
ratchetUpSendingPair(pair, usedPublishedIntro) {
|
|
225
|
-
if (this.keys.sendingPair) {
|
|
226
|
-
const existingPair = this.keys.sendingPair;
|
|
227
|
-
if (existingPair.type === 'ratcheted') {
|
|
228
|
-
if ((existingPair.recipientPKey.k === pair.recipientPKey.k)
|
|
229
|
-
&& (existingPair.senderKey.pkey.kid === pair.senderKid)) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
if (existingPair.timestamp > pair.timestamp) {
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
let senderKey;
|
|
238
|
-
if (pair.isSenderIntroKey) {
|
|
239
|
-
if (!usedPublishedIntro) {
|
|
240
|
-
throw new Error(`Missing a published intro key, referenced in the pair`);
|
|
241
|
-
}
|
|
242
|
-
senderKey = usedPublishedIntro;
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
senderKey = this.findReceptionKey(pair.senderKid);
|
|
246
|
-
}
|
|
247
|
-
try {
|
|
248
|
-
const msgMasterKey = calcMsgMasterKeyB64(senderKey.skey, pair.recipientPKey);
|
|
249
|
-
this.keys.sendingPair = {
|
|
250
|
-
type: 'ratcheted',
|
|
251
|
-
pids: pair.pids,
|
|
252
|
-
recipientPKey: pair.recipientPKey,
|
|
253
|
-
senderKey: senderKey,
|
|
254
|
-
msgMasterKey,
|
|
255
|
-
timestamp: pair.timestamp
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
catch (err) {
|
|
259
|
-
throw (0, error_1.errWithCause)(err, "Public key in a given pair cannot be used");
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* @param pid
|
|
264
|
-
* @return pair for receiving messages and a role of a given pair.
|
|
265
|
-
* Undefined is returned when no pair were found.
|
|
266
|
-
*/
|
|
267
|
-
getReceivingPair(pid) {
|
|
268
|
-
const pairs = this.keys.receptionPairs;
|
|
269
|
-
if (pairs.suggested && (pairs.suggested.pids.indexOf(pid) >= 0)) {
|
|
270
|
-
return {
|
|
271
|
-
pair: pairs.suggested,
|
|
272
|
-
role: 'suggested'
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
else if (pairs.inUse && (pairs.inUse.pids.indexOf(pid) >= 0)) {
|
|
276
|
-
return {
|
|
277
|
-
pair: pairs.inUse,
|
|
278
|
-
role: 'in_use'
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
else if (pairs.old && (pairs.old.pids.indexOf(pid) >= 0)) {
|
|
282
|
-
return {
|
|
283
|
-
pair: pairs.old,
|
|
284
|
-
role: 'old'
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
return; // explicit return of undefined
|
|
288
|
-
}
|
|
289
|
-
async getSendingPair(recipientIntroPKey) {
|
|
290
|
-
if (!this.keys.sendingPair) {
|
|
291
|
-
if (!recipientIntroPKey) {
|
|
292
|
-
throw new Error(`Sending pair for ${this.correspondent} is not set.`);
|
|
293
|
-
}
|
|
294
|
-
this.keys.sendingPair = {
|
|
295
|
-
type: 'intro',
|
|
296
|
-
recipientPKey: recipientIntroPKey
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
const p = this.keys.sendingPair;
|
|
300
|
-
let currentPair;
|
|
301
|
-
let msgMasterKey;
|
|
302
|
-
let msgCount;
|
|
303
|
-
if (p.type === 'intro') {
|
|
304
|
-
const senderKey = await (0, common_1.generateKeyPair)(this.random);
|
|
305
|
-
msgMasterKey = calcMsgMasterKey(senderKey.skey, p.recipientPKey);
|
|
306
|
-
currentPair = {
|
|
307
|
-
senderPKey: senderKey.pkey,
|
|
308
|
-
recipientKid: p.recipientPKey.kid
|
|
309
|
-
};
|
|
310
|
-
msgCount = 1;
|
|
311
|
-
}
|
|
312
|
-
else {
|
|
313
|
-
msgMasterKey = buffer_utils_1.base64.open(p.msgMasterKey);
|
|
314
|
-
msgCount = updateMsgCountInRatchetedSendingPair(p);
|
|
315
|
-
currentPair = { pid: selectPid(p) };
|
|
316
|
-
}
|
|
317
|
-
return { msgMasterKey, msgCount, currentPair };
|
|
318
|
-
}
|
|
319
|
-
toInfo() {
|
|
320
|
-
const { sendingPair: sp, receptionPairs: rp } = this.keys;
|
|
321
|
-
return {
|
|
322
|
-
sendingPair: (sp ? turnSendingPairToInfo(sp) : null),
|
|
323
|
-
receptionPairs: {
|
|
324
|
-
inUse: (rp.inUse ? turnReceptionPairToInfo(rp.inUse) : null),
|
|
325
|
-
old: (rp.old ? turnReceptionPairToInfo(rp.old) : null),
|
|
326
|
-
suggested: (rp.suggested ? turnReceptionPairToInfo(rp.suggested) : null)
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
exports.CorrespondentKeys = CorrespondentKeys;
|
|
332
|
-
Object.freeze(CorrespondentKeys.prototype);
|
|
333
|
-
Object.freeze(CorrespondentKeys);
|
|
334
|
-
function toSuggestedPair(pair) {
|
|
335
|
-
const nextKeyPair = {
|
|
336
|
-
pids: pair.pids,
|
|
337
|
-
senderKid: pair.senderPKey.kid,
|
|
338
|
-
recipientPKey: pair.recipientKey.pkey,
|
|
339
|
-
isSenderIntroKey: pair.isSenderIntroKey,
|
|
340
|
-
timestamp: pair.timestamp
|
|
341
|
-
};
|
|
342
|
-
return nextKeyPair;
|
|
343
|
-
}
|
|
344
|
-
function selectPid(pair) {
|
|
345
|
-
if (pair.pids.length < 1) {
|
|
346
|
-
throw new Error("There are no pair ids in array.");
|
|
347
|
-
}
|
|
348
|
-
const i = Math.round((pair.pids.length - 1) * Math.random());
|
|
349
|
-
return pair.pids[i];
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* This function updates message count and a timestamp in a given sending pair,
|
|
353
|
-
* returning a message count to use for sending a new message.
|
|
354
|
-
* @param p is a sending pair, in which changes should be done.
|
|
355
|
-
*/
|
|
356
|
-
function updateMsgCountInRatchetedSendingPair(p) {
|
|
357
|
-
const lastTS = Date.now();
|
|
358
|
-
if (p.sentMsgs) {
|
|
359
|
-
p.sentMsgs.count += 1;
|
|
360
|
-
p.sentMsgs.lastTS = lastTS;
|
|
361
|
-
}
|
|
362
|
-
else {
|
|
363
|
-
p.sentMsgs = {
|
|
364
|
-
count: 1,
|
|
365
|
-
lastTS
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
return p.sentMsgs.count;
|
|
369
|
-
}
|
|
370
|
-
function turnSendingPairToInfo(sp) {
|
|
371
|
-
if (sp.type === 'ratcheted') {
|
|
372
|
-
const { pids, timestamp, sentMsgs } = sp;
|
|
373
|
-
return {
|
|
374
|
-
type: 'ratcheted',
|
|
375
|
-
recipientKId: sp.recipientPKey.kid,
|
|
376
|
-
senderKId: sp.senderKey.pkey.kid,
|
|
377
|
-
alg: sp.senderKey.pkey.alg,
|
|
378
|
-
pids,
|
|
379
|
-
timestamp,
|
|
380
|
-
sentMsgs
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
else if (sp.type === 'intro') {
|
|
384
|
-
return {
|
|
385
|
-
type: 'intro',
|
|
386
|
-
recipientKId: sp.recipientPKey.kid,
|
|
387
|
-
alg: sp.recipientPKey.alg
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
else {
|
|
391
|
-
return null;
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
function turnReceptionPairToInfo(rp) {
|
|
395
|
-
const { pids, timestamp, receivedMsgs, isSenderIntroKey } = rp;
|
|
396
|
-
return {
|
|
397
|
-
pids, timestamp, receivedMsgs, isSenderIntroKey,
|
|
398
|
-
alg: rp.recipientKey.pkey.alg,
|
|
399
|
-
recipientKId: rp.recipientKey.pkey.kid,
|
|
400
|
-
senderKId: rp.senderPKey.kid
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
Object.freeze(exports);
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file contains functionality, used inside keyring.
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* This is a one-to-many, one way map from string ids to string emails in a
|
|
6
|
-
* canonical form.
|
|
7
|
-
*/
|
|
8
|
-
export declare class IdToEmailMap {
|
|
9
|
-
private idToEmail;
|
|
10
|
-
constructor();
|
|
11
|
-
/**
|
|
12
|
-
* @param id
|
|
13
|
-
* @return undefined, if id is not known, or string with email, if there is
|
|
14
|
-
* one email registered for a given id, or an array of string emails, if
|
|
15
|
-
* more than one email registered for a given id.
|
|
16
|
-
*/
|
|
17
|
-
getEmails(id: string): string[] | undefined;
|
|
18
|
-
/**
|
|
19
|
-
* @param id
|
|
20
|
-
* @param email
|
|
21
|
-
* @return true, if given id-email pair is successfully registered,
|
|
22
|
-
* and false, if such registration already existed.
|
|
23
|
-
*/
|
|
24
|
-
addPair(id: string, email: string): boolean;
|
|
25
|
-
/**
|
|
26
|
-
* @param ids is an array of string ids, associated with a given email
|
|
27
|
-
* @param email
|
|
28
|
-
*/
|
|
29
|
-
addPairs(ids: string[], email: string): void;
|
|
30
|
-
/**
|
|
31
|
-
* This removes given id-email pair.
|
|
32
|
-
* @param id
|
|
33
|
-
* @param email
|
|
34
|
-
* @return true, if pair was found and removed, and false, otherwise.
|
|
35
|
-
*/
|
|
36
|
-
removePair(id: string, email: string): boolean;
|
|
37
|
-
removePairs(ids: string[], email: string): void;
|
|
38
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
Copyright (C) 2015 3NSoft Inc.
|
|
4
|
-
|
|
5
|
-
This program is free software: you can redistribute it and/or modify it under
|
|
6
|
-
the terms of the GNU General Public License as published by the Free Software
|
|
7
|
-
Foundation, either version 3 of the License, or (at your option) any later
|
|
8
|
-
version.
|
|
9
|
-
|
|
10
|
-
This program is distributed in the hope that it will be useful, but
|
|
11
|
-
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
13
|
-
See the GNU General Public License for more details.
|
|
14
|
-
|
|
15
|
-
You should have received a copy of the GNU General Public License along with
|
|
16
|
-
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
-
*/
|
|
18
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.IdToEmailMap = void 0;
|
|
20
|
-
/**
|
|
21
|
-
* This file contains functionality, used inside keyring.
|
|
22
|
-
*/
|
|
23
|
-
/**
|
|
24
|
-
* This is a one-to-many, one way map from string ids to string emails in a
|
|
25
|
-
* canonical form.
|
|
26
|
-
*/
|
|
27
|
-
class IdToEmailMap {
|
|
28
|
-
constructor() {
|
|
29
|
-
this.idToEmail = new Map();
|
|
30
|
-
Object.seal(this);
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* @param id
|
|
34
|
-
* @return undefined, if id is not known, or string with email, if there is
|
|
35
|
-
* one email registered for a given id, or an array of string emails, if
|
|
36
|
-
* more than one email registered for a given id.
|
|
37
|
-
*/
|
|
38
|
-
getEmails(id) {
|
|
39
|
-
const emails = this.idToEmail.get(id);
|
|
40
|
-
if (emails) {
|
|
41
|
-
return emails.concat([]);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
return;
|
|
45
|
-
} // undefined in explicit statement
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* @param id
|
|
49
|
-
* @param email
|
|
50
|
-
* @return true, if given id-email pair is successfully registered,
|
|
51
|
-
* and false, if such registration already existed.
|
|
52
|
-
*/
|
|
53
|
-
addPair(id, email) {
|
|
54
|
-
const emails = this.idToEmail.get(id);
|
|
55
|
-
if (emails) {
|
|
56
|
-
if (emails.includes(email)) {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
emails.push(email);
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
this.idToEmail.set(id, [email]);
|
|
63
|
-
}
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* @param ids is an array of string ids, associated with a given email
|
|
68
|
-
* @param email
|
|
69
|
-
*/
|
|
70
|
-
addPairs(ids, email) {
|
|
71
|
-
for (let i = 0; i < ids.length; i += 1) {
|
|
72
|
-
this.addPair(ids[i], email);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* This removes given id-email pair.
|
|
77
|
-
* @param id
|
|
78
|
-
* @param email
|
|
79
|
-
* @return true, if pair was found and removed, and false, otherwise.
|
|
80
|
-
*/
|
|
81
|
-
removePair(id, email) {
|
|
82
|
-
let emails = this.idToEmail.get(id);
|
|
83
|
-
if (!emails) {
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
const emailInd = emails.indexOf(email);
|
|
87
|
-
if (emailInd < 0) {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
emails = emails.splice(emailInd, 1);
|
|
91
|
-
if (emails.length === 0) {
|
|
92
|
-
this.idToEmail.delete(id);
|
|
93
|
-
}
|
|
94
|
-
return true;
|
|
95
|
-
}
|
|
96
|
-
removePairs(ids, email) {
|
|
97
|
-
for (let i = 0; i < ids.length; i += 1) {
|
|
98
|
-
this.removePair(ids[i], email);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
exports.IdToEmailMap = IdToEmailMap;
|
|
103
|
-
Object.freeze(IdToEmailMap);
|
|
104
|
-
Object.freeze(IdToEmailMap.prototype);
|
|
105
|
-
Object.freeze(exports);
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
type WritableFS = web3n.files.WritableFS;
|
|
2
|
-
export interface KeyringStorage {
|
|
3
|
-
load(): Promise<string | undefined>;
|
|
4
|
-
save(serialForm: string): void;
|
|
5
|
-
start(): Promise<void>;
|
|
6
|
-
close(): Promise<void>;
|
|
7
|
-
}
|
|
8
|
-
export declare function makeKeyringStorage(fs: WritableFS): KeyringStorage;
|
|
9
|
-
export {};
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
Copyright (C) 2018 3NSoft Inc.
|
|
4
|
-
|
|
5
|
-
This program is free software: you can redistribute it and/or modify it under
|
|
6
|
-
the terms of the GNU General Public License as published by the Free Software
|
|
7
|
-
Foundation, either version 3 of the License, or (at your option) any later
|
|
8
|
-
version.
|
|
9
|
-
|
|
10
|
-
This program is distributed in the hope that it will be useful, but
|
|
11
|
-
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
13
|
-
See the GNU General Public License for more details.
|
|
14
|
-
|
|
15
|
-
You should have received a copy of the GNU General Public License along with
|
|
16
|
-
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
-
*/
|
|
18
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.makeKeyringStorage = makeKeyringStorage;
|
|
20
|
-
const synced_1 = require("../../lib-common/processes/synced");
|
|
21
|
-
const KEYRING_FNAME = 'keyring.json';
|
|
22
|
-
function makeKeyringStorage(fs) {
|
|
23
|
-
const proc = new synced_1.SingleProc();
|
|
24
|
-
// initialization for code that works only with version 1
|
|
25
|
-
proc.start(async () => {
|
|
26
|
-
fs = await checkAndUpgradeDataToV1(fs);
|
|
27
|
-
});
|
|
28
|
-
const storage = {
|
|
29
|
-
save: (serialForm) => proc.startOrChain(() => fs.writeTxtFile(KEYRING_FNAME, serialForm)),
|
|
30
|
-
close: () => fs.close(),
|
|
31
|
-
start: async () => {
|
|
32
|
-
// XXX start watching keyring file
|
|
33
|
-
},
|
|
34
|
-
load: () => proc.startOrChain(() => fs.readTxtFile(KEYRING_FNAME).catch(notFoundOrReThrow))
|
|
35
|
-
};
|
|
36
|
-
return Object.freeze(storage);
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* This is a catch callback, which returns undefined on file(folder) not found
|
|
40
|
-
* exception, and re-throws all other exceptions/errors.
|
|
41
|
-
*/
|
|
42
|
-
function notFoundOrReThrow(exc) {
|
|
43
|
-
if (!exc.notFound) {
|
|
44
|
-
throw exc;
|
|
45
|
-
}
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
const VERSION_1_FOLDER_NAME = 'v1';
|
|
49
|
-
async function checkAndUpgradeDataToV1(krFS) {
|
|
50
|
-
const v1FS = await krFS.writableSubRoot(VERSION_1_FOLDER_NAME);
|
|
51
|
-
// XXX can we have an upgrade from no version to version 1 ?
|
|
52
|
-
return v1FS;
|
|
53
|
-
}
|
|
54
|
-
Object.freeze(exports);
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { ParamOnServer } from '../../lib-client/asmail/service-config';
|
|
2
|
-
import { AsyncRNG } from '../../lib-common/rng-def';
|
|
3
|
-
import { GetSigner } from '../id-manager';
|
|
4
|
-
import { JWKeyPair, MsgKeyRole } from './common';
|
|
5
|
-
type WritableFile = web3n.files.WritableFile;
|
|
6
|
-
type IntroKeyCAP = web3n.keys.Keyrings['introKeyOnASMailServer'];
|
|
7
|
-
export declare class PublishedIntroKey {
|
|
8
|
-
private readonly getSigner;
|
|
9
|
-
private readonly random;
|
|
10
|
-
private pkeyOnServer;
|
|
11
|
-
private published;
|
|
12
|
-
private readonly fileProc;
|
|
13
|
-
private periodicExpiryCheck;
|
|
14
|
-
private constructor();
|
|
15
|
-
static makeAndInit(file: WritableFile, getSigner: GetSigner, random: AsyncRNG, pkeyOnServer: ParamOnServer<'init-pub-key'>): Promise<PublishedIntroKey>;
|
|
16
|
-
private startExpiryCheckProcess;
|
|
17
|
-
close(): Promise<void>;
|
|
18
|
-
private onFileEvent;
|
|
19
|
-
private setFromJSON;
|
|
20
|
-
private toFileJSON;
|
|
21
|
-
private absorbRemoteChanges;
|
|
22
|
-
private makeNewIntroKey;
|
|
23
|
-
private update;
|
|
24
|
-
private retireCurrent;
|
|
25
|
-
/**
|
|
26
|
-
* This looks for a published key with a given key id. If it is found, an
|
|
27
|
-
* object is returned with following fields:
|
|
28
|
-
* - pair is JWK key pair;
|
|
29
|
-
* - role of a found key pair;
|
|
30
|
-
* - replacedAt field is present for a previously published key pair,
|
|
31
|
-
* telling, in milliseconds, when this key was superseded a newer one.
|
|
32
|
-
* Undefined is returned, when a key is not found.
|
|
33
|
-
* @param kid
|
|
34
|
-
* @return if key is found, object with following fields is returned:
|
|
35
|
-
*/
|
|
36
|
-
find(kid: string): {
|
|
37
|
-
role: MsgKeyRole;
|
|
38
|
-
pair: JWKeyPair;
|
|
39
|
-
replacedAt?: number;
|
|
40
|
-
} | undefined;
|
|
41
|
-
makeIntroKeyCAP(): IntroKeyCAP;
|
|
42
|
-
private getCurrent;
|
|
43
|
-
private removeCurrent;
|
|
44
|
-
}
|
|
45
|
-
export {};
|