core-3nweb-client-lib 0.40.1 → 0.41.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/build/api-defs/files.d.ts +1 -0
  2. package/build/api-defs/mailerid.d.ts +51 -1
  3. package/build/core/asmail/key-verification.d.ts +5 -0
  4. package/build/core/asmail/key-verification.js +6 -4
  5. package/build/core/id-manager/index.d.ts +2 -2
  6. package/build/core/id-manager/index.js +30 -0
  7. package/build/core/id-manager/mailerid-cap-ipc.js +6 -2
  8. package/build/core-ipc/json-ipc-wrapping/json-n-binary.js +1 -1
  9. package/build/lib-client/asmail/sender.d.ts +2 -2
  10. package/build/lib-client/asmail/sender.js +1 -1
  11. package/build/lib-client/mailer-id/login.d.ts +2 -2
  12. package/build/lib-client/mailer-id/login.js +1 -1
  13. package/build/lib-client/mailer-id/provisioner.d.ts +2 -2
  14. package/build/lib-client/mailer-id/provisioner.js +6 -6
  15. package/build/lib-client/user-with-mid-session.d.ts +3 -3
  16. package/build/lib-client/user-with-mid-session.js +1 -1
  17. package/build/lib-client/xsp-fs/folder-node.js +3 -0
  18. package/build/lib-common/mailerid-sigs/id-provider.d.ts +64 -0
  19. package/build/lib-common/mailerid-sigs/id-provider.js +174 -0
  20. package/build/lib-common/mailerid-sigs/index.d.ts +44 -0
  21. package/build/lib-common/mailerid-sigs/index.js +50 -0
  22. package/build/lib-common/mailerid-sigs/relying-party.d.ts +59 -0
  23. package/build/lib-common/mailerid-sigs/relying-party.js +237 -0
  24. package/build/lib-common/mailerid-sigs/user.d.ts +60 -0
  25. package/build/lib-common/mailerid-sigs/user.js +149 -0
  26. package/build/lib-common/mailerid-sigs/utils-NaCl-Ed.d.ts +8 -0
  27. package/build/lib-common/mailerid-sigs/utils-NaCl-Ed.js +61 -0
  28. package/build/raw-3nweb-clients.d.ts +2 -2
  29. package/build/raw-3nweb-clients.js +1 -1
  30. package/package.json +1 -1
  31. package/build/lib-common/mid-sigs-NaCl-Ed.d.ts +0 -220
  32. package/build/lib-common/mid-sigs-NaCl-Ed.js +0 -560
@@ -0,0 +1,44 @@
1
+ type JsonKey = web3n.keys.JsonKey;
2
+ type Key = web3n.keys.Key;
3
+ type SignedLoad = web3n.keys.SignedLoad;
4
+ type MailerIdException = web3n.mailerid.MailerIdException;
5
+ /**
6
+ * This enumerates MailerId's different use-roles of keys, involved in
7
+ * establishing a trust.
8
+ */
9
+ export declare const KEY_USE: {
10
+ /**
11
+ * This is a MailerId trust root.
12
+ * It signs certificate for itself, and it signs certificates for provider
13
+ * keys, which have shorter life span, than the root.
14
+ * Root may revoke itself, and may revoke provider key.
15
+ */
16
+ ROOT: string;
17
+ /**
18
+ * This is a provider key, which is used to certify users' signing keys.
19
+ */
20
+ PROVIDER: string;
21
+ /**
22
+ * With this key, MailerId user signs assertions and mail keys.
23
+ */
24
+ SIGN: string;
25
+ };
26
+ export declare function makeMailerIdException(flags: Partial<MailerIdException>, params: Partial<MailerIdException>): MailerIdException;
27
+ export declare function makeMalformedCertsException(message: string, cause?: any): MailerIdException;
28
+ export interface Keypair {
29
+ pkey: JsonKey;
30
+ skey: Key;
31
+ }
32
+ export interface AssertionLoad {
33
+ user: string;
34
+ rpDomain: string;
35
+ sessionId: string;
36
+ issuedAt: number;
37
+ expiresAt: number;
38
+ }
39
+ export interface CertsChain {
40
+ user: SignedLoad;
41
+ prov: SignedLoad;
42
+ root: SignedLoad;
43
+ }
44
+ export {};
@@ -0,0 +1,50 @@
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.KEY_USE = void 0;
20
+ exports.makeMailerIdException = makeMailerIdException;
21
+ exports.makeMalformedCertsException = makeMalformedCertsException;
22
+ const runtime_1 = require("../exceptions/runtime");
23
+ /**
24
+ * This enumerates MailerId's different use-roles of keys, involved in
25
+ * establishing a trust.
26
+ */
27
+ exports.KEY_USE = {
28
+ /**
29
+ * This is a MailerId trust root.
30
+ * It signs certificate for itself, and it signs certificates for provider
31
+ * keys, which have shorter life span, than the root.
32
+ * Root may revoke itself, and may revoke provider key.
33
+ */
34
+ ROOT: "mid-root",
35
+ /**
36
+ * This is a provider key, which is used to certify users' signing keys.
37
+ */
38
+ PROVIDER: "mid-provider",
39
+ /**
40
+ * With this key, MailerId user signs assertions and mail keys.
41
+ */
42
+ SIGN: "mid-sign",
43
+ };
44
+ Object.freeze(exports.KEY_USE);
45
+ function makeMailerIdException(flags, params) {
46
+ return (0, runtime_1.makeRuntimeException)('mailerid', params, flags);
47
+ }
48
+ function makeMalformedCertsException(message, cause) {
49
+ return makeMailerIdException({ certMalformed: true }, { message, cause });
50
+ }
@@ -0,0 +1,59 @@
1
+ import { arrays } from "ecma-nacl";
2
+ import { CertsChain } from "./index";
3
+ type JsonKey = web3n.keys.JsonKey;
4
+ type Key = web3n.keys.Key;
5
+ type SignedLoad = web3n.keys.SignedLoad;
6
+ /**
7
+ * @param certs is a chain of certificate to be verified.
8
+ * @param rootAddr is MailerId service's domain.
9
+ * @param validAt is an epoch time moment (in second), at which user
10
+ * certificate must be valid. Provider certificate must be valid at
11
+ * creation of user's certificate. Root certificate must be valid at
12
+ * creation of provider's certificate.
13
+ * @return user's MailerId signing key with user's address.
14
+ */
15
+ export declare function verifyChainAndGetUserKey(certs: CertsChain, rootAddr: string, validAt: number, arrFactory?: arrays.Factory): {
16
+ pkey: Key;
17
+ address: string;
18
+ };
19
+ export interface AssertionInfo {
20
+ relyingPartyDomain: string;
21
+ sessionId: string;
22
+ user: string;
23
+ }
24
+ export declare function verifyAssertion(midAssertion: SignedLoad, certChain: CertsChain, rootAddr: string, validAt: number, arrFactory?: arrays.Factory): AssertionInfo;
25
+ /**
26
+ * This function does verification of a single certificate with known
27
+ * signing key.
28
+ * If your task requires verification starting with principal's MailerId,
29
+ * use verifyPubKey function that also accepts and checks MailerId
30
+ * certificates chain.
31
+ * @param keyCert is a certificate that should be checked
32
+ * @param principalAddress is an expected principal's address in a given
33
+ * certificate. Exception is thrown, if certificate does not match this
34
+ * expectation.
35
+ * @param signingKey is a public key, with which given certificate is
36
+ * validated cryptographically. Exception is thrown, if crypto-verification
37
+ * fails.
38
+ * @param validAt is an epoch time moment (in second), for which verification
39
+ * should be done.
40
+ * @param arrFactory is an optional array factory.
41
+ * @return a key from a given certificate.
42
+ */
43
+ export declare function verifyKeyCert(keyCert: SignedLoad, principalAddress: string, signingKey: Key, validAt: number, arrFactory?: arrays.Factory): JsonKey;
44
+ /**
45
+ * @param pubKeyCert certificate with a public key, that needs to be
46
+ * verified.
47
+ * @param principalAddress is an expected principal's address in both key
48
+ * certificate, and in MailerId certificate chain. Exception is thrown,
49
+ * if certificate does not match this expectation.
50
+ * @param certChain is MailerId certificate chain for named principal.
51
+ * @param rootAddr is MailerId root's domain.
52
+ * @param validAt is an epoch time moment (in second), for which key
53
+ * certificate verification should be done.
54
+ * @param arrFactory is an optional array factory.
55
+ * @return a key from a given certificate.
56
+ */
57
+ export declare function verifyPubKey(pubKeyCert: SignedLoad, principalAddress: string, certChain: CertsChain, rootAddr: string, validAt: number, arrFactory?: arrays.Factory): JsonKey;
58
+ export declare function verifySignature(root: SignedLoad, prov: SignedLoad, user: SignedLoad, signature: SignedLoad, arrFactory?: arrays.Factory): boolean;
59
+ export {};
@@ -0,0 +1,237 @@
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.verifyChainAndGetUserKey = verifyChainAndGetUserKey;
20
+ exports.verifyAssertion = verifyAssertion;
21
+ exports.verifyKeyCert = verifyKeyCert;
22
+ exports.verifyPubKey = verifyPubKey;
23
+ exports.verifySignature = verifySignature;
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 makeTimeMismatchException(message) {
29
+ return (0, index_1.makeMailerIdException)({ timeMismatch: true }, { message });
30
+ }
31
+ function makeCertsMismatchException(message) {
32
+ return (0, index_1.makeMailerIdException)({ certsMismatch: true }, { message });
33
+ }
34
+ function makeSigVerifException(message) {
35
+ return (0, index_1.makeMailerIdException)({ sigVerificationFails: true }, { message });
36
+ }
37
+ const minValidityPeriodForCert = 20 * 60;
38
+ function verifyCertAndGetPubKey(signedCert, use, validAt, arrFactory, issuer, issuerPKey) {
39
+ const cert = (0, jwkeys_1.getKeyCert)(signedCert);
40
+ if ((validAt < (cert.issuedAt - minValidityPeriodForCert))
41
+ || (cert.expiresAt <= validAt)) {
42
+ throw (0, index_1.makeMailerIdException)({ timeMismatch: true }, { message: `Certificate is not valid at a given moment ${validAt}, cause it is issued at ${cert.issuedAt}, and expires at ${cert.expiresAt}` });
43
+ }
44
+ if (issuer) {
45
+ if (!issuerPKey) {
46
+ throw new Error(`No issuer key given.`);
47
+ }
48
+ if ((cert.issuer !== issuer) || (signedCert.kid !== issuerPKey.kid)) {
49
+ throw makeCertsMismatchException(`Certificate is not signed by issuer key.`);
50
+ }
51
+ }
52
+ let pkey;
53
+ let sig;
54
+ let load;
55
+ try {
56
+ pkey = (0, jwkeys_1.keyFromJson)(cert.cert.publicKey, use, ecma_nacl_1.signing.JWK_ALG_NAME, ecma_nacl_1.signing.PUBLIC_KEY_LENGTH);
57
+ sig = buffer_utils_1.base64.open(signedCert.sig);
58
+ load = buffer_utils_1.base64.open(signedCert.load);
59
+ }
60
+ catch (err) {
61
+ throw (0, index_1.makeMalformedCertsException)(`Cannot read certificate`, err);
62
+ }
63
+ const pk = (issuer ? issuerPKey.k : pkey.k);
64
+ const certOK = ecma_nacl_1.signing.verify(sig, load, pk, arrFactory);
65
+ if (!certOK) {
66
+ throw makeSigVerifException(`Certificate ${use} failed validation.`);
67
+ }
68
+ return { pkey: pkey, address: cert.cert.principal.address };
69
+ }
70
+ /**
71
+ * @param certs is a chain of certificate to be verified.
72
+ * @param rootAddr is MailerId service's domain.
73
+ * @param validAt is an epoch time moment (in second), at which user
74
+ * certificate must be valid. Provider certificate must be valid at
75
+ * creation of user's certificate. Root certificate must be valid at
76
+ * creation of provider's certificate.
77
+ * @return user's MailerId signing key with user's address.
78
+ */
79
+ function verifyChainAndGetUserKey(certs, rootAddr, validAt, arrFactory) {
80
+ // root certificate must be valid when provider's certificate was issued
81
+ let rootValidityMoment;
82
+ try {
83
+ rootValidityMoment = (0, jwkeys_1.getKeyCert)(certs.prov).issuedAt;
84
+ }
85
+ catch (err) {
86
+ throw (0, index_1.makeMalformedCertsException)(`Provider's certificate is malformed`, err);
87
+ }
88
+ // check root and get the key
89
+ const root = verifyCertAndGetPubKey(certs.root, index_1.KEY_USE.ROOT, rootValidityMoment, arrFactory);
90
+ if (rootAddr !== root.address) {
91
+ throw makeCertsMismatchException(`Root certificate address ${root.address} doesn't match expected address ${rootAddr}`);
92
+ }
93
+ // provider's certificate must be valid when user's certificate was issued
94
+ let provValidityMoment;
95
+ try {
96
+ provValidityMoment = (0, jwkeys_1.getKeyCert)(certs.user).issuedAt;
97
+ }
98
+ catch (err) {
99
+ throw (0, index_1.makeMalformedCertsException)(`User's certificate is malformed`, err);
100
+ }
101
+ // check provider and get the key
102
+ const provider = verifyCertAndGetPubKey(certs.prov, index_1.KEY_USE.PROVIDER, provValidityMoment, arrFactory, root.address, root.pkey);
103
+ // check that provider cert comes from the same issuer as root
104
+ if (root.address !== provider.address) {
105
+ throw makeCertsMismatchException(`Provider's certificate address ${provider.address} doesn't match expected address ${root.address}.`);
106
+ }
107
+ // check user certificate and get the key
108
+ return verifyCertAndGetPubKey(certs.user, index_1.KEY_USE.SIGN, validAt, arrFactory, provider.address, provider.pkey);
109
+ }
110
+ function verifyAssertion(midAssertion, certChain, rootAddr, validAt, arrFactory) {
111
+ const userInfo = verifyChainAndGetUserKey(certChain, rootAddr, validAt, arrFactory);
112
+ let loadBytes;
113
+ let sigBytes;
114
+ let assertion;
115
+ try {
116
+ loadBytes = buffer_utils_1.base64.open(midAssertion.load);
117
+ sigBytes = buffer_utils_1.base64.open(midAssertion.sig);
118
+ assertion = JSON.parse(buffer_utils_1.utf8.open(loadBytes));
119
+ }
120
+ catch (err) {
121
+ throw (0, index_1.makeMalformedCertsException)(`Cannot read assertion`, err);
122
+ }
123
+ if (!ecma_nacl_1.signing.verify(sigBytes, loadBytes, userInfo.pkey.k, arrFactory)) {
124
+ throw makeSigVerifException(`Assertion fails verification.`);
125
+ }
126
+ if (assertion.user !== userInfo.address) {
127
+ throw (0, index_1.makeMalformedCertsException)(`Assertion is for one user, while chain is for another.`);
128
+ }
129
+ if (!assertion.sessionId) {
130
+ throw (0, index_1.makeMalformedCertsException)(`Assertion doesn't have session id.`);
131
+ }
132
+ // Note that assertion can be valid before issue time, to counter
133
+ // some mis-synchronization of clocks.
134
+ // It can be some fixed value, like minimum validity period of certs.
135
+ if (Math.abs(validAt - assertion.issuedAt) > (assertion.expiresAt - assertion.issuedAt)) {
136
+ throw makeTimeMismatchException(`Assertion is not valid at ${validAt}, being issued at ${assertion.expiresAt} and expiring at ${assertion.expiresAt}.`);
137
+ }
138
+ return {
139
+ sessionId: assertion.sessionId,
140
+ relyingPartyDomain: assertion.rpDomain,
141
+ user: userInfo.address
142
+ };
143
+ }
144
+ /**
145
+ * This function does verification of a single certificate with known
146
+ * signing key.
147
+ * If your task requires verification starting with principal's MailerId,
148
+ * use verifyPubKey function that also accepts and checks MailerId
149
+ * certificates chain.
150
+ * @param keyCert is a certificate that should be checked
151
+ * @param principalAddress is an expected principal's address in a given
152
+ * certificate. Exception is thrown, if certificate does not match this
153
+ * expectation.
154
+ * @param signingKey is a public key, with which given certificate is
155
+ * validated cryptographically. Exception is thrown, if crypto-verification
156
+ * fails.
157
+ * @param validAt is an epoch time moment (in second), for which verification
158
+ * should be done.
159
+ * @param arrFactory is an optional array factory.
160
+ * @return a key from a given certificate.
161
+ */
162
+ function verifyKeyCert(keyCert, principalAddress, signingKey, validAt, arrFactory) {
163
+ let sigBytes;
164
+ let loadBytes;
165
+ try {
166
+ sigBytes = buffer_utils_1.base64.open(keyCert.sig);
167
+ loadBytes = buffer_utils_1.base64.open(keyCert.load);
168
+ }
169
+ catch (err) {
170
+ throw (0, index_1.makeMalformedCertsException)(`Cannot read certificate`, err);
171
+ }
172
+ if (!ecma_nacl_1.signing.verify(sigBytes, loadBytes, signingKey.k, arrFactory)) {
173
+ throw makeSigVerifException(`Key certificate fails verification.`);
174
+ }
175
+ let cert;
176
+ try {
177
+ cert = (0, jwkeys_1.getKeyCert)(keyCert);
178
+ }
179
+ catch (err) {
180
+ throw (0, index_1.makeMalformedCertsException)(`Cannot read certificate`, err);
181
+ }
182
+ if (cert.cert.principal.address !== principalAddress) {
183
+ throw makeCertsMismatchException(`Key certificate is for user ${cert.cert.principal.address}, while expected address is ${principalAddress}`);
184
+ }
185
+ if ((cert.expiresAt - cert.issuedAt) <= minValidityPeriodForCert) {
186
+ if (Math.abs(cert.issuedAt - validAt) > minValidityPeriodForCert) {
187
+ throw makeTimeMismatchException(`Certificate is not valid at ${validAt} being issued at ${cert.issuedAt} and applying minimum validity period window of ${minValidityPeriodForCert} seconds`);
188
+ }
189
+ }
190
+ else {
191
+ if ((validAt < (cert.issuedAt - minValidityPeriodForCert)) || (cert.expiresAt <= validAt)) {
192
+ throw makeTimeMismatchException(`Certificate is not valid at ${validAt} being issued at ${cert.issuedAt} and expiring at ${cert.expiresAt}`);
193
+ }
194
+ }
195
+ return cert.cert.publicKey;
196
+ }
197
+ /**
198
+ * @param pubKeyCert certificate with a public key, that needs to be
199
+ * verified.
200
+ * @param principalAddress is an expected principal's address in both key
201
+ * certificate, and in MailerId certificate chain. Exception is thrown,
202
+ * if certificate does not match this expectation.
203
+ * @param certChain is MailerId certificate chain for named principal.
204
+ * @param rootAddr is MailerId root's domain.
205
+ * @param validAt is an epoch time moment (in second), for which key
206
+ * certificate verification should be done.
207
+ * @param arrFactory is an optional array factory.
208
+ * @return a key from a given certificate.
209
+ */
210
+ function verifyPubKey(pubKeyCert, principalAddress, certChain, rootAddr, validAt, arrFactory) {
211
+ // time moment, for which user's certificate chain must be valid
212
+ let chainValidityMoment;
213
+ try {
214
+ chainValidityMoment = (0, jwkeys_1.getKeyCert)(pubKeyCert).issuedAt;
215
+ }
216
+ catch (err) {
217
+ throw (0, index_1.makeMalformedCertsException)(`Cannot read certificate`, err);
218
+ }
219
+ const principalInfo = verifyChainAndGetUserKey(certChain, rootAddr, chainValidityMoment, arrFactory);
220
+ if (principalInfo.address !== principalAddress) {
221
+ throw makeCertsMismatchException(`MailerId certificate chain is for user ${principalInfo.address}, while expected address is ${principalAddress}`);
222
+ }
223
+ return verifyKeyCert(pubKeyCert, principalAddress, principalInfo.pkey, validAt, arrFactory);
224
+ }
225
+ function verifySignature(root, prov, user, signature, arrFactory) {
226
+ try {
227
+ const rootAddr = (0, jwkeys_1.getKeyCert)(root).cert.principal.address;
228
+ const validAt = (0, jwkeys_1.getKeyCert)(user).issuedAt + 60;
229
+ const signee = verifyChainAndGetUserKey({ prov, root, user }, rootAddr, validAt, arrFactory);
230
+ const sigBytes = buffer_utils_1.base64.open(signature.sig);
231
+ const loadBytes = buffer_utils_1.base64.open(signature.load);
232
+ return ecma_nacl_1.signing.verify(sigBytes, loadBytes, signee.pkey.k, arrFactory);
233
+ }
234
+ catch (err) {
235
+ return false;
236
+ }
237
+ }
@@ -0,0 +1,60 @@
1
+ import { GetRandom, arrays } from "ecma-nacl";
2
+ import { Keypair } from "./index";
3
+ type JsonKey = web3n.keys.JsonKey;
4
+ type Key = web3n.keys.Key;
5
+ type SignedLoad = web3n.keys.SignedLoad;
6
+ /**
7
+ * This is used by user of MailerId to create assertion that prove user's
8
+ * identity.
9
+ */
10
+ export interface MailerIdSigner {
11
+ address: string;
12
+ userCert: SignedLoad;
13
+ providerCert: SignedLoad;
14
+ issuer: string;
15
+ certExpiresAt: number;
16
+ validityPeriod: number;
17
+ /**
18
+ * @param rpDomain relying party domain. If there is an explicit port,
19
+ * this should domain:port, which is a hostname part of url parsing.
20
+ * @param sessionId
21
+ * @param validFor (optional)
22
+ * @returns signed assertion with a given sessionId string.
23
+ */
24
+ generateAssertionFor(rpDomain: string, sessionId: string, validFor?: number): SignedLoad;
25
+ /**
26
+ * @param pkey
27
+ * @param validFor
28
+ * @returns signed certificate with a given public key.
29
+ */
30
+ certifyPublicKey(pkey: JsonKey, validFor: number): SignedLoad;
31
+ /**
32
+ * Makes this AssertionSigner not usable by wiping its secret key.
33
+ */
34
+ destroy(): void;
35
+ /**
36
+ * @param payload
37
+ * @returns
38
+ */
39
+ sign(payload: Uint8Array): {
40
+ provCert: SignedLoad;
41
+ signeeCert: SignedLoad;
42
+ signature: SignedLoad;
43
+ };
44
+ }
45
+ export declare const KID_BYTES_LENGTH = 9;
46
+ export declare const MAX_SIG_VALIDITY: number;
47
+ export declare function generateSigningKeyPair(random: GetRandom, arrFactory?: arrays.Factory): Keypair;
48
+ /**
49
+ * @param signKey which will be used to sign assertions/keys. Note that
50
+ * this key shall be wiped, when signer is destroyed, as key is neither
51
+ * long-living, nor should be shared.
52
+ * @param cert is user's certificate, signed by identity provider.
53
+ * @param provCert is provider's certificate, signed by respective mid root.
54
+ * @param assertionValidity is an assertion validity period in seconds
55
+ * @param arrFactory is an optional array factory
56
+ * @return signer for user of MailerId to generate assertions, and to sign
57
+ * keys.
58
+ */
59
+ export declare function makeMailerIdSigner(signKey: Key, userCert: SignedLoad, provCert: SignedLoad, assertionValidity?: number, arrFactory?: arrays.Factory): MailerIdSigner;
60
+ export {};
@@ -0,0 +1,149 @@
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_SIG_VALIDITY = exports.KID_BYTES_LENGTH = void 0;
20
+ exports.generateSigningKeyPair = generateSigningKeyPair;
21
+ exports.makeMailerIdSigner = makeMailerIdSigner;
22
+ const ecma_nacl_1 = require("ecma-nacl");
23
+ const jwkeys_1 = require("../jwkeys");
24
+ const buffer_utils_1 = require("../buffer-utils");
25
+ const json_utils_1 = require("../json-utils");
26
+ const utils_NaCl_Ed_1 = require("./utils-NaCl-Ed");
27
+ const index_1 = require("./index");
28
+ function correlateSKeyWithItsCert(skey, cert) {
29
+ const pkey = (0, jwkeys_1.keyFromJson)(cert.cert.publicKey, skey.use, ecma_nacl_1.signing.JWK_ALG_NAME, ecma_nacl_1.signing.PUBLIC_KEY_LENGTH);
30
+ if ((pkey.kid !== skey.kid) || (pkey.use !== skey.use) || (pkey.alg !== skey.alg)
31
+ || !(0, ecma_nacl_1.compareVectors)(ecma_nacl_1.signing.extract_pkey(skey.k), pkey.k)) {
32
+ throw new Error("Key does not correspond to certificate.");
33
+ }
34
+ }
35
+ exports.KID_BYTES_LENGTH = 9;
36
+ exports.MAX_SIG_VALIDITY = 30 * 60;
37
+ function generateSigningKeyPair(random, arrFactory) {
38
+ return (0, utils_NaCl_Ed_1.genSignKeyPair)(index_1.KEY_USE.SIGN, exports.KID_BYTES_LENGTH, random, arrFactory);
39
+ }
40
+ /**
41
+ * @param signKey which will be used to sign assertions/keys. Note that
42
+ * this key shall be wiped, when signer is destroyed, as key is neither
43
+ * long-living, nor should be shared.
44
+ * @param cert is user's certificate, signed by identity provider.
45
+ * @param provCert is provider's certificate, signed by respective mid root.
46
+ * @param assertionValidity is an assertion validity period in seconds
47
+ * @param arrFactory is an optional array factory
48
+ * @return signer for user of MailerId to generate assertions, and to sign
49
+ * keys.
50
+ */
51
+ function makeMailerIdSigner(signKey, userCert, provCert, assertionValidity = exports.MAX_SIG_VALIDITY, arrFactory) {
52
+ const certificate = (0, jwkeys_1.getKeyCert)(userCert);
53
+ if (signKey.use !== index_1.KEY_USE.SIGN) {
54
+ throw new Error(`Given key ${signKey.kid} has incorrect use: ${signKey.use}`);
55
+ }
56
+ correlateSKeyWithItsCert(signKey, certificate);
57
+ if ((typeof assertionValidity !== 'number') || (assertionValidity < 1)
58
+ || (assertionValidity > exports.MAX_SIG_VALIDITY)) {
59
+ throw new Error(`Given assertion validity is illegal: ${assertionValidity}`);
60
+ }
61
+ if (!arrFactory) {
62
+ arrFactory = ecma_nacl_1.arrays.makeFactory();
63
+ }
64
+ function ensureSignerCanBeUsed() {
65
+ if (!signKey) {
66
+ throw new Error("Signer is already destroyed.");
67
+ }
68
+ }
69
+ const signer = {
70
+ address: certificate.cert.principal.address,
71
+ userCert: userCert,
72
+ providerCert: provCert,
73
+ issuer: certificate.issuer,
74
+ certExpiresAt: certificate.expiresAt,
75
+ validityPeriod: assertionValidity,
76
+ generateAssertionFor: (rpDomain, sessionId, validFor) => {
77
+ ensureSignerCanBeUsed();
78
+ if (typeof validFor === 'number') {
79
+ if (validFor > assertionValidity) {
80
+ validFor = assertionValidity;
81
+ }
82
+ else if (validFor < 0) {
83
+ new Error(`Given assertion validity is illegal: ${validFor}`);
84
+ }
85
+ }
86
+ else {
87
+ validFor = assertionValidity;
88
+ }
89
+ let now = Math.floor(Date.now() / 1000);
90
+ if (now <= certificate.issuedAt) {
91
+ now = certificate.issuedAt + 1;
92
+ }
93
+ if (now >= certificate.expiresAt) {
94
+ throw new Error(`Signing key has already expiried at ${certificate.expiresAt} and now is ${now}`);
95
+ }
96
+ const assertion = {
97
+ rpDomain: rpDomain,
98
+ sessionId: sessionId,
99
+ user: certificate.cert.principal.address,
100
+ issuedAt: now,
101
+ expiresAt: now + validFor
102
+ };
103
+ const assertionBytes = buffer_utils_1.utf8.pack(JSON.stringify(assertion));
104
+ const sigBytes = ecma_nacl_1.signing.signature(assertionBytes, signKey.k, arrFactory);
105
+ return {
106
+ alg: signKey.alg,
107
+ kid: signKey.kid,
108
+ sig: buffer_utils_1.base64.pack(sigBytes),
109
+ load: buffer_utils_1.base64.pack(assertionBytes)
110
+ };
111
+ },
112
+ certifyPublicKey: (pkey, validFor) => {
113
+ ensureSignerCanBeUsed();
114
+ if (validFor < 0) {
115
+ new Error(`Given certificate validity is illegal: ${validFor}`);
116
+ }
117
+ const now = Math.floor(Date.now() / 1000);
118
+ if (now >= certificate.expiresAt) {
119
+ throw new Error(`Signing key has already expiried at ${certificate.expiresAt} and now is ${now}`);
120
+ }
121
+ return (0, utils_NaCl_Ed_1.makeCert)(pkey, certificate.cert.principal.address, certificate.cert.principal.address, now, now + validFor, signKey, arrFactory);
122
+ },
123
+ destroy: () => {
124
+ if (!signKey) {
125
+ return;
126
+ }
127
+ ecma_nacl_1.arrays.wipe(signKey.k);
128
+ signKey = undefined;
129
+ arrFactory.wipeRecycled();
130
+ arrFactory = undefined;
131
+ },
132
+ sign: payload => {
133
+ ensureSignerCanBeUsed();
134
+ const sigBytes = ecma_nacl_1.signing.signature(payload, signKey.k, arrFactory);
135
+ return {
136
+ signature: {
137
+ alg: signKey.alg,
138
+ kid: signKey.kid,
139
+ sig: buffer_utils_1.base64.pack(sigBytes),
140
+ load: buffer_utils_1.base64.pack(payload)
141
+ },
142
+ provCert: (0, json_utils_1.copy)(provCert),
143
+ signeeCert: (0, json_utils_1.copy)(userCert)
144
+ };
145
+ }
146
+ };
147
+ Object.freeze(signer);
148
+ return signer;
149
+ }
@@ -0,0 +1,8 @@
1
+ import { GetRandom, arrays } from "ecma-nacl";
2
+ import { Keypair } from "./index";
3
+ type JsonKey = web3n.keys.JsonKey;
4
+ type Key = web3n.keys.Key;
5
+ type SignedLoad = web3n.keys.SignedLoad;
6
+ export declare function genSignKeyPair(use: string, kidLen: number, random: GetRandom, arrFactory?: arrays.Factory): Keypair;
7
+ export declare function makeCert(pkey: JsonKey, principalAddr: string, issuer: string, issuedAt: number, expiresAt: number, signKey: Key, arrFactory?: arrays.Factory): SignedLoad;
8
+ export {};
@@ -0,0 +1,61 @@
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.genSignKeyPair = genSignKeyPair;
20
+ exports.makeCert = makeCert;
21
+ const ecma_nacl_1 = require("ecma-nacl");
22
+ const buffer_utils_1 = require("../buffer-utils");
23
+ const index_1 = require("./index");
24
+ function genSignKeyPair(use, kidLen, random, arrFactory) {
25
+ const pair = ecma_nacl_1.signing.generate_keypair(random(ecma_nacl_1.signing.SEED_LENGTH), arrFactory);
26
+ const pkey = {
27
+ use: use,
28
+ alg: ecma_nacl_1.signing.JWK_ALG_NAME,
29
+ kid: buffer_utils_1.base64.pack(random(kidLen)),
30
+ k: buffer_utils_1.base64.pack(pair.pkey)
31
+ };
32
+ const skey = {
33
+ use: pkey.use,
34
+ alg: pkey.alg,
35
+ kid: pkey.kid,
36
+ k: pair.skey
37
+ };
38
+ return { pkey, skey };
39
+ }
40
+ function makeCert(pkey, principalAddr, issuer, issuedAt, expiresAt, signKey, arrFactory) {
41
+ if (signKey.alg !== ecma_nacl_1.signing.JWK_ALG_NAME) {
42
+ throw (0, index_1.makeMailerIdException)({ algMismatch: true }, { message: `Given signing key is used with unknown algorithm ${signKey.alg}` });
43
+ }
44
+ const cert = {
45
+ cert: {
46
+ publicKey: pkey,
47
+ principal: { address: principalAddr }
48
+ },
49
+ issuer: issuer,
50
+ issuedAt: issuedAt,
51
+ expiresAt: expiresAt
52
+ };
53
+ const certBytes = buffer_utils_1.utf8.pack(JSON.stringify(cert));
54
+ const sigBytes = ecma_nacl_1.signing.signature(certBytes, signKey.k, arrFactory);
55
+ return {
56
+ alg: signKey.alg,
57
+ kid: signKey.kid,
58
+ sig: buffer_utils_1.base64.pack(sigBytes),
59
+ load: buffer_utils_1.base64.pack(certBytes)
60
+ };
61
+ }