core-3nweb-client-lib 0.27.0 → 0.27.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/build/api-defs/files.d.ts +56 -26
- package/build/core/asmail/config/index.d.ts +2 -2
- package/build/core/asmail/config/index.js +2 -2
- package/build/core/asmail/config/invitations-anon.d.ts +10 -24
- package/build/core/asmail/config/invitations-anon.js +43 -31
- package/build/core/asmail/config/published-intro-key.d.ts +11 -22
- package/build/core/asmail/config/published-intro-key.js +47 -38
- package/build/core/asmail/inbox/attachments/fs.d.ts +2 -1
- package/build/core/asmail/inbox/attachments/fs.js +4 -3
- package/build/core/asmail/inbox/index.js +2 -2
- package/build/core/asmail/index.d.ts +1 -1
- package/build/core/asmail/index.js +2 -2
- package/build/core/asmail/keyring/correspondent-keys.d.ts +2 -2
- package/build/core/asmail/keyring/correspondent-keys.js +1 -1
- package/build/core/asmail/keyring/index.d.ts +9 -29
- package/build/core/asmail/keyring/index.js +82 -69
- package/build/core/id-manager/index.d.ts +43 -0
- package/build/core/{id-manager.js → id-manager/index.js} +33 -114
- package/build/core/id-manager/key-storage.d.ts +21 -0
- package/build/core/id-manager/key-storage.js +96 -0
- package/build/core/index.js +22 -25
- package/build/core/sign-in.d.ts +1 -2
- package/build/core/sign-in.js +5 -14
- package/build/core/sign-up.d.ts +2 -0
- package/build/core/sign-up.js +2 -1
- package/build/core/storage/index.d.ts +4 -2
- package/build/core/storage/index.js +36 -57
- package/build/core/storage/local/storage.d.ts +1 -1
- package/build/core/storage/synced/obj-files-gc.d.ts +1 -4
- package/build/core/storage/synced/obj-files-gc.js +1 -18
- package/build/core/storage/synced/obj-files.d.ts +11 -1
- package/build/core/storage/synced/obj-files.js +59 -34
- package/build/core/storage/synced/obj-status.d.ts +19 -7
- package/build/core/storage/synced/obj-status.js +158 -83
- package/build/core/storage/synced/storage.d.ts +7 -2
- package/build/core/storage/synced/storage.js +38 -15
- package/build/core/storage/synced/upsyncer.d.ts +4 -4
- package/build/core/storage/synced/upsyncer.js +14 -9
- package/build/ipc-via-protobuf/file.d.ts +7 -0
- package/build/ipc-via-protobuf/file.js +60 -27
- package/build/ipc-via-protobuf/fs.js +55 -38
- package/build/lib-client/3nstorage/exceptions.d.ts +13 -1
- package/build/lib-client/3nstorage/exceptions.js +9 -3
- package/build/lib-client/3nstorage/service.d.ts +6 -2
- package/build/lib-client/3nstorage/service.js +33 -17
- package/build/lib-client/3nstorage/util/file-based-json.js +2 -1
- package/build/lib-client/3nstorage/util/for-arrays.d.ts +1 -0
- package/build/lib-client/3nstorage/util/for-arrays.js +32 -0
- package/build/lib-client/3nstorage/xsp-fs/common.d.ts +5 -4
- package/build/lib-client/3nstorage/xsp-fs/common.js +1 -0
- package/build/lib-client/3nstorage/xsp-fs/file-node.d.ts +5 -10
- package/build/lib-client/3nstorage/xsp-fs/file-node.js +43 -45
- package/build/lib-client/3nstorage/xsp-fs/file.d.ts +7 -6
- package/build/lib-client/3nstorage/xsp-fs/file.js +14 -20
- package/build/lib-client/3nstorage/xsp-fs/folder-node.d.ts +16 -5
- package/build/lib-client/3nstorage/xsp-fs/folder-node.js +238 -68
- package/build/lib-client/3nstorage/xsp-fs/fs.d.ts +18 -17
- package/build/lib-client/3nstorage/xsp-fs/fs.js +32 -37
- package/build/lib-client/3nstorage/xsp-fs/node-in-fs.d.ts +15 -11
- package/build/lib-client/3nstorage/xsp-fs/node-in-fs.js +72 -22
- package/build/lib-client/3nstorage/xsp-fs/xsp-payload-v1.js +1 -1
- package/build/lib-client/local-files/device-fs.js +11 -11
- package/build/lib-client/objs-on-disk/obj-on-disk.d.ts +5 -2
- package/build/lib-client/objs-on-disk/obj-on-disk.js +16 -1
- package/build/lib-client/user-with-mid-session.d.ts +2 -1
- package/build/lib-client/user-with-mid-session.js +7 -1
- package/build/lib-common/async-fs-node.js +8 -8
- package/build/lib-common/exceptions/file.d.ts +4 -2
- package/build/lib-common/exceptions/file.js +24 -58
- package/build/lib-common/ipc/generic-ipc.js +5 -4
- package/build/lib-common/objs-on-disk/file-layout.js +1 -1
- package/build/lib-common/objs-on-disk/utils.js +1 -1
- package/build/lib-common/service-api/3nstorage/owner.d.ts +8 -9
- package/build/lib-common/service-api/3nstorage/owner.js +2 -1
- package/build/protos/asmail.proto.js +5943 -4348
- package/build/protos/file.proto.js +874 -0
- package/build/protos/fs.proto.js +7014 -5419
- package/package.json +3 -2
- package/protos/file.proto +23 -7
- package/protos/fs.proto +27 -13
- package/build/core/id-manager.d.ts +0 -46
|
@@ -25,35 +25,15 @@ export interface MsgKeyInfo {
|
|
|
25
25
|
declare type WritableFS = web3n.files.WritableFS;
|
|
26
26
|
declare type SendingResources = ResourcesForSending['correspondents'];
|
|
27
27
|
declare type ReceptionResources = ResourcesForReceiving['correspondents'];
|
|
28
|
-
export
|
|
29
|
-
private readonly cryptor;
|
|
30
|
-
private readonly publishedKeys;
|
|
31
|
-
/**
|
|
32
|
-
* This is a map from correspondents' canonical addresses to key objects.
|
|
33
|
-
*/
|
|
34
|
-
private readonly corrKeys;
|
|
35
|
-
readonly pairIdToEmailMap: IdToEmailMap;
|
|
36
|
-
private storage;
|
|
37
|
-
constructor(cryptor: AsyncSBoxCryptor, publishedKeys: ConfigOfASMailServer['publishedKeys']);
|
|
38
|
-
private addCorrespondent;
|
|
39
|
-
private init;
|
|
40
|
-
static makeAndStart(cryptor: AsyncSBoxCryptor, fs: WritableFS, publishedKeys: ConfigOfASMailServer['publishedKeys']): Promise<KeyRing>;
|
|
41
|
-
saveChanges(): void;
|
|
28
|
+
export interface KeyRing {
|
|
42
29
|
needIntroKeyFor: SendingResources['needIntroKeyFor'];
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
private findEstablishedReceptionPairs;
|
|
47
|
-
private decryptMsgKeyWithEstablishedPair;
|
|
48
|
-
/**
|
|
49
|
-
* This method updates message counts and a timestamp in a given reception
|
|
50
|
-
* pair.
|
|
51
|
-
* @param rp is a sending pair, in which changes should be done. Note this
|
|
52
|
-
* must be a shared structure at this point, not a copy of a pair.
|
|
53
|
-
* @param msgCount is a message count that should be added to the pair.
|
|
54
|
-
*/
|
|
55
|
-
private updateReceivedMsgCountIn;
|
|
56
|
-
private absorbSuggestedNextKeyPair;
|
|
57
|
-
readonly decrypt: ReceptionResources['msgDecryptor'];
|
|
30
|
+
generateKeysToSend: SendingResources['generateKeysToSend'];
|
|
31
|
+
nextCrypto: SendingResources['nextCrypto'];
|
|
32
|
+
decrypt: ReceptionResources['msgDecryptor'];
|
|
58
33
|
close(): Promise<void>;
|
|
59
34
|
}
|
|
35
|
+
export declare function makeAndKeyRing(cryptor: AsyncSBoxCryptor, fs: WritableFS, publishedKeys: ConfigOfASMailServer['publishedKeys']): Promise<KeyRing>;
|
|
36
|
+
export interface KeyPairsStorage {
|
|
37
|
+
pairIdToEmailMap: IdToEmailMap;
|
|
38
|
+
saveChanges: () => void;
|
|
39
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2015 - 2018 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2015 - 2018, 2022 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,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.
|
|
19
|
+
exports.makeAndKeyRing = exports.KEY_USE = void 0;
|
|
20
20
|
const correspondent_keys_1 = require("./correspondent-keys");
|
|
21
21
|
const id_to_email_map_1 = require("./id-to-email-map");
|
|
22
22
|
const common_1 = require("./common");
|
|
@@ -27,9 +27,14 @@ const buffer_utils_1 = require("../../../lib-common/buffer-utils");
|
|
|
27
27
|
const canonical_address_1 = require("../../../lib-common/canonical-address");
|
|
28
28
|
const common_2 = require("../delivery/common");
|
|
29
29
|
const keyring_storage_1 = require("./keyring-storage");
|
|
30
|
+
const assert_1 = require("../../../lib-common/assert");
|
|
30
31
|
var common_3 = require("./common");
|
|
31
32
|
Object.defineProperty(exports, "KEY_USE", { enumerable: true, get: function () { return common_3.KEY_USE; } });
|
|
32
|
-
|
|
33
|
+
function makeAndKeyRing(cryptor, fs, publishedKeys) {
|
|
34
|
+
return KRing.makeAndStart(cryptor, fs, publishedKeys);
|
|
35
|
+
}
|
|
36
|
+
exports.makeAndKeyRing = makeAndKeyRing;
|
|
37
|
+
class KRing {
|
|
33
38
|
constructor(cryptor, publishedKeys) {
|
|
34
39
|
this.cryptor = cryptor;
|
|
35
40
|
this.publishedKeys = publishedKeys;
|
|
@@ -39,7 +44,11 @@ class KeyRing {
|
|
|
39
44
|
this.corrKeys = new Map();
|
|
40
45
|
this.pairIdToEmailMap = new id_to_email_map_1.IdToEmailMap();
|
|
41
46
|
this.storage = undefined;
|
|
42
|
-
this.
|
|
47
|
+
this.asKeyPairsStorage = {
|
|
48
|
+
pairIdToEmailMap: this.pairIdToEmailMap,
|
|
49
|
+
saveChanges: this.saveChanges.bind(this)
|
|
50
|
+
};
|
|
51
|
+
this.needIntroKeyFor = address => {
|
|
43
52
|
address = (0, canonical_address_1.toCanonicalAddress)(address);
|
|
44
53
|
return !this.corrKeys.has(address);
|
|
45
54
|
};
|
|
@@ -68,65 +77,14 @@ class KeyRing {
|
|
|
68
77
|
const suggestPair = await ck.suggestPair();
|
|
69
78
|
return suggestPair;
|
|
70
79
|
};
|
|
71
|
-
this.decrypt = async (msgMeta, getMainObjHeader, getOpenedMsg, checkMidKeyCerts) => {
|
|
72
|
-
let decrInfo;
|
|
73
|
-
let incrMsgCount;
|
|
74
|
-
let openedMsg;
|
|
75
|
-
if (msgMeta.pid) {
|
|
76
|
-
const r = await this.decryptMsgKeyWithEstablishedPair(msgMeta.pid, getMainObjHeader);
|
|
77
|
-
if (!r) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
decrInfo = r.keyInfo;
|
|
81
|
-
incrMsgCount = r.incrMsgCount;
|
|
82
|
-
openedMsg = await getOpenedMsg(decrInfo.key, decrInfo.msgKeyPackLen);
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
decrInfo = await this.decryptMsgKeyWithIntroPair(msgMeta.recipientKid, msgMeta.senderPKey, getMainObjHeader);
|
|
86
|
-
if (!decrInfo) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
openedMsg = await getOpenedMsg(decrInfo.key, decrInfo.msgKeyPackLen);
|
|
90
|
-
const certs = openedMsg.introCryptoCerts;
|
|
91
|
-
const { address, pkey } = await checkMidKeyCerts(certs);
|
|
92
|
-
if (pkey.k !== msgMeta.senderPKey) {
|
|
93
|
-
throw new Error(`Key certificates in the message are not for a key that encrypted this message.`);
|
|
94
|
-
}
|
|
95
|
-
decrInfo.correspondent = (0, canonical_address_1.toCanonicalAddress)(address);
|
|
96
|
-
}
|
|
97
|
-
// check that sender is the same as the trusted correspondent
|
|
98
|
-
const sender = openedMsg.sender;
|
|
99
|
-
if (!sender || !(0, canonical_address_1.areAddressesEqual)(sender, decrInfo.correspondent)) {
|
|
100
|
-
throw new Error(`Mismatch between message sender field '${sender}', and address '${decrInfo.correspondent}', associated with decrypting key.`);
|
|
101
|
-
}
|
|
102
|
-
// update received msg counts and a time stamp
|
|
103
|
-
if (incrMsgCount) {
|
|
104
|
-
incrMsgCount(openedMsg.msgCount);
|
|
105
|
-
}
|
|
106
|
-
// absorb next crypto
|
|
107
|
-
const pair = openedMsg.nextCrypto;
|
|
108
|
-
if (pair) {
|
|
109
|
-
if (msgMeta.recipientKid) {
|
|
110
|
-
if (!pair.isSenderIntroKey) {
|
|
111
|
-
throw new Error(`Introductory message is not referencing used intro key in the next crypto`);
|
|
112
|
-
}
|
|
113
|
-
if (msgMeta.recipientKid !== pair.senderKid) {
|
|
114
|
-
throw new Error(`Introductory message is referencing wrong key in the next crypto`);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
this.absorbSuggestedNextKeyPair(decrInfo.correspondent, pair);
|
|
118
|
-
}
|
|
119
|
-
return { decrInfo, openedMsg };
|
|
120
|
-
};
|
|
121
80
|
Object.seal(this);
|
|
122
81
|
}
|
|
123
82
|
addCorrespondent(address, serialForm) {
|
|
124
83
|
const ck = (serialForm ?
|
|
125
|
-
new correspondent_keys_1.CorrespondentKeys(this, undefined, serialForm) :
|
|
126
|
-
new correspondent_keys_1.CorrespondentKeys(this, address));
|
|
84
|
+
new correspondent_keys_1.CorrespondentKeys(this.asKeyPairsStorage, undefined, serialForm) :
|
|
85
|
+
new correspondent_keys_1.CorrespondentKeys(this.asKeyPairsStorage, address));
|
|
127
86
|
if (this.corrKeys.has(ck.correspondent)) {
|
|
128
|
-
throw new Error(
|
|
129
|
-
" is already present.");
|
|
87
|
+
throw new Error(`Correspondent with address ${ck.correspondent} is already present.`);
|
|
130
88
|
}
|
|
131
89
|
this.corrKeys.set(ck.correspondent, ck);
|
|
132
90
|
if (serialForm) {
|
|
@@ -135,9 +93,7 @@ class KeyRing {
|
|
|
135
93
|
return ck;
|
|
136
94
|
}
|
|
137
95
|
async init(fs) {
|
|
138
|
-
|
|
139
|
-
throw new Error("Keyring has already been initialized.");
|
|
140
|
-
}
|
|
96
|
+
(0, assert_1.assert)(!this.storage);
|
|
141
97
|
this.storage = (0, keyring_storage_1.makeKeyringStorage)(fs);
|
|
142
98
|
await this.storage.start();
|
|
143
99
|
const serialForm = await this.storage.load();
|
|
@@ -155,9 +111,15 @@ class KeyRing {
|
|
|
155
111
|
}
|
|
156
112
|
}
|
|
157
113
|
static async makeAndStart(cryptor, fs, publishedKeys) {
|
|
158
|
-
const kr = new
|
|
114
|
+
const kr = new KRing(cryptor, publishedKeys);
|
|
159
115
|
await kr.init(fs);
|
|
160
|
-
return
|
|
116
|
+
return {
|
|
117
|
+
close: kr.close.bind(kr),
|
|
118
|
+
decrypt: kr.decrypt.bind(kr),
|
|
119
|
+
generateKeysToSend: kr.generateKeysToSend.bind(kr),
|
|
120
|
+
needIntroKeyFor: kr.needIntroKeyFor.bind(kr),
|
|
121
|
+
nextCrypto: kr.nextCrypto.bind(kr)
|
|
122
|
+
};
|
|
161
123
|
}
|
|
162
124
|
saveChanges() {
|
|
163
125
|
// pack bytes that need to be encrypted and saved
|
|
@@ -253,9 +215,10 @@ class KeyRing {
|
|
|
253
215
|
const corrKeys = this.corrKeys.get(keyInfo.correspondent);
|
|
254
216
|
corrKeys.markPairAsInUse(pair);
|
|
255
217
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
218
|
+
return {
|
|
219
|
+
keyInfo,
|
|
220
|
+
incrMsgCount: msgCount => this.updateReceivedMsgCountIn(pair, msgCount)
|
|
221
|
+
};
|
|
259
222
|
}
|
|
260
223
|
catch (err) {
|
|
261
224
|
if (!err.failedCipherVerification) {
|
|
@@ -301,13 +264,63 @@ class KeyRing {
|
|
|
301
264
|
}
|
|
302
265
|
this.saveChanges();
|
|
303
266
|
}
|
|
267
|
+
async decrypt(msgMeta, getMainObjHeader, getOpenedMsg, checkMidKeyCerts) {
|
|
268
|
+
let decrInfo;
|
|
269
|
+
let incrMsgCount;
|
|
270
|
+
let openedMsg;
|
|
271
|
+
if (msgMeta.pid) {
|
|
272
|
+
const r = await this.decryptMsgKeyWithEstablishedPair(msgMeta.pid, getMainObjHeader);
|
|
273
|
+
if (!r) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
decrInfo = r.keyInfo;
|
|
277
|
+
incrMsgCount = r.incrMsgCount;
|
|
278
|
+
openedMsg = await getOpenedMsg(decrInfo.key, decrInfo.msgKeyPackLen);
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
decrInfo = await this.decryptMsgKeyWithIntroPair(msgMeta.recipientKid, msgMeta.senderPKey, getMainObjHeader);
|
|
282
|
+
if (!decrInfo) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
openedMsg = await getOpenedMsg(decrInfo.key, decrInfo.msgKeyPackLen);
|
|
286
|
+
const certs = openedMsg.introCryptoCerts;
|
|
287
|
+
const { address, pkey } = await checkMidKeyCerts(certs);
|
|
288
|
+
if (pkey.k !== msgMeta.senderPKey) {
|
|
289
|
+
throw new Error(`Key certificates in the message are not for a key that encrypted this message.`);
|
|
290
|
+
}
|
|
291
|
+
decrInfo.correspondent = (0, canonical_address_1.toCanonicalAddress)(address);
|
|
292
|
+
}
|
|
293
|
+
// check that sender is the same as the trusted correspondent
|
|
294
|
+
const sender = openedMsg.sender;
|
|
295
|
+
if (!sender || !(0, canonical_address_1.areAddressesEqual)(sender, decrInfo.correspondent)) {
|
|
296
|
+
throw new Error(`Mismatch between message sender field '${sender}', and address '${decrInfo.correspondent}', associated with decrypting key.`);
|
|
297
|
+
}
|
|
298
|
+
// update received msg counts and a time stamp
|
|
299
|
+
if (incrMsgCount) {
|
|
300
|
+
incrMsgCount(openedMsg.msgCount);
|
|
301
|
+
}
|
|
302
|
+
// absorb next crypto
|
|
303
|
+
const pair = openedMsg.nextCrypto;
|
|
304
|
+
if (pair) {
|
|
305
|
+
if (msgMeta.recipientKid) {
|
|
306
|
+
if (!pair.isSenderIntroKey) {
|
|
307
|
+
throw new Error(`Introductory message is not referencing used intro key in the next crypto`);
|
|
308
|
+
}
|
|
309
|
+
if (msgMeta.recipientKid !== pair.senderKid) {
|
|
310
|
+
throw new Error(`Introductory message is referencing wrong key in the next crypto`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
this.absorbSuggestedNextKeyPair(decrInfo.correspondent, pair);
|
|
314
|
+
}
|
|
315
|
+
return { decrInfo, openedMsg };
|
|
316
|
+
}
|
|
317
|
+
;
|
|
304
318
|
close() {
|
|
305
319
|
return this.storage.close();
|
|
306
320
|
}
|
|
307
321
|
}
|
|
308
|
-
|
|
309
|
-
Object.freeze(
|
|
310
|
-
Object.freeze(KeyRing);
|
|
322
|
+
Object.freeze(KRing.prototype);
|
|
323
|
+
Object.freeze(KRing);
|
|
311
324
|
function msgKeyPackLenForPair(p) {
|
|
312
325
|
return (0, common_1.msgKeyPackSizeFor)(p.recipientKey.skey.alg);
|
|
313
326
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { user as mid } from '../../lib-common/mid-sigs-NaCl-Ed';
|
|
2
|
+
import { JsonKey } from '../../lib-common/jwkeys';
|
|
3
|
+
import { GenerateKey } from '../sign-in';
|
|
4
|
+
import { LogError, LogWarning } from '../../lib-client/logging/log-to-file';
|
|
5
|
+
import { NetClient } from '../../lib-client/request-utils';
|
|
6
|
+
import { ServiceLocator } from '../../lib-client/service-locator';
|
|
7
|
+
declare type WritableFS = web3n.files.WritableFS;
|
|
8
|
+
/**
|
|
9
|
+
* This function completes provisioning process, returning a promise, resolvable
|
|
10
|
+
* to either true, when all is done, or to false, when challenge reply is not
|
|
11
|
+
* accepted by the server.
|
|
12
|
+
*/
|
|
13
|
+
export interface CompleteProvisioning {
|
|
14
|
+
keyParams: any;
|
|
15
|
+
complete(defaultSKey: Uint8Array): Promise<boolean>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* This returns a promise, resolvable to mailerId signer.
|
|
19
|
+
*/
|
|
20
|
+
export declare type GetSigner = () => Promise<mid.MailerIdSigner>;
|
|
21
|
+
export declare type SetupManagerStorage = (fs: WritableFS, keysToSave?: JsonKey[]) => Promise<void>;
|
|
22
|
+
export declare class IdManager {
|
|
23
|
+
private readonly store;
|
|
24
|
+
private readonly makeNet;
|
|
25
|
+
private readonly midServiceFor;
|
|
26
|
+
private address;
|
|
27
|
+
private signer;
|
|
28
|
+
private provisioningProc;
|
|
29
|
+
private constructor();
|
|
30
|
+
static initWithoutStore(address: string, resolver: ServiceLocator, makeNet: () => NetClient, logError: LogError, logWarning: LogWarning): Promise<((midLoginKey: GenerateKey | Uint8Array) => Promise<{
|
|
31
|
+
idManager: IdManager;
|
|
32
|
+
setupManagerStorage: SetupManagerStorage;
|
|
33
|
+
} | undefined>) | undefined>;
|
|
34
|
+
static initFromCachedStore(address: string, fs: WritableFS, resolver: ServiceLocator, makeNet: () => NetClient, logError: LogError, logWarning: LogWarning): Promise<IdManager | undefined>;
|
|
35
|
+
private startProvisionWithoutSavedKey;
|
|
36
|
+
private provisionUsingSavedKey;
|
|
37
|
+
getId(): string;
|
|
38
|
+
getSigner: GetSigner;
|
|
39
|
+
isProvisionedAndValid(): boolean;
|
|
40
|
+
makeMailerIdCAP(): Service;
|
|
41
|
+
}
|
|
42
|
+
declare type Service = web3n.mailerid.Service;
|
|
43
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2015 - 2018, 2020 -
|
|
3
|
+
Copyright (C) 2015 - 2018, 2020 - 2022 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
|
|
@@ -18,24 +18,21 @@
|
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.IdManager = void 0;
|
|
20
20
|
const ecma_nacl_1 = require("ecma-nacl");
|
|
21
|
-
const provisioner_1 = require("
|
|
22
|
-
const jwkeys_1 = require("
|
|
23
|
-
const synced_1 = require("
|
|
24
|
-
const login_1 = require("
|
|
21
|
+
const provisioner_1 = require("../../lib-client/mailer-id/provisioner");
|
|
22
|
+
const jwkeys_1 = require("../../lib-common/jwkeys");
|
|
23
|
+
const synced_1 = require("../../lib-common/processes/synced");
|
|
24
|
+
const login_1 = require("../../lib-client/mailer-id/login");
|
|
25
|
+
const key_storage_1 = require("./key-storage");
|
|
25
26
|
const CERTIFICATE_DURATION_SECONDS = 16 * 60 * 60;
|
|
26
27
|
const ASSERTION_VALIDITY = 15 * 60;
|
|
27
28
|
const MIN_SECS_LEFT_ASSUMED_OK = 10 * 60;
|
|
28
|
-
const LOGIN_KEY_FILE_NAME = 'login-keys';
|
|
29
29
|
class IdManager {
|
|
30
|
-
constructor(makeNet, midServiceFor,
|
|
30
|
+
constructor(store, makeNet, midServiceFor, address) {
|
|
31
|
+
this.store = store;
|
|
31
32
|
this.makeNet = makeNet;
|
|
32
33
|
this.midServiceFor = midServiceFor;
|
|
33
|
-
this.logError = logError;
|
|
34
|
-
this.logWarning = logWarning;
|
|
35
34
|
this.address = address;
|
|
36
35
|
this.signer = undefined;
|
|
37
|
-
this.localFS = undefined;
|
|
38
|
-
this.syncedFS = undefined;
|
|
39
36
|
this.provisioningProc = new synced_1.SingleProc();
|
|
40
37
|
this.getSigner = async () => {
|
|
41
38
|
if (!this.address) {
|
|
@@ -46,117 +43,46 @@ class IdManager {
|
|
|
46
43
|
}
|
|
47
44
|
return this.signer;
|
|
48
45
|
};
|
|
49
|
-
if (localFS) {
|
|
50
|
-
this.localFS = localFS;
|
|
51
|
-
}
|
|
52
46
|
Object.seal(this);
|
|
53
47
|
}
|
|
54
|
-
static async initInOneStepWithoutStore(address, midLoginKey, resolver, makeNet, logError, logWarning) {
|
|
55
|
-
const stepTwo = await IdManager.initWithoutStore(address, resolver, makeNet, logError, logWarning);
|
|
56
|
-
if (!stepTwo) {
|
|
57
|
-
throw new Error(`MailerId server doesn't recognize identity ${address}`);
|
|
58
|
-
}
|
|
59
|
-
return stepTwo(midLoginKey);
|
|
60
|
-
}
|
|
61
48
|
static async initWithoutStore(address, resolver, makeNet, logError, logWarning) {
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
|
|
49
|
+
const { store, setupManagerStorage } = key_storage_1.IdKeysStorage.makeWithoutStorage(logError, logWarning);
|
|
50
|
+
const idManager = new IdManager(store, makeNet, resolver, address);
|
|
51
|
+
const provisioning = await idManager.startProvisionWithoutSavedKey(address);
|
|
52
|
+
if (!provisioning) {
|
|
65
53
|
return;
|
|
66
54
|
}
|
|
67
55
|
return async (midLoginKey) => {
|
|
68
56
|
const key = ((typeof midLoginKey === 'function') ?
|
|
69
|
-
await midLoginKey(
|
|
57
|
+
await midLoginKey(provisioning.keyParams) :
|
|
70
58
|
midLoginKey);
|
|
71
|
-
const isDone = await
|
|
59
|
+
const isDone = await provisioning.complete(key);
|
|
72
60
|
key.fill(0);
|
|
73
|
-
|
|
61
|
+
if (!isDone) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
idManager,
|
|
66
|
+
setupManagerStorage: (fs, keys) => setupManagerStorage(fs, (keys ? {
|
|
67
|
+
address: idManager.address,
|
|
68
|
+
keys
|
|
69
|
+
} : undefined))
|
|
70
|
+
};
|
|
74
71
|
};
|
|
75
72
|
}
|
|
76
|
-
static async
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
throw new Error(`Expected local storage is typed as ${localFS.type}`);
|
|
80
|
-
}
|
|
81
|
-
idMan.localFS = localFS;
|
|
73
|
+
static async initFromCachedStore(address, fs, resolver, makeNet, logError, logWarning) {
|
|
74
|
+
const store = key_storage_1.IdKeysStorage.makeWithStorage(fs, logError, logWarning);
|
|
75
|
+
const idManager = new IdManager(store, makeNet, resolver, address);
|
|
82
76
|
try {
|
|
83
|
-
await
|
|
77
|
+
await idManager.provisionUsingSavedKey();
|
|
78
|
+
return idManager;
|
|
84
79
|
}
|
|
85
80
|
catch (err) {
|
|
86
81
|
await logError(err, `Can't initialize id manager from local store`);
|
|
87
82
|
return;
|
|
88
83
|
}
|
|
89
|
-
return idMan;
|
|
90
|
-
}
|
|
91
|
-
async ensureLocalCacheOfKeys() {
|
|
92
|
-
if (!this.localFS || !this.syncedFS) {
|
|
93
|
-
throw new Error(`Id manager's storages are not set.`);
|
|
94
|
-
}
|
|
95
|
-
const keysCached = await this.localFS.checkFilePresence(LOGIN_KEY_FILE_NAME);
|
|
96
|
-
if (keysCached) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
try {
|
|
100
|
-
const bytes = await this.syncedFS.readBytes(LOGIN_KEY_FILE_NAME);
|
|
101
|
-
await this.localFS.writeBytes(LOGIN_KEY_FILE_NAME, bytes);
|
|
102
|
-
bytes.fill(0);
|
|
103
|
-
}
|
|
104
|
-
catch (err) {
|
|
105
|
-
await this.logError(err, `Fail to ensure local cache of MailerId login keys.`);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
async getSavedKey() {
|
|
109
|
-
if (!this.localFS) {
|
|
110
|
-
throw new Error(`Id manager's local storage is not set.`);
|
|
111
|
-
}
|
|
112
|
-
const json = await this.localFS.readJSONFile(LOGIN_KEY_FILE_NAME).catch(notFoundOrReThrow);
|
|
113
|
-
if (json) {
|
|
114
|
-
return json.keys[0];
|
|
115
|
-
}
|
|
116
|
-
if (this.syncedFS) {
|
|
117
|
-
const json = await this.syncedFS.readJSONFile(LOGIN_KEY_FILE_NAME).catch(notFoundOrReThrow);
|
|
118
|
-
if (json) {
|
|
119
|
-
await this.ensureLocalCacheOfKeys();
|
|
120
|
-
return json.keys[0];
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
await this.logWarning(`IdManager: there is no login MailerId login keys`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
async setStorages(localFS, syncedFS, keysToSave) {
|
|
129
|
-
if (localFS) {
|
|
130
|
-
if (localFS.type !== 'local') {
|
|
131
|
-
throw new Error(`Expected local storage is typed as ${localFS.type}`);
|
|
132
|
-
}
|
|
133
|
-
this.localFS = localFS;
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
if (!this.localFS) {
|
|
137
|
-
throw new Error(`Local storage is not given`);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
if (syncedFS.type !== 'synced') {
|
|
141
|
-
throw new Error(`Expected synced storage is typed as ${syncedFS.type}`);
|
|
142
|
-
}
|
|
143
|
-
this.syncedFS = syncedFS;
|
|
144
|
-
if (keysToSave) {
|
|
145
|
-
const json = {
|
|
146
|
-
address: this.address,
|
|
147
|
-
keys: keysToSave
|
|
148
|
-
};
|
|
149
|
-
await this.localFS.writeJSONFile(LOGIN_KEY_FILE_NAME, json);
|
|
150
|
-
await this.syncedFS.writeJSONFile(LOGIN_KEY_FILE_NAME, json);
|
|
151
|
-
// XXX must add work with not-online condition
|
|
152
|
-
await this.syncedFS.v.sync.upload(LOGIN_KEY_FILE_NAME);
|
|
153
|
-
await this.syncedFS.v.sync.upload('');
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
await this.ensureLocalCacheOfKeys();
|
|
157
|
-
}
|
|
158
84
|
}
|
|
159
|
-
async
|
|
85
|
+
async startProvisionWithoutSavedKey(address) {
|
|
160
86
|
const midUrl = await this.midServiceFor(address);
|
|
161
87
|
const provisioner = new provisioner_1.MailerIdProvisioner(address, midUrl, this.makeNet());
|
|
162
88
|
try {
|
|
@@ -202,7 +128,7 @@ class IdManager {
|
|
|
202
128
|
proc = this.provisioningProc.start(async () => {
|
|
203
129
|
const midUrl = await this.midServiceFor(this.address);
|
|
204
130
|
const provisioner = new provisioner_1.MailerIdProvisioner(this.address, midUrl, this.makeNet());
|
|
205
|
-
const key = await this.getSavedKey();
|
|
131
|
+
const key = await this.store.getSavedKey();
|
|
206
132
|
if (!key) {
|
|
207
133
|
throw new Error(`No saved MailerId login key can be found`);
|
|
208
134
|
}
|
|
@@ -245,15 +171,8 @@ class IdManager {
|
|
|
245
171
|
}
|
|
246
172
|
}
|
|
247
173
|
exports.IdManager = IdManager;
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
* exception, and re-throws all other exceptions/errors.
|
|
251
|
-
*/
|
|
252
|
-
function notFoundOrReThrow(exc) {
|
|
253
|
-
if (!exc.notFound) {
|
|
254
|
-
throw exc;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
174
|
+
Object.freeze(IdManager.prototype);
|
|
175
|
+
Object.freeze(IdManager);
|
|
257
176
|
async function doMidLogin(loginUrl, userId, net, signer) {
|
|
258
177
|
const { sessionId, redirect } = await (0, login_1.startMidSession)(userId, net, loginUrl);
|
|
259
178
|
if (!sessionId) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { LogError, LogWarning } from "../../lib-client/logging/log-to-file";
|
|
2
|
+
import { JsonKey } from "../../lib-common/jwkeys";
|
|
3
|
+
declare type WritableFS = web3n.files.WritableFS;
|
|
4
|
+
export interface LoginKeysJSON {
|
|
5
|
+
address: string;
|
|
6
|
+
keys: JsonKey[];
|
|
7
|
+
}
|
|
8
|
+
export declare class IdKeysStorage {
|
|
9
|
+
private readonly logError;
|
|
10
|
+
private readonly logWarning;
|
|
11
|
+
private fs;
|
|
12
|
+
private constructor();
|
|
13
|
+
static makeWithStorage(fs: WritableFS, logError: LogError, logWarning: LogWarning): IdKeysStorage;
|
|
14
|
+
static makeWithoutStorage(logError: LogError, logWarning: LogWarning): {
|
|
15
|
+
store: IdKeysStorage;
|
|
16
|
+
setupManagerStorage: (fs: WritableFS, keysToSave?: LoginKeysJSON) => Promise<void>;
|
|
17
|
+
};
|
|
18
|
+
getSavedKey(): Promise<JsonKey | undefined>;
|
|
19
|
+
private setStorageFS;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (C) 2022 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.IdKeysStorage = void 0;
|
|
20
|
+
const assert_1 = require("../../lib-common/assert");
|
|
21
|
+
const error_1 = require("../../lib-common/exceptions/error");
|
|
22
|
+
const LOGIN_KEY_FILE_NAME = 'login-keys';
|
|
23
|
+
class IdKeysStorage {
|
|
24
|
+
constructor(logError, logWarning, fs) {
|
|
25
|
+
this.logError = logError;
|
|
26
|
+
this.logWarning = logWarning;
|
|
27
|
+
this.fs = undefined;
|
|
28
|
+
if (fs) {
|
|
29
|
+
(0, assert_1.assert)(fs.type === 'synced');
|
|
30
|
+
this.fs = fs;
|
|
31
|
+
}
|
|
32
|
+
Object.seal(this);
|
|
33
|
+
}
|
|
34
|
+
static makeWithStorage(fs, logError, logWarning) {
|
|
35
|
+
return new IdKeysStorage(logError, logWarning, fs);
|
|
36
|
+
}
|
|
37
|
+
static makeWithoutStorage(logError, logWarning) {
|
|
38
|
+
const store = new IdKeysStorage(logError, logWarning);
|
|
39
|
+
return {
|
|
40
|
+
store,
|
|
41
|
+
setupManagerStorage: (fs, keys) => store.setStorageFS(fs, keys)
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async getSavedKey() {
|
|
45
|
+
var _a, _b;
|
|
46
|
+
if (!((_b = (_a = this.fs) === null || _a === void 0 ? void 0 : _a.v) === null || _b === void 0 ? void 0 : _b.sync)) {
|
|
47
|
+
throw new Error(`Id manager's storages are not set.`);
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const json = await this.fs.readJSONFile(LOGIN_KEY_FILE_NAME);
|
|
51
|
+
return json.keys[0];
|
|
52
|
+
}
|
|
53
|
+
catch (exc) {
|
|
54
|
+
if (!exc.notFound) {
|
|
55
|
+
throw exc;
|
|
56
|
+
}
|
|
57
|
+
await this.fs.v.sync.updateStatusInfo('');
|
|
58
|
+
await this.fs.v.sync.adoptRemote('');
|
|
59
|
+
if (await this.fs.checkFilePresence(LOGIN_KEY_FILE_NAME)) {
|
|
60
|
+
return this.getSavedKey();
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
await this.logWarning(`IdManager: no saved login MailerId keys`);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async setStorageFS(fs, keysToSave) {
|
|
69
|
+
(0, assert_1.assert)(!this.fs);
|
|
70
|
+
(0, assert_1.assert)(fs.type === 'synced');
|
|
71
|
+
this.fs = fs;
|
|
72
|
+
if (keysToSave) {
|
|
73
|
+
await this.fs.writeJSONFile(LOGIN_KEY_FILE_NAME, keysToSave);
|
|
74
|
+
// XXX must add work with not-online condition
|
|
75
|
+
await this.fs.v.sync.upload(LOGIN_KEY_FILE_NAME);
|
|
76
|
+
await this.fs.v.sync.upload('');
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
try {
|
|
80
|
+
await this.fs.readJSONFile(LOGIN_KEY_FILE_NAME);
|
|
81
|
+
}
|
|
82
|
+
catch (exc) {
|
|
83
|
+
throw (0, error_1.errWithCause)(exc, `Fail expection read of login MailerId keys from the storage`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.IdKeysStorage = IdKeysStorage;
|
|
89
|
+
Object.freeze(IdKeysStorage.prototype);
|
|
90
|
+
Object.freeze(IdKeysStorage);
|
|
91
|
+
function notFoundOrReThrow(exc) {
|
|
92
|
+
if (!exc.notFound) {
|
|
93
|
+
throw exc;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
Object.freeze(exports);
|