core-3nweb-client-lib 0.49.5 → 0.49.7

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.
Files changed (81) hide show
  1. package/build/api-defs/files.d.ts +11 -5
  2. package/build/core/asmail/delivery/common.d.ts +8 -28
  3. package/build/core/asmail/delivery/common.js +1 -47
  4. package/build/core/asmail/delivery/index.js +3 -8
  5. package/build/core/asmail/delivery/msg.js +1 -7
  6. package/build/core/asmail/delivery/per-recipient-wip.js +3 -29
  7. package/build/core/asmail/inbox/index.d.ts +1 -2
  8. package/build/core/asmail/inbox/index.js +14 -15
  9. package/build/core/asmail/inbox/msg-indexing/dataset/v0/sql-db-v-none.d.ts +11 -0
  10. package/build/core/asmail/inbox/msg-indexing/dataset/v0/sql-db-v-none.js +25 -0
  11. package/build/core/asmail/inbox/msg-indexing/dataset/v1/logs.d.ts +33 -0
  12. package/build/core/asmail/inbox/msg-indexing/dataset/v1/logs.js +72 -0
  13. package/build/core/asmail/inbox/msg-indexing/dataset/v1/sql-db.d.ts +28 -0
  14. package/build/core/asmail/inbox/msg-indexing/dataset/v1/sql-db.js +477 -0
  15. package/build/core/asmail/inbox/msg-indexing/index.d.ts +12 -26
  16. package/build/core/asmail/inbox/msg-indexing/index.js +47 -68
  17. package/build/core/asmail/inbox/msg-on-disk.js +1 -2
  18. package/build/core/asmail/index.js +8 -7
  19. package/build/core/asmail/msg/common.d.ts +0 -1
  20. package/build/core/asmail/msg/common.js +1 -1
  21. package/build/core/asmail/msg/packer.js +1 -3
  22. package/build/core/index.js +7 -4
  23. package/build/core/keyring/common.d.ts +1 -0
  24. package/build/core/keyring/common.js +2 -1
  25. package/build/core/keyring/index.d.ts +7 -44
  26. package/build/core/keyring/index.js +89 -222
  27. package/build/core/keyring/introductory-keys/published-intro-key.d.ts +17 -0
  28. package/build/core/keyring/introductory-keys/published-intro-key.js +190 -0
  29. package/build/core/keyring/peer-keys/dataset/v1/json-files.d.ts +105 -0
  30. package/build/core/keyring/peer-keys/dataset/v1/json-files.js +89 -0
  31. package/build/core/keyring/peer-keys/dataset/v2/logs.d.ts +43 -0
  32. package/build/core/keyring/peer-keys/dataset/v2/logs.js +116 -0
  33. package/build/core/keyring/peer-keys/dataset/v2/peer-keys-db.d.ts +73 -0
  34. package/build/core/keyring/peer-keys/dataset/v2/peer-keys-db.js +543 -0
  35. package/build/core/keyring/peer-keys/index.d.ts +24 -0
  36. package/build/core/keyring/peer-keys/index.js +208 -0
  37. package/build/core/storage/synced/obj-files.js +10 -3
  38. package/build/core/storage/synced/obj-status.d.ts +1 -1
  39. package/build/core/storage/synced/obj-status.js +8 -2
  40. package/build/core/storage/synced/storage.d.ts +4 -4
  41. package/build/core/storage/system-folders/apps-data.d.ts +0 -1
  42. package/build/core/storage/system-folders/apps-data.js +2 -6
  43. package/build/lib-client/fs-utils/fs-sync-utils.d.ts +1 -1
  44. package/build/lib-client/fs-utils/fs-sync-utils.js +70 -13
  45. package/build/lib-client/xsp-fs/fs.js +3 -1
  46. package/build/lib-client/xsp-fs/node-in-fs.d.ts +1 -0
  47. package/build/lib-client/xsp-fs/node-in-fs.js +7 -2
  48. package/build/lib-client/xsp-fs/node-persistence.js +1 -3
  49. package/build/lib-client/xsp-fs/xsp-payload-v2.js +1 -2
  50. package/build/lib-common/dataset-sync/per-device-json-array-logs.d.ts +58 -0
  51. package/build/lib-common/dataset-sync/per-device-json-array-logs.js +432 -0
  52. package/build/lib-common/number-line.d.ts +10 -0
  53. package/build/lib-common/number-line.js +66 -0
  54. package/build/lib-common/objs-on-disk/obj-version-file.d.ts +1 -1
  55. package/build/lib-common/objs-on-disk/obj-version-file.js +3 -3
  56. package/build/lib-common/rng-def.d.ts +1 -0
  57. package/build/lib-common/rng-def.js +8 -0
  58. package/build/lib-sqlite-on-3nstorage/for-sqlite.d.ts +38 -0
  59. package/build/lib-sqlite-on-3nstorage/for-sqlite.js +162 -0
  60. package/build/lib-sqlite-on-3nstorage/index.d.ts +18 -5
  61. package/build/lib-sqlite-on-3nstorage/index.js +49 -26
  62. package/build/tests/caps-api/file-sink-checks/splice.js +72 -1
  63. package/build/tests/caps-api/fs-checks/sync-on-one-dev/upload.js +27 -1
  64. package/build/tests/caps-api/fs-checks/sync-with-two-devs/update-propagation.js +12 -3
  65. package/build/tests/computer.3nweb.core/inbox/msg-indexing.js +16 -12
  66. package/build/tests/computer.3nweb.core/keyrings.js +113 -28
  67. package/build/tests/jasmine.js +2 -2
  68. package/build/tests/units/number-line.js +9 -9
  69. package/package.json +2 -1
  70. package/build/core/asmail/inbox/msg-indexing/logs-n-entries.d.ts +0 -52
  71. package/build/core/asmail/inbox/msg-indexing/logs-n-entries.js +0 -333
  72. package/build/core/asmail/inbox/msg-indexing/sql-indexing.d.ts +0 -4
  73. package/build/core/asmail/inbox/msg-indexing/sql-indexing.js +0 -319
  74. package/build/core/keyring/correspondent-keys.d.ts +0 -149
  75. package/build/core/keyring/correspondent-keys.js +0 -403
  76. package/build/core/keyring/id-to-email-map.d.ts +0 -38
  77. package/build/core/keyring/id-to-email-map.js +0 -105
  78. package/build/core/keyring/keyring-storage.d.ts +0 -9
  79. package/build/core/keyring/keyring-storage.js +0 -54
  80. package/build/core/keyring/published-intro-key.d.ts +0 -45
  81. package/build/core/keyring/published-intro-key.js +0 -200
@@ -49,7 +49,7 @@ class ASMail {
49
49
  this.keyring = keyring;
50
50
  await this.setupSendingParams(syncedFS);
51
51
  await Promise.all([
52
- this.setupInbox(syncedFS, getSigner, getStorages, makeResolver),
52
+ this.setupInbox(syncedFS, localFS, getSigner, getStorages, makeResolver),
53
53
  this.setupDelivery(localFS, getSigner, makeResolver)
54
54
  ]);
55
55
  await (0, fs_sync_utils_1.uploadFolderChangesIfAny)(syncedFS);
@@ -61,7 +61,7 @@ class ASMail {
61
61
  }
62
62
  }
63
63
  async setupSendingParams(syncedFS) {
64
- const fs = await (0, fs_sync_utils_1.getOrMakeAndUploadFolderIn)(syncedFS, SEND_PARAMS_DATA_FOLDER);
64
+ const fs = await (0, fs_sync_utils_1.getOrMakeSyncedDirOnInit)(syncedFS, SEND_PARAMS_DATA_FOLDER);
65
65
  this.sendingParams = await sending_params_1.SendingParamsHolder.makeAndInit(fs, this.config.makeParamSetterAndGetter('anon-sender/invites'), this.random);
66
66
  }
67
67
  async setupDelivery(localFS, getSigner, makeResolver) {
@@ -75,8 +75,8 @@ class ASMail {
75
75
  midResolver: makeResolver('mailerid', this.logger.logError),
76
76
  correspondents: {
77
77
  needIntroKeyFor: this.keyring.needIntroKeyFor,
78
- generateKeysToSend: this.keyring.generateKeysToSend,
79
- nextCrypto: this.keyring.nextCrypto,
78
+ generateIntroKeysToSendMsg: this.keyring.generateIntroKeysToSendMsg,
79
+ getEstablishedKeysToSendMsg: this.keyring.getEstablishedKeysToSendMsg,
80
80
  paramsForSendingTo: this.sendingParams.otherSides.get,
81
81
  newParamsForSendingReplies: this.sendingParams.thisSide.getUpdated
82
82
  },
@@ -86,10 +86,11 @@ class ASMail {
86
86
  logWarning: this.logger.logWarning
87
87
  });
88
88
  }
89
- async setupInbox(syncedFS, getSigner, getStorages, makeResolver) {
89
+ async setupInbox(syncedFS, localFS, getSigner, getStorages, makeResolver) {
90
90
  const cachePath = this.inboxPathForUser(this.address);
91
- const inboxSyncedFS = await (0, fs_sync_utils_1.getOrMakeAndUploadFolderIn)(syncedFS, INBOX_DATA_FOLDER);
92
- this.inbox = await inbox_1.InboxOnServer.makeAndStart(cachePath, inboxSyncedFS, {
91
+ const inboxSyncedFS = await (0, fs_sync_utils_1.getOrMakeSyncedDirOnInit)(syncedFS, INBOX_DATA_FOLDER);
92
+ const inboxLocalFS = await localFS.writableSubRoot(INBOX_DATA_FOLDER);
93
+ this.inbox = await inbox_1.InboxOnServer.makeAndStart(cachePath, inboxSyncedFS, inboxLocalFS, {
93
94
  address: this.address,
94
95
  cryptor: this.cryptor,
95
96
  random: this.random,
@@ -38,7 +38,6 @@ export interface MsgEnvelope {
38
38
  export interface SuggestedNextKeyPair {
39
39
  pids: string[];
40
40
  senderKid: string;
41
- isSenderIntroKey?: boolean;
42
41
  recipientPKey: JsonKeyShort;
43
42
  timestamp: number;
44
43
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- Copyright (C) 2015 - 2018, 2020, 2022 3NSoft Inc.
3
+ Copyright (C) 2015 - 2018, 2020, 2022, 2026 3NSoft Inc.
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under
6
6
  the terms of the GNU General Public License as published by the Free Software
@@ -153,7 +153,7 @@ class MsgPacker {
153
153
  const fPath = appendedPath(fsPath, fName);
154
154
  if (entry.isFile) {
155
155
  await fs.readonlyFile(fName);
156
- this.addFileInto(folder, fName, fPath);
156
+ await this.addFileInto(folder, fName, fPath);
157
157
  }
158
158
  else if (entry.isFolder) {
159
159
  const f = await fs.readonlySubRoot(fName);
@@ -331,8 +331,6 @@ class MsgPacker {
331
331
  if (this.hasAttachments) {
332
332
  this.main['Attachments'] = attachments;
333
333
  }
334
- // DEBUG log
335
- console.log(` message packer allObjs has ${this.allObjs.size} items`);
336
334
  }
337
335
  throwupOnMissingParts() {
338
336
  if (!this.meta) {
@@ -38,12 +38,12 @@ class Core {
38
38
  this.appDirs = appDirs;
39
39
  this.logger = logger;
40
40
  this.signUpUrl = signUpUrl;
41
+ this.keyrings = undefined;
41
42
  this.idManager = undefined;
42
43
  this.closingProc = undefined;
43
44
  this.isInitialized = false;
44
45
  this.cryptor = makeCryptor(this.logger.logError, this.logger.logWarning);
45
46
  this.storages = new storage_1.Storages(this.cryptor.cryptor.sbox, this.random, this.appDirs.storagePathFor);
46
- this.keyrings = new keyring_1.Keyrings(this.cryptor.cryptor.sbox, this.random, this.logger);
47
47
  this.asmail = new asmail_1.ASMail(this.cryptor.cryptor.sbox, this.random, this.makeNet, this.appDirs.inboxPathFor, this.logger);
48
48
  Object.seal(this);
49
49
  }
@@ -265,9 +265,10 @@ class Core {
265
265
  }
266
266
  }
267
267
  makeKeyringsCAP(requestedCAPs) {
268
+ var _a;
268
269
  if (requestedCAPs.keyrings
269
270
  && (requestedCAPs.keyrings === 'all')) {
270
- return this.keyrings.makeKeyringsCAP();
271
+ return (_a = this.keyrings) === null || _a === void 0 ? void 0 : _a.makeKeyringsCAP();
271
272
  }
272
273
  else {
273
274
  return undefined;
@@ -292,9 +293,10 @@ class Core {
292
293
  async close() {
293
294
  if (!this.closingProc) {
294
295
  this.closingProc = (async () => {
296
+ var _a;
295
297
  if (this.isInitialized) {
296
298
  await this.asmail.close();
297
- await this.keyrings.close();
299
+ await ((_a = this.keyrings) === null || _a === void 0 ? void 0 : _a.close());
298
300
  await this.storages.close();
299
301
  this.asmail = undefined;
300
302
  this.keyrings = undefined;
@@ -323,7 +325,8 @@ class Core {
323
325
  const asmailServerConfig = new config_1.ConfigOfASMailServer(address, getSigner, this.makeResolver('asmail', this.logger.logError), this.makeNet());
324
326
  emitBootEvent({ coreApp: constants_1.KEYRINGS_APP_NAME, message: `starting initialization` });
325
327
  const keyringsSyncedFS = await this.storages.makeSyncedFSForApp(constants_1.KEYRINGS_APP_NAME);
326
- await this.keyrings.init(keyringsSyncedFS, this.idManager.getSigner, asmailServerConfig.makeParamSetterAndGetter('init-pub-key'));
328
+ const keyringsLocalFS = await this.storages.makeLocalFSForApp(constants_1.KEYRINGS_APP_NAME);
329
+ this.keyrings = await (0, keyring_1.makeKeyrings)(this.cryptor.cryptor.sbox, this.random, this.logger, keyringsSyncedFS, keyringsLocalFS, this.idManager.getSigner, asmailServerConfig.makeParamSetterAndGetter('init-pub-key'));
327
330
  emitBootEvent({ coreApp: constants_1.KEYRINGS_APP_NAME, message: `✔️ initialized` });
328
331
  emitBootEvent({ coreApp: constants_1.ASMAIL_APP_NAME, message: `starting initialization` });
329
332
  const inboxSyncedFS = await this.storages.makeSyncedFSForApp(constants_1.ASMAIL_APP_NAME);
@@ -4,6 +4,7 @@ type JsonKeyShort = web3n.keys.JsonKeyShort;
4
4
  export type MsgKeyRole = 'suggested' | 'in_use' | 'old' | 'published_intro' | 'prev_published_intro' | 'introductory';
5
5
  export declare const KID_LENGTH = 16;
6
6
  export declare const PID_LENGTH = 2;
7
+ export declare const MIN_PERIOD_FOR_PAIR: number;
7
8
  export interface JWKeyPair {
8
9
  skey: JsonKey;
9
10
  pkey: JsonKey;
@@ -16,7 +16,7 @@
16
16
  this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.KEY_USE = exports.PID_LENGTH = exports.KID_LENGTH = void 0;
19
+ exports.KEY_USE = exports.MIN_PERIOD_FOR_PAIR = exports.PID_LENGTH = exports.KID_LENGTH = void 0;
20
20
  exports.generateKeyPair = generateKeyPair;
21
21
  exports.generateSymmetricKey = generateSymmetricKey;
22
22
  exports.extractSKeyBytes = extractSKeyBytes;
@@ -31,6 +31,7 @@ const buffer_utils_1 = require("../../lib-common/buffer-utils");
31
31
  const rng_def_1 = require("../../lib-common/rng-def");
32
32
  exports.KID_LENGTH = 16;
33
33
  exports.PID_LENGTH = 2;
34
+ exports.MIN_PERIOD_FOR_PAIR = 15 * 60 * 1000;
34
35
  exports.KEY_USE = {
35
36
  PUBLIC: 'asmail-pub-key',
36
37
  SECRET: 'asmail-sec-key',
@@ -1,4 +1,3 @@
1
- import { IdToEmailMap } from './id-to-email-map';
2
1
  import { MsgKeyRole } from './common';
3
2
  import { AsyncSBoxCryptor } from 'xsp-files';
4
3
  import { ResourcesForSending } from '../asmail/delivery/common';
@@ -28,49 +27,13 @@ type SendingResources = ResourcesForSending['correspondents'];
28
27
  type ReceptionResources = ResourcesForReceiving['correspondents'];
29
28
  export interface KeyringForASMail {
30
29
  needIntroKeyFor: SendingResources['needIntroKeyFor'];
31
- generateKeysToSend: SendingResources['generateKeysToSend'];
32
- nextCrypto: SendingResources['nextCrypto'];
30
+ generateIntroKeysToSendMsg: SendingResources['generateIntroKeysToSendMsg'];
31
+ getEstablishedKeysToSendMsg: SendingResources['getEstablishedKeysToSendMsg'];
33
32
  decrypt: ReceptionResources['msgDecryptor'];
34
33
  close(): Promise<void>;
35
34
  }
36
- export interface KeyPairsStorage {
37
- pairIdToEmailMap: IdToEmailMap;
38
- saveChanges: () => void;
39
- }
40
- export declare class Keyrings {
41
- private readonly cryptor;
42
- private readonly random;
43
- private readonly logger;
44
- /**
45
- * This is a map from correspondents' canonical addresses to key objects.
46
- */
47
- private readonly corrKeys;
48
- readonly pairIdToEmailMap: IdToEmailMap;
49
- private readonly workLabel;
50
- private storage;
51
- private publishedKeys;
52
- constructor(cryptor: AsyncSBoxCryptor, random: AsyncRNG, logger: Logger);
53
- private readonly asKeyPairsStorage;
54
- private addCorrespondent;
55
- init(fs: WritableFS, getSigner: GetSigner, pkeyOnServer: ParamOnServer<'init-pub-key'>): Promise<void>;
56
- forASMail(): KeyringForASMail;
57
- private saveChanges;
58
- private needIntroKeyFor;
59
- private generateKeysToSend;
60
- private nextCrypto;
61
- private decryptMsgKeyWithIntroPair;
62
- private findEstablishedReceptionPairs;
63
- private decryptMsgKeyWithEstablishedPair;
64
- /**
65
- * This method updates message counts and a timestamp in a given reception
66
- * pair.
67
- * @param rp is a sending pair, in which changes should be done. Note this
68
- * must be a shared structure at this point, not a copy of a pair.
69
- * @param msgCount is a message count that should be added to the pair.
70
- */
71
- private updateReceivedMsgCountIn;
72
- private absorbSuggestedNextKeyPair;
73
- private decrypt;
74
- close(): Promise<void>;
75
- makeKeyringsCAP(): Service;
76
- }
35
+ export declare function makeKeyrings(cryptor: AsyncSBoxCryptor, random: AsyncRNG, logger: Logger, fs: WritableFS, localFS: WritableFS, getSigner: GetSigner, pkeyOnServer: ParamOnServer<'init-pub-key'>): Promise<{
36
+ close: () => Promise<void>;
37
+ makeKeyringsCAP: () => Service;
38
+ forASMail: () => KeyringForASMail;
39
+ }>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- Copyright (C) 2015 - 2018, 2022, 2025 3NSoft Inc.
3
+ Copyright (C) 2015 - 2018, 2022, 2025 - 2026 3NSoft Inc.
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under
6
6
  the terms of the GNU General Public License as published by the Free Software
@@ -16,124 +16,54 @@
16
16
  this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.Keyrings = exports.KEY_USE = void 0;
20
- const correspondent_keys_1 = require("./correspondent-keys");
21
- const id_to_email_map_1 = require("./id-to-email-map");
19
+ exports.KEY_USE = void 0;
20
+ exports.makeKeyrings = makeKeyrings;
21
+ const peer_keys_1 = require("./peer-keys");
22
22
  const common_1 = require("./common");
23
23
  const async_cryptor_wrap_1 = require("../../lib-common/async-cryptor-wrap");
24
24
  const xsp_files_1 = require("xsp-files");
25
- const buffer_utils_1 = require("../../lib-common/buffer-utils");
26
25
  const canonical_address_1 = require("../../lib-common/canonical-address");
27
- const common_2 = require("../asmail/delivery/common");
28
- const keyring_storage_1 = require("./keyring-storage");
29
26
  const cryptor_work_labels_1 = require("../../lib-client/cryptor-work-labels");
30
- const published_intro_key_1 = require("./published-intro-key");
31
- var common_3 = require("./common");
32
- Object.defineProperty(exports, "KEY_USE", { enumerable: true, get: function () { return common_3.KEY_USE; } });
33
- const FILE_FOR_INTRO_KEY_ON_SERVER = 'introductory-keys/published-on-server.json';
34
- // XXX Keyring is just a storage and crypto functionality around keys
35
- class Keyrings {
36
- constructor(cryptor, random, logger) {
37
- this.cryptor = cryptor;
38
- this.random = random;
39
- this.logger = logger;
40
- /**
41
- * This is a map from correspondents' canonical addresses to key objects.
42
- */
43
- this.corrKeys = new Map();
44
- this.pairIdToEmailMap = new id_to_email_map_1.IdToEmailMap();
45
- this.workLabel = cryptor_work_labels_1.cryptoWorkLabels.makeRandom('asmail');
46
- this.storage = undefined;
47
- this.publishedKeys = undefined;
48
- this.asKeyPairsStorage = {
49
- pairIdToEmailMap: this.pairIdToEmailMap,
50
- saveChanges: this.saveChanges.bind(this)
51
- };
52
- Object.seal(this);
53
- }
54
- addCorrespondent(address, serialForm) {
55
- const ck = (serialForm ?
56
- new correspondent_keys_1.CorrespondentKeys(this.asKeyPairsStorage, this.random, undefined, serialForm) :
57
- new correspondent_keys_1.CorrespondentKeys(this.asKeyPairsStorage, this.random, address));
58
- if (this.corrKeys.has(ck.correspondent)) {
59
- throw new Error(`Correspondent with address ${ck.correspondent} is already present.`);
60
- }
61
- this.corrKeys.set(ck.correspondent, ck);
62
- if (serialForm) {
63
- ck.mapAllKeysIntoRing();
64
- }
65
- return ck;
66
- }
67
- async init(fs, getSigner, pkeyOnServer) {
68
- this.publishedKeys = await published_intro_key_1.PublishedIntroKey.makeAndInit(await fs.writableFile(FILE_FOR_INTRO_KEY_ON_SERVER), getSigner, this.random, pkeyOnServer);
69
- this.storage = (0, keyring_storage_1.makeKeyringStorage)(fs);
70
- await this.storage.start();
71
- const serialForm = await this.storage.load();
72
- if (serialForm) {
73
- const json = JSON.parse(serialForm);
74
- // TODO check json's fields
75
- // init data
76
- json.corrKeys.forEach((info) => {
77
- this.addCorrespondent(undefined, info);
78
- });
79
- }
80
- else {
81
- // save initial file, as there was none initially
82
- this.saveChanges();
83
- }
84
- }
85
- forASMail() {
86
- return {
87
- close: this.close.bind(this),
88
- decrypt: this.decrypt.bind(this),
89
- generateKeysToSend: this.generateKeysToSend.bind(this),
90
- needIntroKeyFor: this.needIntroKeyFor.bind(this),
91
- nextCrypto: this.nextCrypto.bind(this),
92
- };
93
- }
94
- saveChanges() {
95
- // pack bytes that need to be encrypted and saved
96
- const dataToSave = {
97
- corrKeys: []
27
+ const published_intro_key_1 = require("./introductory-keys/published-intro-key");
28
+ const fs_sync_utils_1 = require("../../lib-client/fs-utils/fs-sync-utils");
29
+ const ecma_nacl_1 = require("ecma-nacl");
30
+ const buffer_utils_1 = require("../../lib-common/buffer-utils");
31
+ var common_2 = require("./common");
32
+ Object.defineProperty(exports, "KEY_USE", { enumerable: true, get: function () { return common_2.KEY_USE; } });
33
+ const INTRO_KEYS_FOLDER = 'introductory-keys';
34
+ const INTRO_KEY_ON_SERVER_FILE = `published-on-server.json`;
35
+ async function makeKeyrings(cryptor, random, logger, fs, localFS, getSigner, pkeyOnServer) {
36
+ const workLabel = cryptor_work_labels_1.cryptoWorkLabels.makeRandom('asmail');
37
+ const introKeysFS = await (0, fs_sync_utils_1.getOrMakeSyncedDirOnInit)(fs, INTRO_KEYS_FOLDER);
38
+ const publishedKeys = await (0, published_intro_key_1.makeHolderOfPublishedIntroKey)(await introKeysFS.writableFile(INTRO_KEY_ON_SERVER_FILE), getSigner, random, pkeyOnServer);
39
+ const peerKeys = await (0, peer_keys_1.makePeersKeyring)(fs, localFS, random, logger);
40
+ async function generateIntroKeysToSendMsg(address, introPKeyFromServer) {
41
+ if (introPKeyFromServer.alg !== ecma_nacl_1.box.JWK_ALG_NAME) {
42
+ // XXX make some standard runtime exception, for unknown alg
43
+ throw new Error(`Unknown alg in introductory key: ${introPKeyFromServer.alg}`);
44
+ }
45
+ const oneTime = await (0, common_1.generateKeyPair)(random);
46
+ const currentPair = {
47
+ recipientKid: introPKeyFromServer.kid,
48
+ senderPKey: oneTime.pkey
98
49
  };
99
- for (const corrKeys of this.corrKeys.values()) {
100
- dataToSave.corrKeys.push(corrKeys.serialForm());
101
- }
102
- // trigger saving utility
103
- this.storage.save(JSON.stringify(dataToSave));
104
- }
105
- needIntroKeyFor(address) {
106
- address = (0, canonical_address_1.toCanonicalAddress)(address);
107
- return !this.corrKeys.has(address);
50
+ const msgMasterKey = ecma_nacl_1.box.calc_dhshared_key(buffer_utils_1.base64.open(introPKeyFromServer.k), buffer_utils_1.base64.open(oneTime.skey.k));
51
+ const nextNonce = await random(xsp_files_1.NONCE_LENGTH);
52
+ const encryptor = (0, async_cryptor_wrap_1.makeEncryptor)(cryptor, workLabel, msgMasterKey, nextNonce);
53
+ msgMasterKey.fill(0);
54
+ const nextMsgCrypto = await peerKeys.suggestPairForPeerIntroKey(address, introPKeyFromServer);
55
+ return { encryptor, currentPair, msgCount: 1, nextMsgCrypto };
108
56
  }
109
- ;
110
- async generateKeysToSend(address, introPKeyFromServer) {
111
- address = (0, canonical_address_1.toCanonicalAddress)(address);
112
- let ck = this.corrKeys.get(address);
113
- if (!ck) {
114
- if (!introPKeyFromServer) {
115
- throw new Error(`There are no known keys for given address ${address} and a key from a mail server is not given either.`);
116
- }
117
- ck = this.addCorrespondent(address);
118
- }
119
- const { msgMasterKey, currentPair, msgCount } = await ck.getSendingPair(introPKeyFromServer);
57
+ async function getEstablishedKeysToSendMsg(address) {
58
+ const { msgMasterKey, currentPair, msgCount, nextMsgCrypto } = await peerKeys.getSendingCryptoWithinEstablishedPair((0, canonical_address_1.toCanonicalAddress)(address));
120
59
  // prepare message encryptor
121
- const nextNonce = await this.random(xsp_files_1.NONCE_LENGTH);
122
- const encryptor = (0, async_cryptor_wrap_1.makeEncryptor)(this.cryptor, this.workLabel, msgMasterKey, nextNonce);
60
+ const nextNonce = await random(xsp_files_1.NONCE_LENGTH);
61
+ const encryptor = (0, async_cryptor_wrap_1.makeEncryptor)(cryptor, workLabel, msgMasterKey, nextNonce);
123
62
  msgMasterKey.fill(0);
124
- return { encryptor, currentPair, msgCount };
63
+ return { encryptor, currentPair, msgCount, nextMsgCrypto };
125
64
  }
126
- async nextCrypto(address) {
127
- address = (0, canonical_address_1.toCanonicalAddress)(address);
128
- let ck = this.corrKeys.get(address);
129
- if (!ck) {
130
- throw new Error(`No correspondent keys found for ${address}`);
131
- }
132
- const suggestPair = await ck.suggestPair();
133
- return suggestPair;
134
- }
135
- async decryptMsgKeyWithIntroPair(recipientKid, senderPKey, getMainObjHeader) {
136
- const recipKey = this.publishedKeys.find(recipientKid);
65
+ async function decryptMsgKeyWithIntroPair(recipientKid, senderPKey, getMainObjHeader) {
66
+ const recipKey = publishedKeys.find(recipientKid);
137
67
  if (!recipKey) {
138
68
  return;
139
69
  }
@@ -142,16 +72,17 @@ class Keyrings {
142
72
  if (h.length < msgKeyPackLen) {
143
73
  return;
144
74
  }
145
- const masterDecr = (0, correspondent_keys_1.msgMasterDecryptor)(this.cryptor, recipKey.pair.skey, { kid: '', k: senderPKey });
75
+ const msgMasterKey = ecma_nacl_1.box.calc_dhshared_key(buffer_utils_1.base64.open(senderPKey), buffer_utils_1.base64.open(recipKey.pair.skey.k));
76
+ const masterDecr = (0, async_cryptor_wrap_1.makeDecryptor)(cryptor, workLabel, msgMasterKey);
146
77
  try {
147
78
  const mainObjFileKey = await masterDecr.open(h.subarray(0, msgKeyPackLen));
148
- const info = {
79
+ const decrInfo = {
149
80
  correspondent: undefined,
150
81
  keyStatus: recipKey.role,
151
82
  key: mainObjFileKey,
152
83
  msgKeyPackLen
153
84
  };
154
- return info;
85
+ return { decrInfo, introKey: recipKey.pair };
155
86
  }
156
87
  catch (err) {
157
88
  if (!err.failedCipherVerification) {
@@ -162,60 +93,35 @@ class Keyrings {
162
93
  masterDecr.destroy();
163
94
  }
164
95
  }
165
- findEstablishedReceptionPairs(pid) {
166
- const emails = this.pairIdToEmailMap.getEmails(pid);
167
- if (!emails) {
168
- return;
169
- }
170
- const decryptors = [];
171
- for (const email of emails) {
172
- const ck = this.corrKeys.get(email);
173
- if (!ck) {
174
- return;
175
- }
176
- const rp = ck.getReceivingPair(pid);
177
- if (!rp) {
178
- return;
179
- }
180
- decryptors.push({
181
- correspondent: email,
182
- role: rp.role,
183
- pair: rp.pair
184
- });
185
- }
186
- return decryptors;
187
- }
188
- async decryptMsgKeyWithEstablishedPair(pid, getMainObjHeader) {
189
- const pairs = this.findEstablishedReceptionPairs(pid);
96
+ async function decryptMsgKeyWithEstablishedPair(pid, getMainObjHeader) {
97
+ const pairs = peerKeys.findEstablishedReceptionPairs(pid);
190
98
  if (!pairs) {
191
99
  return;
192
100
  }
193
101
  // try to open main object's file key from a header
194
102
  const h = await getMainObjHeader();
195
- for (const { correspondent, pair, role } of pairs) {
196
- const masterKey = buffer_utils_1.base64.open(pair.msgMasterKey);
197
- const masterDecr = (0, async_cryptor_wrap_1.makeDecryptor)(this.cryptor, this.workLabel, masterKey);
198
- masterKey.fill(0);
103
+ for (const { msgMasterKey, pairAlg, peerCAddr, ratchetStage, peerKId, recipientKId } of pairs) {
104
+ const masterDecr = (0, async_cryptor_wrap_1.makeDecryptor)(cryptor, workLabel, msgMasterKey);
105
+ msgMasterKey.fill(0);
199
106
  try {
200
- const msgKeyPackLen = msgKeyPackLenForPair(pair);
107
+ const msgKeyPackLen = (0, common_1.msgKeyPackSizeFor)(pairAlg);
201
108
  if (h.length < msgKeyPackLen) {
202
109
  continue;
203
110
  }
204
111
  const mainObjFileKey = await masterDecr.open(h.subarray(0, msgKeyPackLen));
205
112
  const keyInfo = {
206
- correspondent: correspondent,
207
- keyStatus: role,
113
+ correspondent: peerKeys.getPeerAddressForCanonical(peerCAddr) || peerCAddr,
114
+ keyStatus: ratchetStage,
208
115
  key: mainObjFileKey,
209
116
  msgKeyPackLen
210
117
  };
211
118
  // set pair as in use
212
119
  if (keyInfo.keyStatus === 'suggested') {
213
- const corrKeys = this.corrKeys.get(keyInfo.correspondent);
214
- corrKeys.markPairAsInUse(pair);
120
+ await peerKeys.markPairAsInUse(peerCAddr, peerKId, recipientKId);
215
121
  }
216
122
  return {
217
123
  keyInfo,
218
- incrMsgCount: msgCount => this.updateReceivedMsgCountIn(pair, msgCount)
124
+ incrMsgCount: msgCount => peerKeys.updateReceivedMsgCountIn(peerCAddr, peerKId, recipientKId, msgCount, Date.now())
219
125
  };
220
126
  }
221
127
  catch (err) {
@@ -228,58 +134,13 @@ class Keyrings {
228
134
  }
229
135
  }
230
136
  }
231
- /**
232
- * This method updates message counts and a timestamp in a given reception
233
- * pair.
234
- * @param rp is a sending pair, in which changes should be done. Note this
235
- * must be a shared structure at this point, not a copy of a pair.
236
- * @param msgCount is a message count that should be added to the pair.
237
- */
238
- updateReceivedMsgCountIn(rp, msgCount) {
239
- const lastTS = Date.now();
240
- if (!rp.receivedMsgs) {
241
- rp.receivedMsgs = { counts: [], lastTS };
242
- }
243
- (0, common_2.addToNumberLineSegments)(rp.receivedMsgs.counts, msgCount);
244
- rp.receivedMsgs.lastTS = lastTS;
245
- this.saveChanges();
246
- }
247
- absorbSuggestedNextKeyPair(correspondent, pair) {
248
- let ck = this.corrKeys.get(correspondent);
249
- if (!ck) {
250
- ck = this.addCorrespondent(correspondent);
251
- }
252
- if (pair.isSenderIntroKey) {
253
- const usedIntro = this.publishedKeys.find(pair.senderKid);
254
- if (!usedIntro) {
255
- throw new Error(`Recently used published intro key is not found`);
256
- }
257
- ck.ratchetUpSendingPair(pair, usedIntro.pair);
258
- }
259
- else {
260
- ck.ratchetUpSendingPair(pair);
261
- }
262
- // if (ck) {
263
- // ck.ratchetUpSendingPair(pair);
264
- // } else {
265
- // if (!pair.isSenderIntroKey) {
266
- // throw new Error(`Expected addition of correspondent to be done, when new `);
267
- // }
268
- // const usedIntro = this.publishedKeys.find(pair.senderKid);
269
- // if (!usedIntro) {
270
- // throw new Error(`Recently used published intro key is not found`);
271
- // }
272
- // ck = this.addCorrespondent(correspondent);
273
- // ck.ratchetUpSendingPair(pair, usedIntro.pair);
274
- // }
275
- this.saveChanges();
276
- }
277
- async decrypt(msgMeta, getMainObjHeader, getOpenedMsg, checkMidKeyCerts) {
137
+ async function decrypt(msgMeta, getMainObjHeader, getOpenedMsg, checkMidKeyCerts) {
278
138
  let decrInfo;
139
+ let introKey = undefined;
279
140
  let incrMsgCount;
280
141
  let openedMsg;
281
142
  if (msgMeta.pid) {
282
- const r = await this.decryptMsgKeyWithEstablishedPair(msgMeta.pid, getMainObjHeader);
143
+ const r = await decryptMsgKeyWithEstablishedPair(msgMeta.pid, getMainObjHeader);
283
144
  if (!r) {
284
145
  return;
285
146
  }
@@ -288,10 +149,12 @@ class Keyrings {
288
149
  openedMsg = await getOpenedMsg(decrInfo.key, decrInfo.msgKeyPackLen);
289
150
  }
290
151
  else {
291
- decrInfo = await this.decryptMsgKeyWithIntroPair(msgMeta.recipientKid, msgMeta.senderPKey, getMainObjHeader);
292
- if (!decrInfo) {
152
+ const r = await decryptMsgKeyWithIntroPair(msgMeta.recipientKid, msgMeta.senderPKey, getMainObjHeader);
153
+ if (!r) {
293
154
  return;
294
155
  }
156
+ decrInfo = r.decrInfo;
157
+ introKey = r.introKey;
295
158
  openedMsg = await getOpenedMsg(decrInfo.key, decrInfo.msgKeyPackLen);
296
159
  const certs = openedMsg.introCryptoCerts;
297
160
  const { address, pkey } = await checkMidKeyCerts(certs);
@@ -310,46 +173,50 @@ class Keyrings {
310
173
  incrMsgCount(openedMsg.msgCount);
311
174
  }
312
175
  // absorb next crypto
313
- const pair = openedMsg.nextCrypto;
314
- if (pair) {
176
+ const suggestedPair = openedMsg.nextCrypto;
177
+ if (suggestedPair) {
315
178
  try {
316
- if (msgMeta.recipientKid) {
317
- if (!pair.isSenderIntroKey) {
318
- throw new Error(`Introductory message is not referencing used intro key in the next crypto`);
319
- }
320
- if (msgMeta.recipientKid !== pair.senderKid) {
179
+ if (introKey) {
180
+ if (introKey.pkey.kid !== suggestedPair.senderKid) {
321
181
  throw new Error(`Introductory message is referencing wrong key in the next crypto`);
322
182
  }
183
+ await peerKeys.absorbNextPairSuggestedByPeer(decrInfo.correspondent, suggestedPair, introKey);
184
+ }
185
+ else {
186
+ await peerKeys.absorbNextPairSuggestedByPeer(decrInfo.correspondent, suggestedPair);
323
187
  }
324
- this.absorbSuggestedNextKeyPair(decrInfo.correspondent, pair);
325
188
  }
326
189
  catch (err) {
327
- this.logger.logError(err, `Fail to absorb next suggested key for messaging`);
190
+ logger.logError(err, `Fail to absorb next suggested key for messaging`);
328
191
  }
329
192
  }
330
193
  return { decrInfo, openedMsg };
331
194
  }
332
195
  ;
333
- async close() {
334
- await this.publishedKeys.close();
335
- await this.storage.close();
196
+ async function close() {
197
+ await publishedKeys.close();
198
+ await peerKeys.close();
336
199
  }
337
- makeKeyringsCAP() {
200
+ function makeKeyringsCAP() {
338
201
  const w = {
339
- introKeyOnASMailServer: this.publishedKeys.makeIntroKeyCAP(),
340
- getCorrespondentKeys: async (addr) => {
341
- var _a;
342
- const cAddr = (0, canonical_address_1.toCanonicalAddress)(addr);
343
- return (_a = this.corrKeys.get(cAddr)) === null || _a === void 0 ? void 0 : _a.toInfo();
344
- }
202
+ introKeyOnASMailServer: publishedKeys.makeIntroKeyCAP(),
203
+ getCorrespondentKeys: async (peerAddr) => peerKeys.getPeerKeysInfo(peerAddr)
345
204
  };
346
205
  return Object.freeze(w);
347
206
  }
348
- }
349
- exports.Keyrings = Keyrings;
350
- Object.freeze(Keyrings.prototype);
351
- Object.freeze(Keyrings);
352
- function msgKeyPackLenForPair(p) {
353
- return (0, common_1.msgKeyPackSizeFor)(p.recipientKey.skey.alg);
207
+ function forASMail() {
208
+ return {
209
+ close,
210
+ decrypt,
211
+ generateIntroKeysToSendMsg,
212
+ getEstablishedKeysToSendMsg,
213
+ needIntroKeyFor: peerKeys.needIntroKeyFor
214
+ };
215
+ }
216
+ return {
217
+ close,
218
+ makeKeyringsCAP,
219
+ forASMail
220
+ };
354
221
  }
355
222
  Object.freeze(exports);
@@ -0,0 +1,17 @@
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 function makeHolderOfPublishedIntroKey(file: WritableFile, getSigner: GetSigner, random: AsyncRNG, pkeyOnServer: ParamOnServer<'init-pub-key'>): Promise<{
8
+ startExpiryCheckProcess: () => void;
9
+ close: () => Promise<void>;
10
+ makeIntroKeyCAP: () => IntroKeyCAP;
11
+ find: (kid: string) => {
12
+ role: MsgKeyRole;
13
+ pair: JWKeyPair;
14
+ replacedAt?: number;
15
+ } | undefined;
16
+ }>;
17
+ export {};