core-3nweb-client-lib 0.40.0 → 0.41.0
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/mailerid.d.ts +51 -1
- package/build/core/asmail/key-verification.d.ts +5 -0
- package/build/core/asmail/key-verification.js +6 -4
- package/build/core/id-manager/index.d.ts +2 -2
- package/build/core/id-manager/index.js +30 -0
- package/build/core/id-manager/mailerid-cap-ipc.js +6 -2
- package/build/core/index.js +8 -3
- package/build/core-ipc/json-ipc-wrapping/json-n-binary.js +1 -1
- package/build/lib-client/asmail/sender.d.ts +2 -2
- package/build/lib-client/asmail/sender.js +1 -1
- package/build/lib-client/mailer-id/login.d.ts +2 -2
- package/build/lib-client/mailer-id/login.js +1 -1
- package/build/lib-client/mailer-id/provisioner.d.ts +2 -2
- package/build/lib-client/mailer-id/provisioner.js +6 -6
- package/build/lib-client/user-with-mid-session.d.ts +3 -3
- package/build/lib-client/user-with-mid-session.js +1 -1
- package/build/lib-common/mailerid-sigs/id-provider.d.ts +64 -0
- package/build/lib-common/mailerid-sigs/id-provider.js +174 -0
- package/build/lib-common/mailerid-sigs/index.d.ts +44 -0
- package/build/lib-common/mailerid-sigs/index.js +50 -0
- package/build/lib-common/mailerid-sigs/relying-party.d.ts +59 -0
- package/build/lib-common/mailerid-sigs/relying-party.js +237 -0
- package/build/lib-common/mailerid-sigs/user.d.ts +60 -0
- package/build/lib-common/mailerid-sigs/user.js +149 -0
- package/build/lib-common/mailerid-sigs/utils-NaCl-Ed.d.ts +8 -0
- package/build/lib-common/mailerid-sigs/utils-NaCl-Ed.js +61 -0
- package/build/raw-3nweb-clients.d.ts +2 -2
- package/build/raw-3nweb-clients.js +1 -1
- package/package.json +1 -1
- package/build/lib-common/mid-sigs-NaCl-Ed.d.ts +0 -220
- package/build/lib-common/mid-sigs-NaCl-Ed.js +0 -560
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Copyright (C) 2020 3NSoft Inc.
|
|
2
|
+
Copyright (C) 2020, 2025 3NSoft Inc.
|
|
3
3
|
|
|
4
4
|
This program is free software: you can redistribute it and/or modify it under
|
|
5
5
|
the terms of the GNU General Public License as published by the Free Software
|
|
@@ -20,10 +20,36 @@ declare namespace web3n.mailerid {
|
|
|
20
20
|
|
|
21
21
|
interface Service {
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Returns MailerId/address of a current user.
|
|
25
|
+
*/
|
|
23
26
|
getUserId(): Promise<string>;
|
|
24
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Performs a MailerId-based login at a given url, returning session id.
|
|
30
|
+
* @param serviceUrl
|
|
31
|
+
*/
|
|
25
32
|
login(serviceUrl: string): Promise<string>;
|
|
26
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Signs given payload with current identity, returning object with
|
|
36
|
+
* signature and a complete MailerId certificates' chain of a used key.
|
|
37
|
+
* @param payload
|
|
38
|
+
*/
|
|
39
|
+
sign(payload: Uint8Array): Promise<MailerIdSignature>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Verifies given signature, returning true if it is ok.
|
|
43
|
+
* Since this is a check of MailerId signature, root certificate of a
|
|
44
|
+
* respective identity provider would have to be retrieved with a chance
|
|
45
|
+
* of related exceptions being thrown.
|
|
46
|
+
* @param midSignature
|
|
47
|
+
*/
|
|
48
|
+
verifySignature(midSignature: MailerIdSignature): Promise<{
|
|
49
|
+
cryptoCheck: boolean;
|
|
50
|
+
midProviderCheck?: MailerIdProviderCheckResult;
|
|
51
|
+
}>;
|
|
52
|
+
|
|
27
53
|
}
|
|
28
54
|
|
|
29
55
|
interface MailerIdAssertionLoad {
|
|
@@ -34,4 +60,28 @@ declare namespace web3n.mailerid {
|
|
|
34
60
|
expiresAt: number;
|
|
35
61
|
}
|
|
36
62
|
|
|
63
|
+
interface MailerIdSignature {
|
|
64
|
+
rootMidCert: keys.SignedLoad;
|
|
65
|
+
provCert: keys.SignedLoad;
|
|
66
|
+
signeeCert: keys.SignedLoad;
|
|
67
|
+
signature: keys.SignedLoad;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
type MailerIdProviderCheckResult =
|
|
71
|
+
'all-ok'
|
|
72
|
+
| 'unknown-root-cert'
|
|
73
|
+
| 'not-current-provider'
|
|
74
|
+
|'dns-not-set'
|
|
75
|
+
| 'offline-no-check'
|
|
76
|
+
| 'other-fail';
|
|
77
|
+
|
|
78
|
+
interface MailerIdException extends RuntimeException {
|
|
79
|
+
type: 'mailerid';
|
|
80
|
+
algMismatch?: true;
|
|
81
|
+
timeMismatch?: true;
|
|
82
|
+
certsMismatch?: true;
|
|
83
|
+
certMalformed?: true;
|
|
84
|
+
sigVerificationFails?: true;
|
|
85
|
+
}
|
|
86
|
+
|
|
37
87
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ServiceLocator } from '../../lib-client/service-locator';
|
|
2
2
|
import { NetClient } from '../../lib-client/request-utils';
|
|
3
3
|
type JsonKey = web3n.keys.JsonKey;
|
|
4
|
+
type SignedLoad = web3n.keys.SignedLoad;
|
|
4
5
|
type PKeyCertChain = web3n.keys.PKeyCertChain;
|
|
5
6
|
/**
|
|
6
7
|
* This returns a promise, resolvable to public key, when certificates'
|
|
@@ -12,6 +13,10 @@ type PKeyCertChain = web3n.keys.PKeyCertChain;
|
|
|
12
13
|
* @param certs is an object with a MailerId certificates chain for a public key
|
|
13
14
|
*/
|
|
14
15
|
export declare function checkAndExtractPKey(client: NetClient, resolver: ServiceLocator, address: string, certs: PKeyCertChain): Promise<JsonKey>;
|
|
16
|
+
export declare function getRootCertForKey(kid: string, resolver: ServiceLocator, client: NetClient, address: string): Promise<{
|
|
17
|
+
domain: string;
|
|
18
|
+
rootCert: SignedLoad;
|
|
19
|
+
}>;
|
|
15
20
|
/**
|
|
16
21
|
* This returns a promise, resolvable to public key and related address, when
|
|
17
22
|
* certificates' verification is successful, and rejectable in all other cases.
|
|
@@ -17,11 +17,13 @@
|
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.checkAndExtractPKey = checkAndExtractPKey;
|
|
20
|
+
exports.getRootCertForKey = getRootCertForKey;
|
|
20
21
|
exports.checkAndExtractPKeyWithAddress = checkAndExtractPKeyWithAddress;
|
|
21
22
|
const canonical_address_1 = require("../../lib-common/canonical-address");
|
|
22
|
-
const mid_sigs_NaCl_Ed_1 = require("../../lib-common/mid-sigs-NaCl-Ed");
|
|
23
23
|
const jwkeys_1 = require("../../lib-common/jwkeys");
|
|
24
24
|
const service_locator_1 = require("../../lib-client/service-locator");
|
|
25
|
+
const relying_party_1 = require("../../lib-common/mailerid-sigs/relying-party");
|
|
26
|
+
const mailerid_sigs_1 = require("../../lib-common/mailerid-sigs");
|
|
25
27
|
/**
|
|
26
28
|
* This returns a promise, resolvable to public key, when certificates'
|
|
27
29
|
* verification is successful, and rejectable in all other cases.
|
|
@@ -36,7 +38,7 @@ async function checkAndExtractPKey(client, resolver, address, certs) {
|
|
|
36
38
|
const validAt = Math.round(Date.now() / 1000);
|
|
37
39
|
// get MailerId provider's info with a root certificate(s)
|
|
38
40
|
const { domain: rootAddr, rootCert } = await getRootCertForKey(certs.provCert.kid, resolver, client, address);
|
|
39
|
-
const pkey =
|
|
41
|
+
const pkey = (0, relying_party_1.verifyPubKey)(certs.pkeyCert, address, { user: certs.userCert, prov: certs.provCert, root: rootCert }, rootAddr, validAt);
|
|
40
42
|
return pkey;
|
|
41
43
|
}
|
|
42
44
|
async function getRootCertForKey(kid, resolver, client, address) {
|
|
@@ -72,11 +74,11 @@ async function checkAndExtractPKeyWithAddress(client, resolver, certs, validAt)
|
|
|
72
74
|
address = (0, jwkeys_1.getKeyCert)(certs.pkeyCert).cert.principal.address;
|
|
73
75
|
}
|
|
74
76
|
catch (err) {
|
|
75
|
-
throw (0,
|
|
77
|
+
throw (0, mailerid_sigs_1.makeMalformedCertsException)(`Cannot read public key certificate`, err);
|
|
76
78
|
}
|
|
77
79
|
// get MailerId provider's info with a root certificate(s)
|
|
78
80
|
const { domain: rootAddr, rootCert } = await getRootCertForKey(certs.provCert.kid, resolver, client, address);
|
|
79
|
-
const pkey =
|
|
81
|
+
const pkey = (0, relying_party_1.verifyPubKey)(certs.pkeyCert, address, { user: certs.userCert, prov: certs.provCert, root: rootCert }, rootAddr, validAt);
|
|
80
82
|
return { address, pkey };
|
|
81
83
|
}
|
|
82
84
|
Object.freeze(exports);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { user as mid } from '../../lib-common/mid-sigs-NaCl-Ed';
|
|
2
1
|
import { GenerateKey } from '../startup/sign-in';
|
|
3
2
|
import { LogError, LogWarning } from '../../lib-client/logging/log-to-file';
|
|
4
3
|
import { NetClient } from '../../lib-client/request-utils';
|
|
5
4
|
import { ServiceLocator } from '../../lib-client/service-locator';
|
|
5
|
+
import { MailerIdSigner } from '../../lib-common/mailerid-sigs/user';
|
|
6
6
|
type JsonKey = web3n.keys.JsonKey;
|
|
7
7
|
type WritableFS = web3n.files.WritableFS;
|
|
8
8
|
/**
|
|
@@ -17,7 +17,7 @@ export interface CompleteProvisioning {
|
|
|
17
17
|
/**
|
|
18
18
|
* This returns a promise, resolvable to mailerId signer.
|
|
19
19
|
*/
|
|
20
|
-
export type GetSigner = () => Promise<
|
|
20
|
+
export type GetSigner = () => Promise<MailerIdSigner>;
|
|
21
21
|
export type SetupManagerStorage = (fs: WritableFS, keysToSave?: JsonKey[]) => Promise<void>;
|
|
22
22
|
export declare class IdManager {
|
|
23
23
|
private readonly store;
|
|
@@ -23,6 +23,9 @@ const jwkeys_1 = require("../../lib-common/jwkeys");
|
|
|
23
23
|
const synced_1 = require("../../lib-common/processes/synced");
|
|
24
24
|
const login_1 = require("../../lib-client/mailer-id/login");
|
|
25
25
|
const key_storage_1 = require("./key-storage");
|
|
26
|
+
const relying_party_1 = require("../../lib-common/mailerid-sigs/relying-party");
|
|
27
|
+
const key_verification_1 = require("../asmail/key-verification");
|
|
28
|
+
const json_utils_1 = require("../../lib-common/json-utils");
|
|
26
29
|
const CERTIFICATE_DURATION_SECONDS = 16 * 60 * 60;
|
|
27
30
|
const ASSERTION_VALIDITY = 15 * 60;
|
|
28
31
|
const MIN_SECS_LEFT_ASSUMED_OK = 10 * 60;
|
|
@@ -157,6 +160,33 @@ class IdManager {
|
|
|
157
160
|
login: async (serviceUrl) => {
|
|
158
161
|
const signer = await this.getSigner();
|
|
159
162
|
return doMidLogin(serviceUrl, this.getId(), this.makeNet(), signer);
|
|
163
|
+
},
|
|
164
|
+
sign: async (content) => {
|
|
165
|
+
const signer = await this.getSigner();
|
|
166
|
+
const { signature, signeeCert, provCert } = signer.sign(content);
|
|
167
|
+
const { rootCert: rootMidCert } = await (0, key_verification_1.getRootCertForKey)(signer.providerCert.kid, this.midServiceFor, this.makeNet(), signer.address);
|
|
168
|
+
return { signature, signeeCert, provCert, rootMidCert };
|
|
169
|
+
},
|
|
170
|
+
verifySignature: async (midSig) => {
|
|
171
|
+
const { signature, signeeCert, provCert, rootMidCert } = midSig;
|
|
172
|
+
const cryptoCheck = (0, relying_party_1.verifySignature)(rootMidCert, provCert, signeeCert, signature);
|
|
173
|
+
if (!cryptoCheck) {
|
|
174
|
+
return { cryptoCheck };
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
const { rootCert, domain } = await (0, key_verification_1.getRootCertForKey)(rootMidCert.kid, this.midServiceFor, this.makeNet(), (0, jwkeys_1.getKeyCert)(signeeCert).cert.principal.address);
|
|
178
|
+
if ((0, json_utils_1.deepEqual)(rootCert, rootMidCert)) {
|
|
179
|
+
return { cryptoCheck, midProviderCheck: 'all-ok' };
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
// XXX indicate more specific error cases
|
|
183
|
+
return { cryptoCheck, midProviderCheck: 'other-fail' };
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch (err) {
|
|
187
|
+
// XXX indicate more specific error cases
|
|
188
|
+
return { cryptoCheck, midProviderCheck: 'other-fail' };
|
|
189
|
+
}
|
|
160
190
|
}
|
|
161
191
|
};
|
|
162
192
|
return Object.freeze(w);
|
|
@@ -23,7 +23,9 @@ const service_side_wrap_1 = require("../../core-ipc/json-ipc-wrapping/service-si
|
|
|
23
23
|
function exposeMailerIdCAP(cap) {
|
|
24
24
|
return {
|
|
25
25
|
getUserId: (0, service_side_wrap_1.wrapReqReplySrvMethod)(cap, 'getUserId'),
|
|
26
|
-
login: (0, service_side_wrap_1.wrapReqReplySrvMethod)(cap, 'login')
|
|
26
|
+
login: (0, service_side_wrap_1.wrapReqReplySrvMethod)(cap, 'login'),
|
|
27
|
+
sign: (0, service_side_wrap_1.wrapReqReplySrvMethod)(cap, 'sign'),
|
|
28
|
+
verifySignature: (0, service_side_wrap_1.wrapReqReplySrvMethod)(cap, 'verifySignature')
|
|
27
29
|
};
|
|
28
30
|
}
|
|
29
31
|
function callMailerId(caller, objPath, method) {
|
|
@@ -32,7 +34,9 @@ function callMailerId(caller, objPath, method) {
|
|
|
32
34
|
function makeMailerIdCaller(caller, objPath) {
|
|
33
35
|
return {
|
|
34
36
|
getUserId: callMailerId(caller, objPath, 'getUserId'),
|
|
35
|
-
login: callMailerId(caller, objPath, 'login')
|
|
37
|
+
login: callMailerId(caller, objPath, 'login'),
|
|
38
|
+
sign: callMailerId(caller, objPath, 'sign'),
|
|
39
|
+
verifySignature: callMailerId(caller, objPath, 'verifySignature')
|
|
36
40
|
};
|
|
37
41
|
}
|
|
38
42
|
Object.freeze(exports);
|
package/build/core/index.js
CHANGED
|
@@ -302,7 +302,6 @@ class Core {
|
|
|
302
302
|
await this.storages.migrateCoreAppDataOnFirstRun('synced', `${constants_1.ASMAIL_APP_NAME}/config/anonymous/invites.json`, `${constants_1.ASMAIL_APP_NAME}/sending-params/anonymous-invites.json`);
|
|
303
303
|
}
|
|
304
304
|
async initCoreApps(emitBootEvent) {
|
|
305
|
-
// XXX push events to this.bootProcObserver
|
|
306
305
|
var _a;
|
|
307
306
|
try {
|
|
308
307
|
const address = this.idManager.getId();
|
|
@@ -322,6 +321,7 @@ class Core {
|
|
|
322
321
|
emitBootEvent({ isError: true, message: (_a = err.message) !== null && _a !== void 0 ? _a : (0, error_1.stringifyErr)(err) });
|
|
323
322
|
throw (0, error_1.errWithCause)(err, 'Failed to initialize core apps');
|
|
324
323
|
}
|
|
324
|
+
emitBootEvent(true);
|
|
325
325
|
}
|
|
326
326
|
getStorages() {
|
|
327
327
|
return this.storages.wrap();
|
|
@@ -344,8 +344,13 @@ function makeForBootEvents() {
|
|
|
344
344
|
};
|
|
345
345
|
},
|
|
346
346
|
emitBootEvent(ev) {
|
|
347
|
-
var _a;
|
|
348
|
-
(
|
|
347
|
+
var _a, _b;
|
|
348
|
+
if (ev === true) {
|
|
349
|
+
(_a = bootProcObserver === null || bootProcObserver === void 0 ? void 0 : bootProcObserver.complete) === null || _a === void 0 ? void 0 : _a.call(bootProcObserver);
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
(_b = bootProcObserver === null || bootProcObserver === void 0 ? void 0 : bootProcObserver.next) === null || _b === void 0 ? void 0 : _b.call(bootProcObserver, ev);
|
|
353
|
+
}
|
|
349
354
|
}
|
|
350
355
|
};
|
|
351
356
|
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { NetClient } from '../request-utils';
|
|
5
5
|
import * as api from '../../lib-common/service-api/asmail/delivery';
|
|
6
|
-
import { user as mid } from '../../lib-common/mid-sigs-NaCl-Ed';
|
|
7
6
|
import { ServiceLocator } from '../service-locator';
|
|
7
|
+
import { MailerIdSigner } from '../../lib-common/mailerid-sigs/user';
|
|
8
8
|
export type FirstSaveReqOpts = api.PutObjFirstQueryOpts;
|
|
9
9
|
export type FollowingSaveReqOpts = api.PutObjSecondQueryOpts;
|
|
10
10
|
export type ServiceUrlGetter = (address: string) => Promise<string>;
|
|
@@ -97,7 +97,7 @@ export declare class MailSender {
|
|
|
97
97
|
* Rejected promise passes an error object, conditionally containing
|
|
98
98
|
* status field.
|
|
99
99
|
*/
|
|
100
|
-
authorizeSender(assertionSigner:
|
|
100
|
+
authorizeSender(assertionSigner: MailerIdSigner): Promise<void>;
|
|
101
101
|
/**
|
|
102
102
|
* This gets recipients initial public key to launch message exchange.
|
|
103
103
|
* @return a promise resolvable to certificates, received from server.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2015, 2017, 2020 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2015, 2017, 2020, 2025 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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NetClient } from '../request-utils';
|
|
2
2
|
import { HTTPException } from '../../lib-common/exceptions/http';
|
|
3
|
-
import {
|
|
3
|
+
import { MailerIdSigner } from '../../lib-common/mailerid-sigs/user';
|
|
4
4
|
export interface LoginException extends HTTPException {
|
|
5
5
|
loginFailed?: boolean;
|
|
6
6
|
unknownUser?: boolean;
|
|
@@ -9,4 +9,4 @@ export declare function startMidSession(userId: string, net: NetClient, loginUrl
|
|
|
9
9
|
sessionId?: string;
|
|
10
10
|
redirect?: string;
|
|
11
11
|
}>;
|
|
12
|
-
export declare function authenticateMidSession(sessionId: string, midSigner:
|
|
12
|
+
export declare function authenticateMidSession(sessionId: string, midSigner: MailerIdSigner, net: NetClient, loginUrl: string): Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2015, 2017, 2020 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2015, 2017, 2020, 2025 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
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { NetClient } from '../request-utils';
|
|
2
2
|
import { ServiceUser, ICalcDHSharedKey, LoginCompletion } from '../user-with-pkl-session';
|
|
3
|
-
import
|
|
3
|
+
import { MailerIdSigner } from '../../lib-common/mailerid-sigs/user';
|
|
4
4
|
export interface ProvisioningCompletion {
|
|
5
5
|
keyParams: any;
|
|
6
6
|
serverPKey: Uint8Array;
|
|
7
|
-
complete(dhsharedKeyCalc: ICalcDHSharedKey, certDuration: number, assertDuration?: number): Promise<
|
|
7
|
+
complete(dhsharedKeyCalc: ICalcDHSharedKey, certDuration: number, assertDuration?: number): Promise<MailerIdSigner>;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* Certificate provisioner is an object that can do all MailerId's provisioning
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2015 - 2017, 2021 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2015 - 2017, 2021, 2025 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
|
|
@@ -23,11 +23,12 @@ const user_with_pkl_session_1 = require("../user-with-pkl-session");
|
|
|
23
23
|
const jwkeys_1 = require("../../lib-common/jwkeys");
|
|
24
24
|
const json_utils_1 = require("../../lib-common/json-utils");
|
|
25
25
|
const canonical_address_1 = require("../../lib-common/canonical-address");
|
|
26
|
-
const mid = require("../../lib-common/mid-sigs-NaCl-Ed");
|
|
27
26
|
const random = require("../../lib-common/random-node");
|
|
28
27
|
const api = require("../../lib-common/service-api/mailer-id/provisioning");
|
|
29
28
|
const url_1 = require("url");
|
|
30
29
|
const assert_1 = require("../../lib-common/assert");
|
|
30
|
+
const user_1 = require("../../lib-common/mailerid-sigs/user");
|
|
31
|
+
const relying_party_1 = require("../../lib-common/mailerid-sigs/relying-party");
|
|
31
32
|
const DEFAULT_ASSERTION_VALIDITY = 20 * 60;
|
|
32
33
|
/**
|
|
33
34
|
* Certificate provisioner is an object that can do all MailerId's provisioning
|
|
@@ -94,8 +95,7 @@ class MailerIdProvisioner extends user_with_pkl_session_1.ServiceUser {
|
|
|
94
95
|
if (!certs.userCert || !certs.provCert) {
|
|
95
96
|
throw (0, request_utils_1.makeException)(rep, 'Malformed reply: Certificates are missing.');
|
|
96
97
|
}
|
|
97
|
-
const pkeyAndId =
|
|
98
|
-
root: this.rootCert }, this.midDomain, (0, jwkeys_1.getKeyCert)(certs.userCert).issuedAt + 1);
|
|
98
|
+
const pkeyAndId = (0, relying_party_1.verifyChainAndGetUserKey)({ user: certs.userCert, prov: certs.provCert, root: this.rootCert }, this.midDomain, (0, jwkeys_1.getKeyCert)(certs.userCert).issuedAt + 1);
|
|
99
99
|
if (pkeyAndId.address !== (0, canonical_address_1.toCanonicalAddress)(this.userId)) {
|
|
100
100
|
throw (0, request_utils_1.makeException)(rep, 'Malformed reply: Certificate is for a wrong address.');
|
|
101
101
|
}
|
|
@@ -133,13 +133,13 @@ class MailerIdProvisioner extends user_with_pkl_session_1.ServiceUser {
|
|
|
133
133
|
* Undefined value means that a default key should be used.
|
|
134
134
|
*/
|
|
135
135
|
async provisionSigner(keyId) {
|
|
136
|
-
const pair =
|
|
136
|
+
const pair = (0, user_1.generateSigningKeyPair)(random.bytesSync);
|
|
137
137
|
await this.setUrlAndDomain();
|
|
138
138
|
const login = await this.super_login(keyId);
|
|
139
139
|
const completion = async (dhsharedKeyCalc, certDuration, assertDuration = DEFAULT_ASSERTION_VALIDITY) => {
|
|
140
140
|
await login.complete(dhsharedKeyCalc);
|
|
141
141
|
await this.getCertificates(pair.pkey, certDuration);
|
|
142
|
-
return
|
|
142
|
+
return (0, user_1.makeMailerIdSigner)(pair.skey, this.userCert, this.provCert, assertDuration);
|
|
143
143
|
};
|
|
144
144
|
return {
|
|
145
145
|
keyParams: login.keyParams,
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* MailerId and uses respectively authenticated session.
|
|
4
4
|
*/
|
|
5
5
|
import { Reply, RequestOpts, NetClient } from '../lib-client/request-utils';
|
|
6
|
-
import { user as mid } from '../lib-common/mid-sigs-NaCl-Ed';
|
|
7
6
|
import * as WebSocket from 'ws';
|
|
8
|
-
|
|
7
|
+
import { MailerIdSigner } from '../lib-common/mailerid-sigs/user';
|
|
8
|
+
export type IGetMailerIdSigner = () => Promise<MailerIdSigner>;
|
|
9
9
|
export interface ServiceAccessParams {
|
|
10
10
|
login: string;
|
|
11
11
|
logout: string;
|
|
@@ -44,7 +44,7 @@ export declare abstract class ServiceUser {
|
|
|
44
44
|
* @return a promise, resolvable, when mailerId login successfully
|
|
45
45
|
* completes.
|
|
46
46
|
*/
|
|
47
|
-
login(midSigner?:
|
|
47
|
+
login(midSigner?: MailerIdSigner): Promise<void>;
|
|
48
48
|
/**
|
|
49
49
|
* This method closes current session.
|
|
50
50
|
* @return a promise for request completion.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2015, 2017, 2020, 2022 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2015, 2017, 2020, 2022, 2025 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
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { GetRandom, arrays } from "ecma-nacl";
|
|
2
|
+
type JsonKey = web3n.keys.JsonKey;
|
|
3
|
+
type SignedLoad = web3n.keys.SignedLoad;
|
|
4
|
+
export declare const KID_BYTES_LENGTH = 9;
|
|
5
|
+
export declare const MAX_USER_CERT_VALIDITY: number;
|
|
6
|
+
export declare function makeSelfSignedCert(address: string, validityPeriod: number, sjkey: JsonKey, arrFactory?: arrays.Factory): SignedLoad;
|
|
7
|
+
/**
|
|
8
|
+
* One should keep MailerId root key offline, as this key is used only to
|
|
9
|
+
* sign provider keys, which have to work online.
|
|
10
|
+
* @param address is an address of an issuer
|
|
11
|
+
* @param validityPeriod validity period of a generated self-signed
|
|
12
|
+
* certificate in milliseconds
|
|
13
|
+
* @param random
|
|
14
|
+
* @param arrFactory optional array factory
|
|
15
|
+
* @return Generated root key and a self-signed certificate for respective
|
|
16
|
+
* public key.
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateRootKey(address: string, validityPeriod: number, random: GetRandom, arrFactory?: arrays.Factory): {
|
|
19
|
+
cert: SignedLoad;
|
|
20
|
+
skey: JsonKey;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* @param address is an address of an issuer
|
|
24
|
+
* @param validityPeriod validity period of a generated self-signed
|
|
25
|
+
* certificate in seconds
|
|
26
|
+
* @param rootJKey root key in json format
|
|
27
|
+
* @param random
|
|
28
|
+
* @param arrFactory optional array factory
|
|
29
|
+
* @return Generated provider's key and a certificate for a respective
|
|
30
|
+
* public key.
|
|
31
|
+
*/
|
|
32
|
+
export declare function generateProviderKey(address: string, validityPeriod: number, rootJKey: JsonKey, random: GetRandom, arrFactory?: arrays.Factory): {
|
|
33
|
+
cert: SignedLoad;
|
|
34
|
+
skey: JsonKey;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* MailerId providing service should use this object to generate certificates.
|
|
38
|
+
*/
|
|
39
|
+
export interface IdProviderCertifier {
|
|
40
|
+
/**
|
|
41
|
+
* @param publicKey
|
|
42
|
+
* @param address
|
|
43
|
+
* @param validFor (optional)
|
|
44
|
+
* @return certificate for a given key
|
|
45
|
+
*/
|
|
46
|
+
certify(publicKey: JsonKey, address: string, validFor?: number): SignedLoad;
|
|
47
|
+
/**
|
|
48
|
+
* This securely erases internal key.
|
|
49
|
+
* Call this function, when certifier is no longer needed.
|
|
50
|
+
*/
|
|
51
|
+
destroy(): void;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* @param issuer is a domain of certificate issuer, at which issuer's public
|
|
55
|
+
* key can be found to check the signature
|
|
56
|
+
* @param validityPeriod is a default validity period in seconds, for
|
|
57
|
+
* which certifier shall be making certificates
|
|
58
|
+
* @param signJKey is a certificates signing key
|
|
59
|
+
* @param arrFactory is an optional array factory
|
|
60
|
+
* @return MailerId certificates generator, which shall be used on identity
|
|
61
|
+
* provider's side
|
|
62
|
+
*/
|
|
63
|
+
export declare function makeIdProviderCertifier(issuer: string, validityPeriod: number, signJKey: JsonKey, arrFactory?: arrays.Factory): IdProviderCertifier;
|
|
64
|
+
export {};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (C) 2015 - 2017, 2025 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.MAX_USER_CERT_VALIDITY = exports.KID_BYTES_LENGTH = void 0;
|
|
20
|
+
exports.makeSelfSignedCert = makeSelfSignedCert;
|
|
21
|
+
exports.generateRootKey = generateRootKey;
|
|
22
|
+
exports.generateProviderKey = generateProviderKey;
|
|
23
|
+
exports.makeIdProviderCertifier = makeIdProviderCertifier;
|
|
24
|
+
const ecma_nacl_1 = require("ecma-nacl");
|
|
25
|
+
const jwkeys_1 = require("../jwkeys");
|
|
26
|
+
const buffer_utils_1 = require("../buffer-utils");
|
|
27
|
+
const index_1 = require("./index");
|
|
28
|
+
function genSignKeyPair(use, kidLen, random, arrFactory) {
|
|
29
|
+
const pair = ecma_nacl_1.signing.generate_keypair(random(32), arrFactory);
|
|
30
|
+
const pkey = {
|
|
31
|
+
use: use,
|
|
32
|
+
alg: ecma_nacl_1.signing.JWK_ALG_NAME,
|
|
33
|
+
kid: buffer_utils_1.base64.pack(random(kidLen)),
|
|
34
|
+
k: buffer_utils_1.base64.pack(pair.pkey)
|
|
35
|
+
};
|
|
36
|
+
const skey = {
|
|
37
|
+
use: pkey.use,
|
|
38
|
+
alg: pkey.alg,
|
|
39
|
+
kid: pkey.kid,
|
|
40
|
+
k: pair.skey
|
|
41
|
+
};
|
|
42
|
+
return { pkey: pkey, skey: skey };
|
|
43
|
+
}
|
|
44
|
+
function makeCert(pkey, principalAddr, issuer, issuedAt, expiresAt, signKey, arrFactory) {
|
|
45
|
+
if (signKey.alg !== ecma_nacl_1.signing.JWK_ALG_NAME) {
|
|
46
|
+
throw (0, index_1.makeMailerIdException)({ algMismatch: true }, { message: `Given signing key is used with unknown algorithm ${signKey.alg}` });
|
|
47
|
+
}
|
|
48
|
+
const cert = {
|
|
49
|
+
cert: {
|
|
50
|
+
publicKey: pkey,
|
|
51
|
+
principal: { address: principalAddr }
|
|
52
|
+
},
|
|
53
|
+
issuer: issuer,
|
|
54
|
+
issuedAt: issuedAt,
|
|
55
|
+
expiresAt: expiresAt
|
|
56
|
+
};
|
|
57
|
+
const certBytes = buffer_utils_1.utf8.pack(JSON.stringify(cert));
|
|
58
|
+
const sigBytes = ecma_nacl_1.signing.signature(certBytes, signKey.k, arrFactory);
|
|
59
|
+
return {
|
|
60
|
+
alg: signKey.alg,
|
|
61
|
+
kid: signKey.kid,
|
|
62
|
+
sig: buffer_utils_1.base64.pack(sigBytes),
|
|
63
|
+
load: buffer_utils_1.base64.pack(certBytes)
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
exports.KID_BYTES_LENGTH = 9;
|
|
67
|
+
exports.MAX_USER_CERT_VALIDITY = 24 * 60 * 60;
|
|
68
|
+
function makeSelfSignedCert(address, validityPeriod, sjkey, arrFactory) {
|
|
69
|
+
const skey = (0, jwkeys_1.keyFromJson)(sjkey, index_1.KEY_USE.ROOT, ecma_nacl_1.signing.JWK_ALG_NAME, ecma_nacl_1.signing.SECRET_KEY_LENGTH);
|
|
70
|
+
const pkey = {
|
|
71
|
+
use: sjkey.use,
|
|
72
|
+
alg: sjkey.alg,
|
|
73
|
+
kid: sjkey.kid,
|
|
74
|
+
k: buffer_utils_1.base64.pack(ecma_nacl_1.signing.extract_pkey(skey.k))
|
|
75
|
+
};
|
|
76
|
+
const now = Math.floor(Date.now() / 1000);
|
|
77
|
+
return makeCert(pkey, address, address, now, now + validityPeriod, skey, arrFactory);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* One should keep MailerId root key offline, as this key is used only to
|
|
81
|
+
* sign provider keys, which have to work online.
|
|
82
|
+
* @param address is an address of an issuer
|
|
83
|
+
* @param validityPeriod validity period of a generated self-signed
|
|
84
|
+
* certificate in milliseconds
|
|
85
|
+
* @param random
|
|
86
|
+
* @param arrFactory optional array factory
|
|
87
|
+
* @return Generated root key and a self-signed certificate for respective
|
|
88
|
+
* public key.
|
|
89
|
+
*/
|
|
90
|
+
function generateRootKey(address, validityPeriod, random, arrFactory) {
|
|
91
|
+
if (validityPeriod < 1) {
|
|
92
|
+
throw new Error(`Illegal validity period: ${validityPeriod}`);
|
|
93
|
+
}
|
|
94
|
+
const rootPair = genSignKeyPair(index_1.KEY_USE.ROOT, exports.KID_BYTES_LENGTH, random, arrFactory);
|
|
95
|
+
const now = Math.floor(Date.now() / 1000);
|
|
96
|
+
const rootCert = makeCert(rootPair.pkey, address, address, now, now + validityPeriod, rootPair.skey, arrFactory);
|
|
97
|
+
return { cert: rootCert, skey: (0, jwkeys_1.keyToJson)(rootPair.skey) };
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* @param address is an address of an issuer
|
|
101
|
+
* @param validityPeriod validity period of a generated self-signed
|
|
102
|
+
* certificate in seconds
|
|
103
|
+
* @param rootJKey root key in json format
|
|
104
|
+
* @param random
|
|
105
|
+
* @param arrFactory optional array factory
|
|
106
|
+
* @return Generated provider's key and a certificate for a respective
|
|
107
|
+
* public key.
|
|
108
|
+
*/
|
|
109
|
+
function generateProviderKey(address, validityPeriod, rootJKey, random, arrFactory) {
|
|
110
|
+
if (validityPeriod < 1) {
|
|
111
|
+
throw new Error(`Illegal validity period: ${validityPeriod}`);
|
|
112
|
+
}
|
|
113
|
+
const rootKey = (0, jwkeys_1.keyFromJson)(rootJKey, index_1.KEY_USE.ROOT, ecma_nacl_1.signing.JWK_ALG_NAME, ecma_nacl_1.signing.SECRET_KEY_LENGTH);
|
|
114
|
+
const provPair = genSignKeyPair(index_1.KEY_USE.PROVIDER, exports.KID_BYTES_LENGTH, random, arrFactory);
|
|
115
|
+
const now = Math.floor(Date.now() / 1000);
|
|
116
|
+
const rootCert = makeCert(provPair.pkey, address, address, now, now + validityPeriod, rootKey, arrFactory);
|
|
117
|
+
return { cert: rootCert, skey: (0, jwkeys_1.keyToJson)(provPair.skey) };
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* @param issuer is a domain of certificate issuer, at which issuer's public
|
|
121
|
+
* key can be found to check the signature
|
|
122
|
+
* @param validityPeriod is a default validity period in seconds, for
|
|
123
|
+
* which certifier shall be making certificates
|
|
124
|
+
* @param signJKey is a certificates signing key
|
|
125
|
+
* @param arrFactory is an optional array factory
|
|
126
|
+
* @return MailerId certificates generator, which shall be used on identity
|
|
127
|
+
* provider's side
|
|
128
|
+
*/
|
|
129
|
+
function makeIdProviderCertifier(issuer, validityPeriod, signJKey, arrFactory) {
|
|
130
|
+
if (!issuer) {
|
|
131
|
+
throw new Error(`Given issuer is illegal: ${issuer}`);
|
|
132
|
+
}
|
|
133
|
+
if ((validityPeriod < 1) || (validityPeriod > exports.MAX_USER_CERT_VALIDITY)) {
|
|
134
|
+
throw new Error(`Given certificate validity is illegal: ${validityPeriod}`);
|
|
135
|
+
}
|
|
136
|
+
let signKey = (0, jwkeys_1.keyFromJson)(signJKey, index_1.KEY_USE.PROVIDER, ecma_nacl_1.signing.JWK_ALG_NAME, ecma_nacl_1.signing.SECRET_KEY_LENGTH);
|
|
137
|
+
signJKey = undefined;
|
|
138
|
+
if (!arrFactory) {
|
|
139
|
+
arrFactory = ecma_nacl_1.arrays.makeFactory();
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
certify: (publicKey, address, validFor) => {
|
|
143
|
+
if (!signKey) {
|
|
144
|
+
throw new Error(`Certifier is already destroyed.`);
|
|
145
|
+
}
|
|
146
|
+
if (publicKey.use !== index_1.KEY_USE.SIGN) {
|
|
147
|
+
throw new Error(`Given public key has use ${publicKey.use} and cannot be used for signing.`);
|
|
148
|
+
}
|
|
149
|
+
if (typeof validFor === 'number') {
|
|
150
|
+
if (validFor > validityPeriod) {
|
|
151
|
+
validFor = validityPeriod;
|
|
152
|
+
}
|
|
153
|
+
else if (validFor < 0) {
|
|
154
|
+
new Error(`Given certificate validity is illegal: ${validFor}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
validFor = validityPeriod;
|
|
159
|
+
}
|
|
160
|
+
const now = Math.floor(Date.now() / 1000);
|
|
161
|
+
return makeCert(publicKey, address, issuer, now, now + validFor, signKey, arrFactory);
|
|
162
|
+
},
|
|
163
|
+
destroy: () => {
|
|
164
|
+
if (!signKey) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
ecma_nacl_1.arrays.wipe(signKey.k);
|
|
168
|
+
signKey = undefined;
|
|
169
|
+
arrFactory.wipeRecycled();
|
|
170
|
+
arrFactory = undefined;
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
Object.freeze(exports);
|