shamir-mnemonic-ts 1.0.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.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +71 -0
  3. package/dist/cipher.d.ts +3 -0
  4. package/dist/cipher.d.ts.map +1 -0
  5. package/dist/cipher.js +91 -0
  6. package/dist/cipher.js.map +1 -0
  7. package/dist/constants.d.ts +41 -0
  8. package/dist/constants.d.ts.map +1 -0
  9. package/dist/constants.js +45 -0
  10. package/dist/constants.js.map +1 -0
  11. package/dist/index.d.ts +6 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +23 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/recovery.d.ts +18 -0
  16. package/dist/recovery.d.ts.map +1 -0
  17. package/dist/recovery.js +126 -0
  18. package/dist/recovery.js.map +1 -0
  19. package/dist/rs1024.d.ts +5 -0
  20. package/dist/rs1024.d.ts.map +1 -0
  21. package/dist/rs1024.js +50 -0
  22. package/dist/rs1024.js.map +1 -0
  23. package/dist/shamir.d.ts +36 -0
  24. package/dist/shamir.d.ts.map +1 -0
  25. package/dist/shamir.js +448 -0
  26. package/dist/shamir.js.map +1 -0
  27. package/dist/share.d.ts +39 -0
  28. package/dist/share.d.ts.map +1 -0
  29. package/dist/share.js +194 -0
  30. package/dist/share.js.map +1 -0
  31. package/dist/src/cipher.js +90 -0
  32. package/dist/src/constants.js +44 -0
  33. package/dist/src/index.js +22 -0
  34. package/dist/src/recovery.js +127 -0
  35. package/dist/src/rs1024.js +55 -0
  36. package/dist/src/shamir.js +486 -0
  37. package/dist/src/share.js +196 -0
  38. package/dist/src/utils.js +97 -0
  39. package/dist/src/wordlist.js +136 -0
  40. package/dist/test-manual.js +78 -0
  41. package/dist/utils.d.ts +7 -0
  42. package/dist/utils.d.ts.map +1 -0
  43. package/dist/utils.js +39 -0
  44. package/dist/utils.js.map +1 -0
  45. package/dist/wordlist.d.ts +4 -0
  46. package/dist/wordlist.d.ts.map +1 -0
  47. package/dist/wordlist.js +1069 -0
  48. package/dist/wordlist.js.map +1 -0
  49. package/package.json +44 -0
@@ -0,0 +1,486 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
36
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
37
+ if (ar || !(i in from)) {
38
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
39
+ ar[i] = from[i];
40
+ }
41
+ }
42
+ return to.concat(ar || Array.prototype.slice.call(from));
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.RANDOM_BYTES = exports.EncryptedMasterSecret = exports.ShareGroup = void 0;
46
+ exports.decodeMnemonics = decodeMnemonics;
47
+ exports.splitEms = splitEms;
48
+ exports.generateMnemonics = generateMnemonics;
49
+ exports.recoverEms = recoverEms;
50
+ exports.combineMnemonics = combineMnemonics;
51
+ var crypto = __importStar(require("crypto"));
52
+ var cipher = __importStar(require("./cipher"));
53
+ var constants_1 = require("./constants");
54
+ var share_1 = require("./share");
55
+ var utils_1 = require("./utils");
56
+ var ShareGroup = /** @class */ (function () {
57
+ function ShareGroup() {
58
+ this._shares = new Set();
59
+ }
60
+ ShareGroup.prototype[Symbol.iterator] = function () {
61
+ return this._shares.values();
62
+ };
63
+ Object.defineProperty(ShareGroup.prototype, "length", {
64
+ get: function () {
65
+ return this._shares.size;
66
+ },
67
+ enumerable: false,
68
+ configurable: true
69
+ });
70
+ Object.defineProperty(ShareGroup.prototype, "isEmpty", {
71
+ get: function () {
72
+ return this._shares.size === 0;
73
+ },
74
+ enumerable: false,
75
+ configurable: true
76
+ });
77
+ ShareGroup.prototype.has = function (obj) {
78
+ // Check by value equality, not reference
79
+ for (var _i = 0, _a = this._shares; _i < _a.length; _i++) {
80
+ var share = _a[_i];
81
+ if (share.identifier === obj.identifier &&
82
+ share.extendable === obj.extendable &&
83
+ share.iterationExponent === obj.iterationExponent &&
84
+ share.groupIndex === obj.groupIndex &&
85
+ share.groupThreshold === obj.groupThreshold &&
86
+ share.groupCount === obj.groupCount &&
87
+ share.index === obj.index &&
88
+ share.memberThreshold === obj.memberThreshold &&
89
+ share.value.equals(obj.value)) {
90
+ return true;
91
+ }
92
+ }
93
+ return false;
94
+ };
95
+ ShareGroup.prototype.add = function (share) {
96
+ if (this._shares.size > 0 && !this._groupParametersMatch(share)) {
97
+ var existing = Array.from(this._shares)[0];
98
+ var existingParams = existing.groupParameters();
99
+ var newParams = share.groupParameters();
100
+ var fields = [
101
+ 'identifier',
102
+ 'extendable',
103
+ 'iterationExponent',
104
+ 'groupIndex',
105
+ 'groupThreshold',
106
+ 'groupCount',
107
+ 'memberThreshold',
108
+ ];
109
+ for (var _i = 0, fields_1 = fields; _i < fields_1.length; _i++) {
110
+ var field = fields_1[_i];
111
+ if (existingParams[field] !== newParams[field]) {
112
+ throw new utils_1.MnemonicError("Invalid set of mnemonics. The ".concat(field, " parameters don't match."));
113
+ }
114
+ }
115
+ }
116
+ this._shares.add(share);
117
+ };
118
+ ShareGroup.prototype._groupParametersMatch = function (share) {
119
+ if (this._shares.size === 0) {
120
+ return true;
121
+ }
122
+ var existing = Array.from(this._shares)[0];
123
+ var existingParams = existing.groupParameters();
124
+ var newParams = share.groupParameters();
125
+ return (existingParams.identifier === newParams.identifier &&
126
+ existingParams.extendable === newParams.extendable &&
127
+ existingParams.iterationExponent === newParams.iterationExponent &&
128
+ existingParams.groupIndex === newParams.groupIndex &&
129
+ existingParams.groupThreshold === newParams.groupThreshold &&
130
+ existingParams.groupCount === newParams.groupCount &&
131
+ existingParams.memberThreshold === newParams.memberThreshold);
132
+ };
133
+ ShareGroup.prototype.toRawShares = function () {
134
+ return Array.from(this._shares).map(function (s) { return ({ x: s.index, data: s.value }); });
135
+ };
136
+ ShareGroup.prototype.getMinimalGroup = function () {
137
+ var group = new ShareGroup();
138
+ var sharesArray = Array.from(this._shares);
139
+ var threshold = this.memberThreshold();
140
+ group._shares = new Set(sharesArray.slice(0, threshold));
141
+ return group;
142
+ };
143
+ ShareGroup.prototype.commonParameters = function () {
144
+ return Array.from(this._shares)[0].commonParameters();
145
+ };
146
+ ShareGroup.prototype.groupParameters = function () {
147
+ return Array.from(this._shares)[0].groupParameters();
148
+ };
149
+ ShareGroup.prototype.memberThreshold = function () {
150
+ return Array.from(this._shares)[0].memberThreshold;
151
+ };
152
+ ShareGroup.prototype.isComplete = function () {
153
+ if (this._shares.size === 0) {
154
+ return false;
155
+ }
156
+ return this._shares.size >= this.memberThreshold();
157
+ };
158
+ return ShareGroup;
159
+ }());
160
+ exports.ShareGroup = ShareGroup;
161
+ var EncryptedMasterSecret = /** @class */ (function () {
162
+ function EncryptedMasterSecret(identifier, extendable, iterationExponent, ciphertext) {
163
+ this.identifier = identifier;
164
+ this.extendable = extendable;
165
+ this.iterationExponent = iterationExponent;
166
+ this.ciphertext = ciphertext;
167
+ }
168
+ EncryptedMasterSecret.fromMasterSecret = function (masterSecret, passphrase, identifier, extendable, iterationExponent) {
169
+ var ciphertext = cipher.encrypt(masterSecret, passphrase, iterationExponent, identifier, extendable);
170
+ return new EncryptedMasterSecret(identifier, extendable, iterationExponent, ciphertext);
171
+ };
172
+ EncryptedMasterSecret.prototype.decrypt = function (passphrase) {
173
+ return cipher.decrypt(this.ciphertext, passphrase, this.iterationExponent, this.identifier, this.extendable);
174
+ };
175
+ return EncryptedMasterSecret;
176
+ }());
177
+ exports.EncryptedMasterSecret = EncryptedMasterSecret;
178
+ var RANDOM_BYTES = function (length) {
179
+ return crypto.randomBytes(length);
180
+ };
181
+ exports.RANDOM_BYTES = RANDOM_BYTES;
182
+ /** Source of random bytes. Can be overriden for deterministic testing. */
183
+ function _precomputeExpLog() {
184
+ var exp = new Array(255).fill(0);
185
+ var log = new Array(256).fill(0);
186
+ var poly = 1;
187
+ for (var i = 0; i < 255; i++) {
188
+ exp[i] = poly;
189
+ log[poly] = i;
190
+ // Multiply poly by the polynomial x + 1.
191
+ poly = (poly << 1) ^ poly;
192
+ // Reduce poly by x^8 + x^4 + x^3 + x + 1.
193
+ if (poly & 0x100) {
194
+ poly ^= 0x11B;
195
+ }
196
+ }
197
+ return [exp, log];
198
+ }
199
+ var _a = _precomputeExpLog(), EXP_TABLE = _a[0], LOG_TABLE = _a[1];
200
+ function _interpolate(shares, x) {
201
+ /**
202
+ * Returns f(x) given the Shamir shares (x_1, f(x_1)), ... , (x_k, f(x_k)).
203
+ * @param shares The Shamir shares.
204
+ * @param x The x coordinate of the result.
205
+ * @return Evaluations of the polynomials in x.
206
+ */
207
+ var xCoordinates = new Set(shares.map(function (share) { return share.x; }));
208
+ if (xCoordinates.size !== shares.length) {
209
+ throw new utils_1.MnemonicError('Invalid set of shares. Share indices must be unique.');
210
+ }
211
+ var shareValueLengths = new Set(shares.map(function (share) { return share.data.length; }));
212
+ if (shareValueLengths.size !== 1) {
213
+ throw new utils_1.MnemonicError('Invalid set of shares. All share values must have the same length.');
214
+ }
215
+ if (xCoordinates.has(x)) {
216
+ for (var _i = 0, shares_1 = shares; _i < shares_1.length; _i++) {
217
+ var share = shares_1[_i];
218
+ if (share.x === x) {
219
+ return share.data;
220
+ }
221
+ }
222
+ }
223
+ // Logarithm of the product of (x_i - x) for i = 1, ... , k.
224
+ var logProd = 0;
225
+ for (var _a = 0, shares_2 = shares; _a < shares_2.length; _a++) {
226
+ var share = shares_2[_a];
227
+ logProd = (logProd + LOG_TABLE[share.x ^ x]) % 255;
228
+ }
229
+ var resultLength = Array.from(shareValueLengths)[0];
230
+ var result = Buffer.alloc(resultLength);
231
+ for (var _b = 0, shares_3 = shares; _b < shares_3.length; _b++) {
232
+ var share = shares_3[_b];
233
+ // The logarithm of the Lagrange basis polynomial evaluated at x.
234
+ var logBasisEval = logProd;
235
+ logBasisEval = (logBasisEval - LOG_TABLE[share.x ^ x] + 255) % 255;
236
+ var sumOther = 0;
237
+ for (var _c = 0, shares_4 = shares; _c < shares_4.length; _c++) {
238
+ var other = shares_4[_c];
239
+ if (other.x !== share.x) {
240
+ sumOther = (sumOther + LOG_TABLE[share.x ^ other.x]) % 255;
241
+ }
242
+ }
243
+ logBasisEval = (logBasisEval - sumOther + 255) % 255;
244
+ for (var i = 0; i < resultLength; i++) {
245
+ var shareVal = share.data[i];
246
+ if (shareVal !== 0) {
247
+ result[i] ^= EXP_TABLE[(LOG_TABLE[shareVal] + logBasisEval) % 255];
248
+ }
249
+ }
250
+ }
251
+ return result;
252
+ }
253
+ function _createDigest(randomData, sharedSecret) {
254
+ var hmac = crypto.createHmac('sha256', randomData);
255
+ hmac.update(sharedSecret);
256
+ return hmac.digest().slice(0, constants_1.DIGEST_LENGTH_BYTES);
257
+ }
258
+ function _splitSecret(threshold, shareCount, sharedSecret) {
259
+ if (threshold < 1) {
260
+ throw new Error('The requested threshold must be a positive integer.');
261
+ }
262
+ if (threshold > shareCount) {
263
+ throw new Error('The requested threshold must not exceed the number of shares.');
264
+ }
265
+ if (shareCount > constants_1.MAX_SHARE_COUNT) {
266
+ throw new Error("The requested number of shares must not exceed ".concat(constants_1.MAX_SHARE_COUNT, "."));
267
+ }
268
+ // If the threshold is 1, then the digest of the shared secret is not used.
269
+ if (threshold === 1) {
270
+ return Array.from({ length: shareCount }, function (_, i) { return ({
271
+ x: i,
272
+ data: sharedSecret,
273
+ }); });
274
+ }
275
+ var randomShareCount = threshold - 2;
276
+ var shares = Array.from({ length: randomShareCount }, function (_, i) { return ({
277
+ x: i,
278
+ data: (0, exports.RANDOM_BYTES)(sharedSecret.length),
279
+ }); });
280
+ var randomPart = (0, exports.RANDOM_BYTES)(sharedSecret.length - constants_1.DIGEST_LENGTH_BYTES);
281
+ var digest = _createDigest(randomPart, sharedSecret);
282
+ var baseShares = __spreadArray(__spreadArray([], shares, true), [
283
+ { x: constants_1.DIGEST_INDEX, data: Buffer.concat([digest, randomPart]) },
284
+ { x: constants_1.SECRET_INDEX, data: sharedSecret },
285
+ ], false);
286
+ for (var i = randomShareCount; i < shareCount; i++) {
287
+ shares.push({ x: i, data: _interpolate(baseShares, i) });
288
+ }
289
+ return shares;
290
+ }
291
+ function _recoverSecret(threshold, shares) {
292
+ // If the threshold is 1, then the digest of the shared secret is not used.
293
+ if (threshold === 1) {
294
+ return shares[0].data;
295
+ }
296
+ var sharedSecret = _interpolate(shares, constants_1.SECRET_INDEX);
297
+ var digestShare = _interpolate(shares, constants_1.DIGEST_INDEX);
298
+ var digest = digestShare.slice(0, constants_1.DIGEST_LENGTH_BYTES);
299
+ var randomPart = digestShare.slice(constants_1.DIGEST_LENGTH_BYTES);
300
+ if (!digest.equals(_createDigest(randomPart, sharedSecret))) {
301
+ throw new utils_1.MnemonicError('Invalid digest of the shared secret.');
302
+ }
303
+ return sharedSecret;
304
+ }
305
+ function decodeMnemonics(mnemonics) {
306
+ var commonParams = [];
307
+ var groups = new Map();
308
+ for (var _i = 0, mnemonics_1 = mnemonics; _i < mnemonics_1.length; _i++) {
309
+ var mnemonic = mnemonics_1[_i];
310
+ var share = share_1.Share.fromMnemonic(mnemonic);
311
+ var params = share.commonParameters();
312
+ commonParams.push(params);
313
+ if (!groups.has(share.groupIndex)) {
314
+ groups.set(share.groupIndex, new ShareGroup());
315
+ }
316
+ var group = groups.get(share.groupIndex);
317
+ group.add(share);
318
+ }
319
+ if (commonParams.length === 0) {
320
+ throw new utils_1.MnemonicError('The list of mnemonics is empty.');
321
+ }
322
+ var firstParams = commonParams[0];
323
+ for (var _a = 0, commonParams_1 = commonParams; _a < commonParams_1.length; _a++) {
324
+ var params = commonParams_1[_a];
325
+ if (params.identifier !== firstParams.identifier ||
326
+ params.extendable !== firstParams.extendable ||
327
+ params.iterationExponent !== firstParams.iterationExponent ||
328
+ params.groupThreshold !== firstParams.groupThreshold ||
329
+ params.groupCount !== firstParams.groupCount) {
330
+ throw new utils_1.MnemonicError('Invalid set of mnemonics. ' +
331
+ "All mnemonics must begin with the same ".concat(constants_1.ID_EXP_LENGTH_WORDS, " words, ") +
332
+ 'must have the same group threshold and the same group count.');
333
+ }
334
+ }
335
+ return groups;
336
+ }
337
+ function splitEms(groupThreshold, groups, encryptedMasterSecret) {
338
+ /**
339
+ * Split an Encrypted Master Secret into mnemonic shares.
340
+ *
341
+ * This function is a counterpart to `recoverEms`, and it is used as a subroutine in
342
+ * `generateMnemonics`. The input is an *already encrypted* Master Secret (EMS), so it
343
+ * is possible to encrypt the Master Secret in advance and perform the splitting later.
344
+ *
345
+ * @param groupThreshold The number of groups required to reconstruct the master secret.
346
+ * @param groups A list of (member_threshold, member_count) pairs for each group, where member_count
347
+ * is the number of shares to generate for the group and member_threshold is the number of members required to
348
+ * reconstruct the group secret.
349
+ * @param encryptedMasterSecret The encrypted master secret to split.
350
+ * @return List of groups of mnemonics.
351
+ */
352
+ if (encryptedMasterSecret.ciphertext.length * 8 < constants_1.MIN_STRENGTH_BITS) {
353
+ throw new Error('The length of the master secret must be ' +
354
+ "at least ".concat((0, utils_1.bitsToBytes)(constants_1.MIN_STRENGTH_BITS), " bytes."));
355
+ }
356
+ if (groupThreshold > groups.length) {
357
+ throw new Error('The requested group threshold must not exceed the number of groups.');
358
+ }
359
+ if (groups.some(function (_a) {
360
+ var memberThreshold = _a[0], memberCount = _a[1];
361
+ return memberThreshold === 1 && memberCount > 1;
362
+ })) {
363
+ throw new Error('Creating multiple member shares with member threshold 1 is not allowed. ' +
364
+ 'Use 1-of-1 member sharing instead.');
365
+ }
366
+ var groupShares = _splitSecret(groupThreshold, groups.length, encryptedMasterSecret.ciphertext);
367
+ return groups.map(function (_a, groupIndex) {
368
+ var memberThreshold = _a[0], memberCount = _a[1];
369
+ var groupSecret = groupShares[groupIndex].data;
370
+ var memberShares = _splitSecret(memberThreshold, memberCount, groupSecret);
371
+ return memberShares.map(function (_a) {
372
+ var memberIndex = _a.x, value = _a.data;
373
+ return new share_1.Share(encryptedMasterSecret.identifier, encryptedMasterSecret.extendable, encryptedMasterSecret.iterationExponent, groupIndex, groupThreshold, groups.length, memberIndex, memberThreshold, value);
374
+ });
375
+ });
376
+ }
377
+ function _randomIdentifier() {
378
+ /** Returns a random identifier with the given bit length. */
379
+ var identifierBytes = (0, exports.RANDOM_BYTES)((0, utils_1.bitsToBytes)(constants_1.ID_LENGTH_BITS));
380
+ var identifier = 0;
381
+ for (var i = 0; i < identifierBytes.length; i++) {
382
+ identifier = (identifier << 8) | identifierBytes[i];
383
+ }
384
+ // Mask to ID_LENGTH_BITS
385
+ return identifier & ((1 << constants_1.ID_LENGTH_BITS) - 1);
386
+ }
387
+ function generateMnemonics(groupThreshold, groups, masterSecret, passphrase, extendable, iterationExponent) {
388
+ if (passphrase === void 0) { passphrase = Buffer.alloc(0); }
389
+ if (extendable === void 0) { extendable = true; }
390
+ if (iterationExponent === void 0) { iterationExponent = 1; }
391
+ /**
392
+ * Split a master secret into mnemonic shares using Shamir's secret sharing scheme.
393
+ *
394
+ * The supplied Master Secret is encrypted by the passphrase (empty passphrase is used
395
+ * if none is provided) and split into a set of mnemonic shares.
396
+ *
397
+ * This is the user-friendly method to back up a pre-existing secret with the Shamir
398
+ * scheme, optionally protected by a passphrase.
399
+ *
400
+ * @param groupThreshold The number of groups required to reconstruct the master secret.
401
+ * @param groups A list of (member_threshold, member_count) pairs for each group, where member_count
402
+ * is the number of shares to generate for the group and member_threshold is the number of members required to
403
+ * reconstruct the group secret.
404
+ * @param masterSecret The master secret to split.
405
+ * @param passphrase The passphrase used to encrypt the master secret.
406
+ * @param iterationExponent The encryption iteration exponent.
407
+ * @return List of groups mnemonics.
408
+ */
409
+ // Validate passphrase contains only printable ASCII characters (code points 32-126)
410
+ for (var i = 0; i < passphrase.length; i++) {
411
+ var code = passphrase[i];
412
+ if (code < 32 || code > 126) {
413
+ throw new Error('The passphrase must contain only printable ASCII characters (code points 32-126).');
414
+ }
415
+ }
416
+ var identifier = _randomIdentifier();
417
+ var encryptedMasterSecret = EncryptedMasterSecret.fromMasterSecret(masterSecret, passphrase, identifier, extendable, iterationExponent);
418
+ var groupedShares = splitEms(groupThreshold, groups, encryptedMasterSecret);
419
+ return groupedShares.map(function (group) { return group.map(function (share) { return share.mnemonic(); }); });
420
+ }
421
+ function recoverEms(groups) {
422
+ /**
423
+ * Combine shares, recover metadata and the Encrypted Master Secret.
424
+ *
425
+ * This function is a counterpart to `splitEms`, and it is used as a subroutine in
426
+ * `combineMnemonics`. It returns the EMS itself and data required for its decryption,
427
+ * except for the passphrase. It is thus possible to defer decryption of the Master
428
+ * Secret to a later time.
429
+ *
430
+ * @param groups Set of shares classified into groups.
431
+ * @return Encrypted Master Secret
432
+ */
433
+ if (groups.size === 0) {
434
+ throw new utils_1.MnemonicError('The set of shares is empty.');
435
+ }
436
+ var firstGroup = Array.from(groups.values())[0];
437
+ var params = firstGroup.commonParameters();
438
+ if (groups.size < params.groupThreshold) {
439
+ throw new utils_1.MnemonicError('Insufficient number of mnemonic groups. ' +
440
+ "The required number of groups is ".concat(params.groupThreshold, "."));
441
+ }
442
+ if (groups.size !== params.groupThreshold) {
443
+ throw new utils_1.MnemonicError('Wrong number of mnemonic groups. ' +
444
+ "Expected ".concat(params.groupThreshold, " groups, ") +
445
+ "but ".concat(groups.size, " were provided."));
446
+ }
447
+ for (var _i = 0, _a = groups.values(); _i < _a.length; _i++) {
448
+ var group = _a[_i];
449
+ if (group.length !== group.memberThreshold()) {
450
+ var shareWords = Array.from(group)[0].words();
451
+ var prefix = shareWords.slice(0, constants_1.GROUP_PREFIX_LENGTH_WORDS).join(' ');
452
+ throw new utils_1.MnemonicError('Wrong number of mnemonics. ' +
453
+ "Expected ".concat(group.memberThreshold(), " mnemonics starting with \"").concat(prefix, " ...\", ") +
454
+ "but ".concat(group.length, " were provided."));
455
+ }
456
+ }
457
+ var groupShares = Array.from(groups.entries()).map(function (_a) {
458
+ var groupIndex = _a[0], group = _a[1];
459
+ return ({
460
+ x: groupIndex,
461
+ data: _recoverSecret(group.memberThreshold(), group.toRawShares()),
462
+ });
463
+ });
464
+ var ciphertext = _recoverSecret(params.groupThreshold, groupShares);
465
+ return new EncryptedMasterSecret(params.identifier, params.extendable, params.iterationExponent, ciphertext);
466
+ }
467
+ function combineMnemonics(mnemonics, passphrase) {
468
+ if (passphrase === void 0) { passphrase = Buffer.alloc(0); }
469
+ /**
470
+ * Combine mnemonic shares to obtain the master secret which was previously split
471
+ * using Shamir's secret sharing scheme.
472
+ *
473
+ * This is the user-friendly method to recover a backed-up secret optionally protected
474
+ * by a passphrase.
475
+ *
476
+ * @param mnemonics List of mnemonics.
477
+ * @param passphrase The passphrase used to encrypt the master secret.
478
+ * @return The master secret.
479
+ */
480
+ if (!mnemonics || Array.from(mnemonics).length === 0) {
481
+ throw new utils_1.MnemonicError('The list of mnemonics is empty.');
482
+ }
483
+ var groups = decodeMnemonics(mnemonics);
484
+ var encryptedMasterSecret = recoverEms(groups);
485
+ return encryptedMasterSecret.decrypt(passphrase);
486
+ }
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.Share = void 0;
37
+ var rs1024 = __importStar(require("./rs1024"));
38
+ var wordlist = __importStar(require("./wordlist"));
39
+ var constants_1 = require("./constants");
40
+ var utils_1 = require("./utils");
41
+ function _intToWordIndices(value, length) {
42
+ /** Converts an integer value to a list of base 1024 indices in big endian order. */
43
+ return Array.from((0, utils_1.intToIndices)(value, length, constants_1.RADIX_BITS));
44
+ }
45
+ function _intFromWordIndices(indices) {
46
+ /** Converts a list of base 1024 indices in big endian order to an integer value. */
47
+ var value = 0;
48
+ for (var _i = 0, indices_1 = indices; _i < indices_1.length; _i++) {
49
+ var index = indices_1[_i];
50
+ value = value * constants_1.RADIX + index;
51
+ }
52
+ return value;
53
+ }
54
+ function _customizationString(extendable) {
55
+ return extendable ? constants_1.CUSTOMIZATION_STRING_EXTENDABLE : constants_1.CUSTOMIZATION_STRING_ORIG;
56
+ }
57
+ var Share = /** @class */ (function () {
58
+ function Share(identifier, extendable, iterationExponent, groupIndex, groupThreshold, groupCount, index, memberThreshold, value) {
59
+ this.identifier = identifier;
60
+ this.extendable = extendable;
61
+ this.iterationExponent = iterationExponent;
62
+ this.groupIndex = groupIndex;
63
+ this.groupThreshold = groupThreshold;
64
+ this.groupCount = groupCount;
65
+ this.index = index;
66
+ this.memberThreshold = memberThreshold;
67
+ this.value = value;
68
+ }
69
+ Share.prototype.commonParameters = function () {
70
+ /** Return values that uniquely identify a matching set of shares. */
71
+ return {
72
+ identifier: this.identifier,
73
+ extendable: this.extendable,
74
+ iterationExponent: this.iterationExponent,
75
+ groupThreshold: this.groupThreshold,
76
+ groupCount: this.groupCount,
77
+ };
78
+ };
79
+ Share.prototype.groupParameters = function () {
80
+ /** Return values that uniquely identify shares belonging to the same group. */
81
+ return {
82
+ identifier: this.identifier,
83
+ extendable: this.extendable,
84
+ iterationExponent: this.iterationExponent,
85
+ groupIndex: this.groupIndex,
86
+ groupThreshold: this.groupThreshold,
87
+ groupCount: this.groupCount,
88
+ memberThreshold: this.memberThreshold,
89
+ };
90
+ };
91
+ Share.prototype._encodeIdExp = function () {
92
+ var idExpInt = this.identifier << (constants_1.ITERATION_EXP_LENGTH_BITS + constants_1.EXTENDABLE_FLAG_LENGTH_BITS);
93
+ idExpInt += (this.extendable ? 1 : 0) << constants_1.ITERATION_EXP_LENGTH_BITS;
94
+ idExpInt += this.iterationExponent;
95
+ return _intToWordIndices(idExpInt, constants_1.ID_EXP_LENGTH_WORDS);
96
+ };
97
+ Share.prototype._encodeShareParams = function () {
98
+ // each value is 4 bits, for 20 bits total
99
+ var val = this.groupIndex;
100
+ val <<= 4;
101
+ val += this.groupThreshold - 1;
102
+ val <<= 4;
103
+ val += this.groupCount - 1;
104
+ val <<= 4;
105
+ val += this.index;
106
+ val <<= 4;
107
+ val += this.memberThreshold - 1;
108
+ // group parameters are 2 words
109
+ return _intToWordIndices(val, 2);
110
+ };
111
+ Share.prototype.words = function () {
112
+ /** Convert share data to a share mnemonic. */
113
+ var valueWordCount = (0, utils_1.bitsToWords)(this.value.length * 8);
114
+ // Convert Buffer to big-endian integer (using BigInt to handle large values)
115
+ var valueInt = 0n;
116
+ for (var i = 0; i < this.value.length; i++) {
117
+ valueInt = (valueInt << 8n) | BigInt(this.value[i]);
118
+ }
119
+ // Convert BigInt to number array for _intToWordIndices
120
+ // For very large values, we need to handle this differently
121
+ var valueData = [];
122
+ var tempValue = valueInt;
123
+ for (var i = 0; i < valueWordCount; i++) {
124
+ valueData.unshift(Number(tempValue & 1023n));
125
+ tempValue = tempValue >> 10n;
126
+ }
127
+ var shareData = this._encodeIdExp().concat(this._encodeShareParams()).concat(valueData);
128
+ var checksum = rs1024.createChecksum(shareData, _customizationString(this.extendable));
129
+ return Array.from(wordlist.wordsFromIndices(shareData.concat(checksum)));
130
+ };
131
+ Share.prototype.mnemonic = function () {
132
+ /** Convert share data to a share mnemonic. */
133
+ return this.words().join(' ');
134
+ };
135
+ Share.fromMnemonic = function (mnemonic) {
136
+ /** Convert a share mnemonic to share data. */
137
+ var mnemonicData = wordlist.mnemonicToIndices(mnemonic);
138
+ if (mnemonicData.length < constants_1.MIN_MNEMONIC_LENGTH_WORDS) {
139
+ throw new utils_1.MnemonicError("Invalid mnemonic length. The length of each mnemonic " +
140
+ "must be at least ".concat(constants_1.MIN_MNEMONIC_LENGTH_WORDS, " words."));
141
+ }
142
+ var paddingLen = (constants_1.RADIX_BITS * (mnemonicData.length - constants_1.METADATA_LENGTH_WORDS)) % 16;
143
+ if (paddingLen > 8) {
144
+ throw new utils_1.MnemonicError('Invalid mnemonic length.');
145
+ }
146
+ var idExpData = mnemonicData.slice(0, constants_1.ID_EXP_LENGTH_WORDS);
147
+ var idExpInt = _intFromWordIndices(idExpData);
148
+ var identifier = idExpInt >> (constants_1.EXTENDABLE_FLAG_LENGTH_BITS + constants_1.ITERATION_EXP_LENGTH_BITS);
149
+ var extendable = Boolean((idExpInt >> constants_1.ITERATION_EXP_LENGTH_BITS) & 1);
150
+ var iterationExponent = idExpInt & ((1 << constants_1.ITERATION_EXP_LENGTH_BITS) - 1);
151
+ if (!rs1024.verifyChecksum(mnemonicData, _customizationString(extendable))) {
152
+ var prefix = mnemonic.split(/\s+/).slice(0, constants_1.ID_EXP_LENGTH_WORDS + 2).join(' ');
153
+ throw new utils_1.MnemonicError("Invalid mnemonic checksum for \"".concat(prefix, " ...\"."));
154
+ }
155
+ var shareParamsData = mnemonicData.slice(constants_1.ID_EXP_LENGTH_WORDS, constants_1.ID_EXP_LENGTH_WORDS + 2);
156
+ var shareParamsInt = _intFromWordIndices(shareParamsData);
157
+ var shareParams = Array.from((0, utils_1.intToIndices)(shareParamsInt, 5, 4));
158
+ var groupIndex = shareParams[0], groupThreshold = shareParams[1], groupCount = shareParams[2], index = shareParams[3], memberThreshold = shareParams[4];
159
+ if (groupCount < groupThreshold) {
160
+ var prefix = mnemonic.split(/\s+/).slice(0, constants_1.ID_EXP_LENGTH_WORDS + 2).join(' ');
161
+ throw new utils_1.MnemonicError("Invalid mnemonic \"".concat(prefix, " ...\". Group threshold cannot be greater than group count."));
162
+ }
163
+ var valueData = mnemonicData.slice(constants_1.ID_EXP_LENGTH_WORDS + 2, mnemonicData.length - rs1024.CHECKSUM_LENGTH_WORDS);
164
+ var valueByteCount = (0, utils_1.bitsToBytes)(constants_1.RADIX_BITS * valueData.length - paddingLen);
165
+ // Convert word indices to BigInt (base 1024)
166
+ var valueInt = 0n;
167
+ for (var _i = 0, valueData_1 = valueData; _i < valueData_1.length; _i++) {
168
+ var index_1 = valueData_1[_i];
169
+ valueInt = valueInt * 1024n + BigInt(index_1);
170
+ }
171
+ // Convert BigInt to Buffer in big-endian format
172
+ var value;
173
+ try {
174
+ value = Buffer.allocUnsafe(valueByteCount);
175
+ var tempValue = valueInt;
176
+ for (var i = valueByteCount - 1; i >= 0; i--) {
177
+ value[i] = Number(tempValue & 0xffn);
178
+ tempValue = tempValue >> 8n;
179
+ }
180
+ if (tempValue !== 0n) {
181
+ var prefix = mnemonic.split(/\s+/).slice(0, constants_1.ID_EXP_LENGTH_WORDS + 2).join(' ');
182
+ throw new utils_1.MnemonicError("Invalid mnemonic padding for \"".concat(prefix, " ...\"."));
183
+ }
184
+ }
185
+ catch (error) {
186
+ if (error instanceof utils_1.MnemonicError) {
187
+ throw error;
188
+ }
189
+ var prefix = mnemonic.split(/\s+/).slice(0, constants_1.ID_EXP_LENGTH_WORDS + 2).join(' ');
190
+ throw new utils_1.MnemonicError("Invalid mnemonic padding for \"".concat(prefix, " ...\"."));
191
+ }
192
+ return new Share(identifier, extendable, iterationExponent, groupIndex, groupThreshold + 1, groupCount + 1, index, memberThreshold + 1, value);
193
+ };
194
+ return Share;
195
+ }());
196
+ exports.Share = Share;