@bcts/sskr 1.0.0-alpha.8 → 1.0.0-beta.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.
@@ -1,27 +1,26 @@
1
- var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
2
-
3
-
4
- //#region src/error.ts
5
- /**
1
+ var bctsSskr = (function(exports, _bcts_shamir, _bcts_rand) {
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ //#region src/error.ts
4
+ /**
6
5
  * Error types for SSKR operations.
7
6
  */
8
- let SSKRErrorType = /* @__PURE__ */ function(SSKRErrorType$1) {
9
- SSKRErrorType$1["DuplicateMemberIndex"] = "DuplicateMemberIndex";
10
- SSKRErrorType$1["GroupSpecInvalid"] = "GroupSpecInvalid";
11
- SSKRErrorType$1["GroupCountInvalid"] = "GroupCountInvalid";
12
- SSKRErrorType$1["GroupThresholdInvalid"] = "GroupThresholdInvalid";
13
- SSKRErrorType$1["MemberCountInvalid"] = "MemberCountInvalid";
14
- SSKRErrorType$1["MemberThresholdInvalid"] = "MemberThresholdInvalid";
15
- SSKRErrorType$1["NotEnoughGroups"] = "NotEnoughGroups";
16
- SSKRErrorType$1["SecretLengthNotEven"] = "SecretLengthNotEven";
17
- SSKRErrorType$1["SecretTooLong"] = "SecretTooLong";
18
- SSKRErrorType$1["SecretTooShort"] = "SecretTooShort";
19
- SSKRErrorType$1["ShareLengthInvalid"] = "ShareLengthInvalid";
20
- SSKRErrorType$1["ShareReservedBitsInvalid"] = "ShareReservedBitsInvalid";
21
- SSKRErrorType$1["SharesEmpty"] = "SharesEmpty";
22
- SSKRErrorType$1["ShareSetInvalid"] = "ShareSetInvalid";
23
- SSKRErrorType$1["ShamirError"] = "ShamirError";
24
- return SSKRErrorType$1;
7
+ let SSKRErrorType = /* @__PURE__ */ function(SSKRErrorType) {
8
+ SSKRErrorType["DuplicateMemberIndex"] = "DuplicateMemberIndex";
9
+ SSKRErrorType["GroupSpecInvalid"] = "GroupSpecInvalid";
10
+ SSKRErrorType["GroupCountInvalid"] = "GroupCountInvalid";
11
+ SSKRErrorType["GroupThresholdInvalid"] = "GroupThresholdInvalid";
12
+ SSKRErrorType["MemberCountInvalid"] = "MemberCountInvalid";
13
+ SSKRErrorType["MemberThresholdInvalid"] = "MemberThresholdInvalid";
14
+ SSKRErrorType["NotEnoughGroups"] = "NotEnoughGroups";
15
+ SSKRErrorType["SecretLengthNotEven"] = "SecretLengthNotEven";
16
+ SSKRErrorType["SecretTooLong"] = "SecretTooLong";
17
+ SSKRErrorType["SecretTooShort"] = "SecretTooShort";
18
+ SSKRErrorType["ShareLengthInvalid"] = "ShareLengthInvalid";
19
+ SSKRErrorType["ShareReservedBitsInvalid"] = "ShareReservedBitsInvalid";
20
+ SSKRErrorType["SharesEmpty"] = "SharesEmpty";
21
+ SSKRErrorType["ShareSetInvalid"] = "ShareSetInvalid";
22
+ SSKRErrorType["ShamirError"] = "ShamirError";
23
+ return SSKRErrorType;
25
24
  }({});
26
25
  /**
27
26
  * Error class for SSKR operations.
@@ -37,31 +36,35 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
37
36
  }
38
37
  static defaultMessage(type, shamirError) {
39
38
  switch (type) {
40
- case SSKRErrorType.DuplicateMemberIndex: return "When combining shares, the provided shares contained a duplicate member index";
41
- case SSKRErrorType.GroupSpecInvalid: return "Invalid group specification";
42
- case SSKRErrorType.GroupCountInvalid: return "When creating a split spec, the group count is invalid";
43
- case SSKRErrorType.GroupThresholdInvalid: return "SSKR group threshold is invalid";
44
- case SSKRErrorType.MemberCountInvalid: return "SSKR member count is invalid";
45
- case SSKRErrorType.MemberThresholdInvalid: return "SSKR member threshold is invalid";
46
- case SSKRErrorType.NotEnoughGroups: return "SSKR shares did not contain enough groups";
47
- case SSKRErrorType.SecretLengthNotEven: return "SSKR secret is not of even length";
48
- case SSKRErrorType.SecretTooLong: return "SSKR secret is too long";
49
- case SSKRErrorType.SecretTooShort: return "SSKR secret is too short";
50
- case SSKRErrorType.ShareLengthInvalid: return "SSKR shares did not contain enough serialized bytes";
51
- case SSKRErrorType.ShareReservedBitsInvalid: return "SSKR shares contained invalid reserved bits";
52
- case SSKRErrorType.SharesEmpty: return "SSKR shares were empty";
53
- case SSKRErrorType.ShareSetInvalid: return "SSKR shares were invalid";
54
- case SSKRErrorType.ShamirError: return shamirError != null ? `SSKR Shamir error: ${shamirError.message}` : "SSKR Shamir error";
39
+ case "DuplicateMemberIndex": return "When combining shares, the provided shares contained a duplicate member index";
40
+ case "GroupSpecInvalid": return "Invalid group specification.";
41
+ case "GroupCountInvalid": return "When creating a split spec, the group count is invalid";
42
+ case "GroupThresholdInvalid": return "SSKR group threshold is invalid";
43
+ case "MemberCountInvalid": return "SSKR member count is invalid";
44
+ case "MemberThresholdInvalid": return "SSKR member threshold is invalid";
45
+ case "NotEnoughGroups": return "SSKR shares did not contain enough groups";
46
+ case "SecretLengthNotEven": return "SSKR secret is not of even length";
47
+ case "SecretTooLong": return "SSKR secret is too long";
48
+ case "SecretTooShort": return "SSKR secret is too short";
49
+ case "ShareLengthInvalid": return "SSKR shares did not contain enough serialized bytes";
50
+ case "ShareReservedBitsInvalid": return "SSKR shares contained invalid reserved bits";
51
+ case "SharesEmpty": return "SSKR shares were empty";
52
+ case "ShareSetInvalid": return "SSKR shares were invalid";
53
+ case "ShamirError": return shamirError != null ? `SSKR Shamir error: ${shamirError.message}` : "SSKR Shamir error";
55
54
  }
56
55
  }
57
56
  static fromShamirError(error) {
58
- return new SSKRError(SSKRErrorType.ShamirError, void 0, error);
57
+ return new SSKRError("ShamirError", void 0, error);
59
58
  }
60
59
  };
61
-
62
- //#endregion
63
- //#region src/secret.ts
64
- /**
60
+ //#endregion
61
+ //#region src/secret.ts
62
+ /**
63
+ * Copyright © 2023-2026 Blockchain Commons, LLC
64
+ * Copyright © 2025-2026 Parity Technologies
65
+ *
66
+ */
67
+ /**
65
68
  * A secret to be split into shares.
66
69
  */
67
70
  var Secret = class Secret {
@@ -80,9 +83,9 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
80
83
  static new(data) {
81
84
  const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
82
85
  const len = bytes.length;
83
- if (len < MIN_SECRET_LEN) throw new SSKRError(SSKRErrorType.SecretTooShort);
84
- if (len > MAX_SECRET_LEN) throw new SSKRError(SSKRErrorType.SecretTooLong);
85
- if ((len & 1) !== 0) throw new SSKRError(SSKRErrorType.SecretLengthNotEven);
86
+ if (len < MIN_SECRET_LEN) throw new SSKRError("SecretTooShort");
87
+ if (len > MAX_SECRET_LEN) throw new SSKRError("SecretTooLong");
88
+ if ((len & 1) !== 0) throw new SSKRError("SecretLengthNotEven");
86
89
  return new Secret(new Uint8Array(bytes));
87
90
  }
88
91
  /**
@@ -99,12 +102,24 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
99
102
  }
100
103
  /**
101
104
  * Returns a reference to the secret data.
105
+ *
106
+ * Mirrors Rust's `Secret::data(&self) -> &[u8]`
107
+ * (`bc-sskr-rust/src/secret.rs:43`).
102
108
  */
103
109
  getData() {
104
110
  return this.data;
105
111
  }
106
112
  /**
107
113
  * Returns the secret data as a Uint8Array.
114
+ *
115
+ * Mirrors Rust's `impl AsRef<[u8]> for Secret`
116
+ * (`bc-sskr-rust/src/secret.rs:46-49`). In Rust, `as_ref()` is
117
+ * provided via the `AsRef<[u8]>` trait, which lets the `Secret` flow
118
+ * naturally through any API expecting `impl AsRef<[u8]>`. TypeScript
119
+ * has no equivalent of that trait, so we expose the same backing
120
+ * buffer through both {@link getData} (the field accessor) and
121
+ * `asRef` (the trait-style accessor) for ergonomic parity. Callers
122
+ * may pick whichever name reads better at the call site.
108
123
  */
109
124
  asRef() {
110
125
  return this.data;
@@ -124,10 +139,30 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
124
139
  return new Secret(new Uint8Array(this.data));
125
140
  }
126
141
  };
127
-
128
- //#endregion
129
- //#region src/spec.ts
130
- /**
142
+ //#endregion
143
+ //#region src/spec.ts
144
+ /**
145
+ * Copyright © 2023-2026 Blockchain Commons, LLC
146
+ * Copyright © 2025-2026 Parity Technologies
147
+ *
148
+ */
149
+ /**
150
+ * Strictly parses a non-negative integer string the way Rust's
151
+ * `<usize as FromStr>::from_str` does (`bc-sskr-rust/src/spec.rs:102, 108`).
152
+ *
153
+ * Accepts an optional leading `+` followed by one or more decimal digits.
154
+ * Rejects whitespace, decimals (`"2.5"`), trailing characters (`"2x"`),
155
+ * the `-` sign, and the empty string. Returns `undefined` on rejection so
156
+ * callers surface the appropriate `GroupSpecInvalid` error in the same
157
+ * spot Rust's `?` would.
158
+ */
159
+ const STRICT_USIZE_RE = /^\+?\d+$/;
160
+ function parseStrictUsize(s) {
161
+ if (!STRICT_USIZE_RE.test(s)) return void 0;
162
+ const n = Number(s);
163
+ return Number.isSafeInteger(n) ? n : void 0;
164
+ }
165
+ /**
131
166
  * A specification for a group of shares within an SSKR split.
132
167
  */
133
168
  var GroupSpec = class GroupSpec {
@@ -149,9 +184,9 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
149
184
  * greater than the member count.
150
185
  */
151
186
  static new(memberThreshold, memberCount) {
152
- if (memberCount === 0) throw new SSKRError(SSKRErrorType.MemberCountInvalid);
153
- if (memberCount > __bcts_shamir.MAX_SHARE_COUNT) throw new SSKRError(SSKRErrorType.MemberCountInvalid);
154
- if (memberThreshold > memberCount) throw new SSKRError(SSKRErrorType.MemberThresholdInvalid);
187
+ if (memberCount === 0) throw new SSKRError("MemberCountInvalid");
188
+ if (memberCount > _bcts_shamir.MAX_SHARE_COUNT) throw new SSKRError("MemberCountInvalid");
189
+ if (memberThreshold > memberCount) throw new SSKRError("MemberThresholdInvalid");
155
190
  return new GroupSpec(memberThreshold, memberCount);
156
191
  }
157
192
  /**
@@ -168,16 +203,24 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
168
203
  }
169
204
  /**
170
205
  * Parses a group specification from a string.
171
- * Format: "M-of-N" where M is the threshold and N is the count.
206
+ * Format: `"M-of-N"` where `M` is the threshold and `N` is the count.
207
+ *
208
+ * Mirrors Rust's `GroupSpec::parse` (`bc-sskr-rust/src/spec.rs:97-112`),
209
+ * which calls `parts[0].parse::<usize>()`. Rust's `usize::FromStr` is
210
+ * strict: it rejects whitespace, decimals, trailing characters, and the
211
+ * `-` sign, accepting only an optional `+` prefix followed by digits.
212
+ * We mirror that with the regex `^\+?\d+$` so strings like `"2.5"`,
213
+ * `"2x"`, `" 2"`, `"-2"`, and `""` all surface
214
+ * {@link SSKRErrorType.GroupSpecInvalid} on both sides.
172
215
  */
173
216
  static parse(s) {
174
217
  const parts = s.split("-");
175
- if (parts.length !== 3) throw new SSKRError(SSKRErrorType.GroupSpecInvalid);
176
- const memberThreshold = parseInt(parts[0], 10);
177
- if (isNaN(memberThreshold)) throw new SSKRError(SSKRErrorType.GroupSpecInvalid);
178
- if (parts[1] !== "of") throw new SSKRError(SSKRErrorType.GroupSpecInvalid);
179
- const memberCount = parseInt(parts[2], 10);
180
- if (isNaN(memberCount)) throw new SSKRError(SSKRErrorType.GroupSpecInvalid);
218
+ if (parts.length !== 3) throw new SSKRError("GroupSpecInvalid");
219
+ const memberThreshold = parseStrictUsize(parts[0]);
220
+ if (memberThreshold === void 0) throw new SSKRError("GroupSpecInvalid");
221
+ if (parts[1] !== "of") throw new SSKRError("GroupSpecInvalid");
222
+ const memberCount = parseStrictUsize(parts[2]);
223
+ if (memberCount === void 0) throw new SSKRError("GroupSpecInvalid");
181
224
  return GroupSpec.new(memberThreshold, memberCount);
182
225
  }
183
226
  /**
@@ -216,9 +259,9 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
216
259
  * greater than the maximum share count.
217
260
  */
218
261
  static new(groupThreshold, groups) {
219
- if (groupThreshold === 0) throw new SSKRError(SSKRErrorType.GroupThresholdInvalid);
220
- if (groupThreshold > groups.length) throw new SSKRError(SSKRErrorType.GroupThresholdInvalid);
221
- if (groups.length > __bcts_shamir.MAX_SHARE_COUNT) throw new SSKRError(SSKRErrorType.GroupCountInvalid);
262
+ if (groupThreshold === 0) throw new SSKRError("GroupThresholdInvalid");
263
+ if (groupThreshold > groups.length) throw new SSKRError("GroupThresholdInvalid");
264
+ if (groups.length > _bcts_shamir.MAX_SHARE_COUNT) throw new SSKRError("GroupCountInvalid");
222
265
  return new Spec(groupThreshold, groups);
223
266
  }
224
267
  /**
@@ -246,10 +289,9 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
246
289
  return this._groups.reduce((sum, g) => sum + g.memberCount(), 0);
247
290
  }
248
291
  };
249
-
250
- //#endregion
251
- //#region src/share.ts
252
- /**
292
+ //#endregion
293
+ //#region src/share.ts
294
+ /**
253
295
  * A share in the SSKR scheme.
254
296
  */
255
297
  var SSKRShare = class {
@@ -291,10 +333,9 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
291
333
  return this._value;
292
334
  }
293
335
  };
294
-
295
- //#endregion
296
- //#region src/encoding.ts
297
- /**
336
+ //#endregion
337
+ //#region src/encoding.ts
338
+ /**
298
339
  * Generates SSKR shares for the given Spec and Secret.
299
340
  *
300
341
  * @param spec - The Spec instance that defines the group and member thresholds.
@@ -303,7 +344,7 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
303
344
  * each of which is a Uint8Array.
304
345
  */
305
346
  function sskrGenerate(spec, masterSecret) {
306
- return sskrGenerateUsing(spec, masterSecret, new __bcts_rand.SecureRandomNumberGenerator());
347
+ return sskrGenerateUsing(spec, masterSecret, new _bcts_rand.SecureRandomNumberGenerator());
307
348
  }
308
349
  /**
309
350
  * Generates SSKR shares for the given Spec and Secret using the provided
@@ -337,7 +378,7 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
337
378
  }
338
379
  function serializeShare(share) {
339
380
  const valueData = share.value().getData();
340
- const result = new Uint8Array(valueData.length + METADATA_SIZE_BYTES);
381
+ const result = new Uint8Array(valueData.length + 5);
341
382
  const id = share.identifier();
342
383
  const gt = share.groupThreshold() - 1 & 15;
343
384
  const gc = share.groupCount() - 1 & 15;
@@ -351,19 +392,19 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
351
392
  result[2] = gt << 4 | gc;
352
393
  result[3] = gi << 4 | mt;
353
394
  result[4] = mi;
354
- result.set(valueData, METADATA_SIZE_BYTES);
395
+ result.set(valueData, 5);
355
396
  return result;
356
397
  }
357
398
  function deserializeShare(source) {
358
- if (source.length < METADATA_SIZE_BYTES) throw new SSKRError(SSKRErrorType.ShareLengthInvalid);
399
+ if (source.length < 5) throw new SSKRError("ShareLengthInvalid");
359
400
  const groupThreshold = (source[2] >> 4) + 1;
360
401
  const groupCount = (source[2] & 15) + 1;
361
- if (groupThreshold > groupCount) throw new SSKRError(SSKRErrorType.GroupThresholdInvalid);
402
+ if (groupThreshold > groupCount) throw new SSKRError("GroupThresholdInvalid");
362
403
  const identifier = source[0] << 8 | source[1];
363
404
  const groupIndex = source[3] >> 4;
364
405
  const memberThreshold = (source[3] & 15) + 1;
365
- if (source[4] >> 4 !== 0) throw new SSKRError(SSKRErrorType.ShareReservedBitsInvalid);
366
- return new SSKRShare(identifier, groupIndex, groupThreshold, groupCount, source[4] & 15, memberThreshold, Secret.new(source.subarray(METADATA_SIZE_BYTES)));
406
+ if (source[4] >> 4 !== 0) throw new SSKRError("ShareReservedBitsInvalid");
407
+ return new SSKRShare(identifier, groupIndex, groupThreshold, groupCount, source[4] & 15, memberThreshold, Secret.new(source.subarray(5)));
367
408
  }
368
409
  function generateShares(spec, masterSecret, randomGenerator) {
369
410
  const identifierBytes = new Uint8Array(2);
@@ -372,9 +413,9 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
372
413
  const groupsShares = [];
373
414
  let groupSecrets;
374
415
  try {
375
- groupSecrets = (0, __bcts_shamir.splitSecret)(spec.groupThreshold(), spec.groupCount(), masterSecret.getData(), randomGenerator);
416
+ groupSecrets = (0, _bcts_shamir.splitSecret)(spec.groupThreshold(), spec.groupCount(), masterSecret.getData(), randomGenerator);
376
417
  } catch (e) {
377
- if (e instanceof __bcts_shamir.ShamirError) throw SSKRError.fromShamirError(e);
418
+ if (e instanceof _bcts_shamir.ShamirError) throw SSKRError.fromShamirError(e);
378
419
  throw e;
379
420
  }
380
421
  for (let groupIndex = 0; groupIndex < spec.groups().length; groupIndex++) {
@@ -382,9 +423,9 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
382
423
  const groupSecret = groupSecrets[groupIndex];
383
424
  let memberSecrets;
384
425
  try {
385
- memberSecrets = (0, __bcts_shamir.splitSecret)(group.memberThreshold(), group.memberCount(), groupSecret, randomGenerator);
426
+ memberSecrets = (0, _bcts_shamir.splitSecret)(group.memberThreshold(), group.memberCount(), groupSecret, randomGenerator);
386
427
  } catch (e) {
387
- if (e instanceof __bcts_shamir.ShamirError) throw SSKRError.fromShamirError(e);
428
+ if (e instanceof _bcts_shamir.ShamirError) throw SSKRError.fromShamirError(e);
388
429
  throw e;
389
430
  }
390
431
  const memberSSKRShares = memberSecrets.map((memberSecret, memberIndex) => {
@@ -399,7 +440,7 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
399
440
  let identifier = 0;
400
441
  let groupThreshold = 0;
401
442
  let groupCount = 0;
402
- if (shares.length === 0) throw new SSKRError(SSKRErrorType.SharesEmpty);
443
+ if (shares.length === 0) throw new SSKRError("SharesEmpty");
403
444
  let nextGroup = 0;
404
445
  const groups = [];
405
446
  let secretLen = 0;
@@ -410,12 +451,12 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
410
451
  groupCount = share.groupCount();
411
452
  groupThreshold = share.groupThreshold();
412
453
  secretLen = share.value().len();
413
- } else if (share.identifier() !== identifier || share.groupThreshold() !== groupThreshold || share.groupCount() !== groupCount || share.value().len() !== secretLen) throw new SSKRError(SSKRErrorType.ShareSetInvalid);
454
+ } else if (share.identifier() !== identifier || share.groupThreshold() !== groupThreshold || share.groupCount() !== groupCount || share.value().len() !== secretLen) throw new SSKRError("ShareSetInvalid");
414
455
  let groupFound = false;
415
456
  for (const group of groups) if (share.groupIndex() === group.groupIndex) {
416
457
  groupFound = true;
417
- if (share.memberThreshold() !== group.memberThreshold) throw new SSKRError(SSKRErrorType.MemberThresholdInvalid);
418
- for (const memberIndex of group.memberIndexes) if (share.memberIndex() === memberIndex) throw new SSKRError(SSKRErrorType.DuplicateMemberIndex);
458
+ if (share.memberThreshold() !== group.memberThreshold) throw new SSKRError("MemberThresholdInvalid");
459
+ for (const memberIndex of group.memberIndexes) if (share.memberIndex() === memberIndex) throw new SSKRError("DuplicateMemberIndex");
419
460
  if (group.memberIndexes.length < group.memberThreshold) {
420
461
  group.memberIndexes.push(share.memberIndex());
421
462
  group.memberShares.push(share.value().clone());
@@ -432,46 +473,51 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
432
473
  nextGroup++;
433
474
  }
434
475
  }
435
- if (nextGroup < groupThreshold) throw new SSKRError(SSKRErrorType.NotEnoughGroups);
476
+ if (nextGroup < groupThreshold) throw new SSKRError("NotEnoughGroups");
436
477
  const masterIndexes = [];
437
478
  const masterShares = [];
438
479
  for (const group of groups) {
439
480
  if (group.memberIndexes.length < group.memberThreshold) continue;
440
481
  try {
441
482
  const memberSharesData = group.memberShares.map((s) => s.getData());
442
- const groupSecret = (0, __bcts_shamir.recoverSecret)(group.memberIndexes, memberSharesData);
483
+ const groupSecret = (0, _bcts_shamir.recoverSecret)(group.memberIndexes, memberSharesData);
443
484
  masterIndexes.push(group.groupIndex);
444
485
  masterShares.push(groupSecret);
445
- } catch {
446
- continue;
486
+ } catch (e) {
487
+ if (e instanceof _bcts_shamir.ShamirError) continue;
488
+ throw e;
447
489
  }
448
490
  if (masterIndexes.length === groupThreshold) break;
449
491
  }
450
- if (masterIndexes.length < groupThreshold) throw new SSKRError(SSKRErrorType.NotEnoughGroups);
492
+ if (masterIndexes.length < groupThreshold) throw new SSKRError("NotEnoughGroups");
451
493
  let masterSecretData;
452
494
  try {
453
- masterSecretData = (0, __bcts_shamir.recoverSecret)(masterIndexes, masterShares);
495
+ masterSecretData = (0, _bcts_shamir.recoverSecret)(masterIndexes, masterShares);
454
496
  } catch (e) {
455
- if (e instanceof __bcts_shamir.ShamirError) throw SSKRError.fromShamirError(e);
497
+ if (e instanceof _bcts_shamir.ShamirError) throw SSKRError.fromShamirError(e);
456
498
  throw e;
457
499
  }
458
500
  return Secret.new(masterSecretData);
459
501
  }
460
-
461
- //#endregion
462
- //#region src/index.ts
463
- /**
502
+ //#endregion
503
+ //#region src/index.ts
504
+ /**
505
+ * Copyright © 2023-2026 Blockchain Commons, LLC
506
+ * Copyright © 2025-2026 Parity Technologies
507
+ *
508
+ */
509
+ /**
464
510
  * The minimum length of a secret.
465
511
  */
466
- const MIN_SECRET_LEN = __bcts_shamir.MIN_SECRET_LEN;
512
+ const MIN_SECRET_LEN = _bcts_shamir.MIN_SECRET_LEN;
467
513
  /**
468
514
  * The maximum length of a secret.
469
515
  */
470
- const MAX_SECRET_LEN = __bcts_shamir.MAX_SECRET_LEN;
516
+ const MAX_SECRET_LEN = _bcts_shamir.MAX_SECRET_LEN;
471
517
  /**
472
518
  * The maximum number of shares that can be generated from a secret.
473
519
  */
474
- const MAX_SHARE_COUNT = __bcts_shamir.MAX_SHARE_COUNT;
520
+ const MAX_SHARE_COUNT = _bcts_shamir.MAX_SHARE_COUNT;
475
521
  /**
476
522
  * The maximum number of groups in a split.
477
523
  */
@@ -483,24 +529,23 @@ var BCSSKR = (function(exports, __bcts_shamir, __bcts_rand) {
483
529
  /**
484
530
  * The minimum number of bytes required to encode a share.
485
531
  */
486
- const MIN_SERIALIZE_SIZE_BYTES = METADATA_SIZE_BYTES + MIN_SECRET_LEN;
532
+ const MIN_SERIALIZE_SIZE_BYTES = 5 + MIN_SECRET_LEN;
533
+ //#endregion
534
+ exports.GroupSpec = GroupSpec;
535
+ exports.MAX_GROUPS_COUNT = MAX_GROUPS_COUNT;
536
+ exports.MAX_SECRET_LEN = MAX_SECRET_LEN;
537
+ exports.MAX_SHARE_COUNT = MAX_SHARE_COUNT;
538
+ exports.METADATA_SIZE_BYTES = METADATA_SIZE_BYTES;
539
+ exports.MIN_SECRET_LEN = MIN_SECRET_LEN;
540
+ exports.MIN_SERIALIZE_SIZE_BYTES = MIN_SERIALIZE_SIZE_BYTES;
541
+ exports.SSKRError = SSKRError;
542
+ exports.SSKRErrorType = SSKRErrorType;
543
+ exports.Secret = Secret;
544
+ exports.Spec = Spec;
545
+ exports.sskrCombine = sskrCombine;
546
+ exports.sskrGenerate = sskrGenerate;
547
+ exports.sskrGenerateUsing = sskrGenerateUsing;
548
+ return exports;
549
+ })({}, bctsShamir, bctsRand);
487
550
 
488
- //#endregion
489
- exports.GroupSpec = GroupSpec;
490
- exports.MAX_GROUPS_COUNT = MAX_GROUPS_COUNT;
491
- exports.MAX_SECRET_LEN = MAX_SECRET_LEN;
492
- exports.MAX_SHARE_COUNT = MAX_SHARE_COUNT;
493
- exports.METADATA_SIZE_BYTES = METADATA_SIZE_BYTES;
494
- exports.MIN_SECRET_LEN = MIN_SECRET_LEN;
495
- exports.MIN_SERIALIZE_SIZE_BYTES = MIN_SERIALIZE_SIZE_BYTES;
496
- exports.SSKRError = SSKRError;
497
- exports.SSKRErrorType = SSKRErrorType;
498
- exports.SSKRShare = SSKRShare;
499
- exports.Secret = Secret;
500
- exports.Spec = Spec;
501
- exports.sskrCombine = sskrCombine;
502
- exports.sskrGenerate = sskrGenerate;
503
- exports.sskrGenerateUsing = sskrGenerateUsing;
504
- return exports;
505
- })({}, BCShamir, BCRand);
506
551
  //# sourceMappingURL=index.iife.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.iife.js","names":["MAX_SHARE_COUNT","SecureRandomNumberGenerator","sskrShares: SSKRShare[]","groupsShares: SSKRShare[][]","groupSecrets: Uint8Array[]","ShamirError","memberSecrets: Uint8Array[]","memberSSKRShares: SSKRShare[]","groups: Group[]","g: Group","masterIndexes: number[]","masterShares: Uint8Array[]","masterSecretData: Uint8Array","SHAMIR_MIN_SECRET_LEN","SHAMIR_MAX_SECRET_LEN","SHAMIR_MAX_SHARE_COUNT"],"sources":["../src/error.ts","../src/secret.ts","../src/spec.ts","../src/share.ts","../src/encoding.ts","../src/index.ts"],"sourcesContent":["// Ported from bc-sskr-rust/src/error.rs\n\nimport type { ShamirError } from \"@bcts/shamir\";\n\n/**\n * Error types for SSKR operations.\n */\nexport enum SSKRErrorType {\n DuplicateMemberIndex = \"DuplicateMemberIndex\",\n GroupSpecInvalid = \"GroupSpecInvalid\",\n GroupCountInvalid = \"GroupCountInvalid\",\n GroupThresholdInvalid = \"GroupThresholdInvalid\",\n MemberCountInvalid = \"MemberCountInvalid\",\n MemberThresholdInvalid = \"MemberThresholdInvalid\",\n NotEnoughGroups = \"NotEnoughGroups\",\n SecretLengthNotEven = \"SecretLengthNotEven\",\n SecretTooLong = \"SecretTooLong\",\n SecretTooShort = \"SecretTooShort\",\n ShareLengthInvalid = \"ShareLengthInvalid\",\n ShareReservedBitsInvalid = \"ShareReservedBitsInvalid\",\n SharesEmpty = \"SharesEmpty\",\n ShareSetInvalid = \"ShareSetInvalid\",\n ShamirError = \"ShamirError\",\n}\n\n/**\n * Error class for SSKR operations.\n */\nexport class SSKRError extends Error {\n readonly type: SSKRErrorType;\n readonly shamirError?: ShamirError | undefined;\n\n constructor(type: SSKRErrorType, message?: string, shamirError?: ShamirError) {\n super(message ?? SSKRError.defaultMessage(type, shamirError));\n this.type = type;\n this.shamirError = shamirError;\n this.name = \"SSKRError\";\n }\n\n private static defaultMessage(type: SSKRErrorType, shamirError?: ShamirError): string {\n switch (type) {\n case SSKRErrorType.DuplicateMemberIndex:\n return \"When combining shares, the provided shares contained a duplicate member index\";\n case SSKRErrorType.GroupSpecInvalid:\n return \"Invalid group specification\";\n case SSKRErrorType.GroupCountInvalid:\n return \"When creating a split spec, the group count is invalid\";\n case SSKRErrorType.GroupThresholdInvalid:\n return \"SSKR group threshold is invalid\";\n case SSKRErrorType.MemberCountInvalid:\n return \"SSKR member count is invalid\";\n case SSKRErrorType.MemberThresholdInvalid:\n return \"SSKR member threshold is invalid\";\n case SSKRErrorType.NotEnoughGroups:\n return \"SSKR shares did not contain enough groups\";\n case SSKRErrorType.SecretLengthNotEven:\n return \"SSKR secret is not of even length\";\n case SSKRErrorType.SecretTooLong:\n return \"SSKR secret is too long\";\n case SSKRErrorType.SecretTooShort:\n return \"SSKR secret is too short\";\n case SSKRErrorType.ShareLengthInvalid:\n return \"SSKR shares did not contain enough serialized bytes\";\n case SSKRErrorType.ShareReservedBitsInvalid:\n return \"SSKR shares contained invalid reserved bits\";\n case SSKRErrorType.SharesEmpty:\n return \"SSKR shares were empty\";\n case SSKRErrorType.ShareSetInvalid:\n return \"SSKR shares were invalid\";\n case SSKRErrorType.ShamirError:\n return shamirError != null\n ? `SSKR Shamir error: ${shamirError.message}`\n : \"SSKR Shamir error\";\n }\n }\n\n static fromShamirError(error: ShamirError): SSKRError {\n return new SSKRError(SSKRErrorType.ShamirError, undefined, error);\n }\n}\n\nexport type SSKRResult<T> = T;\n","// Ported from bc-sskr-rust/src/secret.rs\n\nimport { MIN_SECRET_LEN, MAX_SECRET_LEN } from \"./index.js\";\nimport { SSKRError, SSKRErrorType } from \"./error.js\";\n\n/**\n * A secret to be split into shares.\n */\nexport class Secret {\n private readonly data: Uint8Array;\n\n private constructor(data: Uint8Array) {\n this.data = data;\n }\n\n /**\n * Creates a new Secret instance with the given data.\n *\n * @param data - The secret data to be split into shares.\n * @returns A new Secret instance.\n * @throws SSKRError if the length of the secret is less than\n * MIN_SECRET_LEN, greater than MAX_SECRET_LEN, or not even.\n */\n static new(data: Uint8Array | string): Secret {\n const bytes = typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n const len = bytes.length;\n\n if (len < MIN_SECRET_LEN) {\n throw new SSKRError(SSKRErrorType.SecretTooShort);\n }\n if (len > MAX_SECRET_LEN) {\n throw new SSKRError(SSKRErrorType.SecretTooLong);\n }\n if ((len & 1) !== 0) {\n throw new SSKRError(SSKRErrorType.SecretLengthNotEven);\n }\n\n return new Secret(new Uint8Array(bytes));\n }\n\n /**\n * Returns the length of the secret.\n */\n len(): number {\n return this.data.length;\n }\n\n /**\n * Returns true if the secret is empty.\n */\n isEmpty(): boolean {\n return this.len() === 0;\n }\n\n /**\n * Returns a reference to the secret data.\n */\n getData(): Uint8Array {\n return this.data;\n }\n\n /**\n * Returns the secret data as a Uint8Array.\n */\n asRef(): Uint8Array {\n return this.data;\n }\n\n /**\n * Check equality with another Secret.\n */\n equals(other: Secret): boolean {\n if (this.data.length !== other.data.length) {\n return false;\n }\n for (let i = 0; i < this.data.length; i++) {\n if (this.data[i] !== other.data[i]) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Clone the secret.\n */\n clone(): Secret {\n return new Secret(new Uint8Array(this.data));\n }\n}\n","// Ported from bc-sskr-rust/src/spec.rs\n\nimport { MAX_SHARE_COUNT } from \"@bcts/shamir\";\nimport { SSKRError, SSKRErrorType } from \"./error.js\";\n\n/**\n * A specification for a group of shares within an SSKR split.\n */\nexport class GroupSpec {\n private readonly _memberThreshold: number;\n private readonly _memberCount: number;\n\n private constructor(memberThreshold: number, memberCount: number) {\n this._memberThreshold = memberThreshold;\n this._memberCount = memberCount;\n }\n\n /**\n * Creates a new GroupSpec instance with the given member threshold and count.\n *\n * @param memberThreshold - The minimum number of member shares required to\n * reconstruct the secret within the group.\n * @param memberCount - The total number of member shares in the group.\n * @returns A new GroupSpec instance.\n * @throws SSKRError if the member count is zero, if the member count is\n * greater than the maximum share count, or if the member threshold is\n * greater than the member count.\n */\n static new(memberThreshold: number, memberCount: number): GroupSpec {\n if (memberCount === 0) {\n throw new SSKRError(SSKRErrorType.MemberCountInvalid);\n }\n if (memberCount > MAX_SHARE_COUNT) {\n throw new SSKRError(SSKRErrorType.MemberCountInvalid);\n }\n if (memberThreshold > memberCount) {\n throw new SSKRError(SSKRErrorType.MemberThresholdInvalid);\n }\n return new GroupSpec(memberThreshold, memberCount);\n }\n\n /**\n * Returns the member share threshold for this group.\n */\n memberThreshold(): number {\n return this._memberThreshold;\n }\n\n /**\n * Returns the number of member shares in this group.\n */\n memberCount(): number {\n return this._memberCount;\n }\n\n /**\n * Parses a group specification from a string.\n * Format: \"M-of-N\" where M is the threshold and N is the count.\n */\n static parse(s: string): GroupSpec {\n const parts = s.split(\"-\");\n if (parts.length !== 3) {\n throw new SSKRError(SSKRErrorType.GroupSpecInvalid);\n }\n\n const memberThreshold = parseInt(parts[0], 10);\n if (isNaN(memberThreshold)) {\n throw new SSKRError(SSKRErrorType.GroupSpecInvalid);\n }\n\n if (parts[1] !== \"of\") {\n throw new SSKRError(SSKRErrorType.GroupSpecInvalid);\n }\n\n const memberCount = parseInt(parts[2], 10);\n if (isNaN(memberCount)) {\n throw new SSKRError(SSKRErrorType.GroupSpecInvalid);\n }\n\n return GroupSpec.new(memberThreshold, memberCount);\n }\n\n /**\n * Creates a default GroupSpec (1-of-1).\n */\n static default(): GroupSpec {\n return GroupSpec.new(1, 1);\n }\n\n /**\n * Returns a string representation of the group spec.\n */\n toString(): string {\n return `${this._memberThreshold}-of-${this._memberCount}`;\n }\n}\n\n/**\n * A specification for an SSKR split.\n */\nexport class Spec {\n private readonly _groupThreshold: number;\n private readonly _groups: GroupSpec[];\n\n private constructor(groupThreshold: number, groups: GroupSpec[]) {\n this._groupThreshold = groupThreshold;\n this._groups = groups;\n }\n\n /**\n * Creates a new Spec instance with the given group threshold and groups.\n *\n * @param groupThreshold - The minimum number of groups required to\n * reconstruct the secret.\n * @param groups - The list of GroupSpec instances that define the groups\n * and their members.\n * @returns A new Spec instance.\n * @throws SSKRError if the group threshold is zero, if the group threshold\n * is greater than the number of groups, or if the number of groups is\n * greater than the maximum share count.\n */\n static new(groupThreshold: number, groups: GroupSpec[]): Spec {\n if (groupThreshold === 0) {\n throw new SSKRError(SSKRErrorType.GroupThresholdInvalid);\n }\n if (groupThreshold > groups.length) {\n throw new SSKRError(SSKRErrorType.GroupThresholdInvalid);\n }\n if (groups.length > MAX_SHARE_COUNT) {\n throw new SSKRError(SSKRErrorType.GroupCountInvalid);\n }\n return new Spec(groupThreshold, groups);\n }\n\n /**\n * Returns the group threshold.\n */\n groupThreshold(): number {\n return this._groupThreshold;\n }\n\n /**\n * Returns a slice of the group specifications.\n */\n groups(): GroupSpec[] {\n return this._groups;\n }\n\n /**\n * Returns the number of groups.\n */\n groupCount(): number {\n return this._groups.length;\n }\n\n /**\n * Returns the total number of shares across all groups.\n */\n shareCount(): number {\n return this._groups.reduce((sum, g) => sum + g.memberCount(), 0);\n }\n}\n","// Ported from bc-sskr-rust/src/share.rs\n\nimport type { Secret } from \"./secret.js\";\n\n/**\n * A share in the SSKR scheme.\n */\nexport class SSKRShare {\n private readonly _identifier: number;\n private readonly _groupIndex: number;\n private readonly _groupThreshold: number;\n private readonly _groupCount: number;\n private readonly _memberIndex: number;\n private readonly _memberThreshold: number;\n private readonly _value: Secret;\n\n constructor(\n identifier: number,\n groupIndex: number,\n groupThreshold: number,\n groupCount: number,\n memberIndex: number,\n memberThreshold: number,\n value: Secret,\n ) {\n this._identifier = identifier;\n this._groupIndex = groupIndex;\n this._groupThreshold = groupThreshold;\n this._groupCount = groupCount;\n this._memberIndex = memberIndex;\n this._memberThreshold = memberThreshold;\n this._value = value;\n }\n\n identifier(): number {\n return this._identifier;\n }\n\n groupIndex(): number {\n return this._groupIndex;\n }\n\n groupThreshold(): number {\n return this._groupThreshold;\n }\n\n groupCount(): number {\n return this._groupCount;\n }\n\n memberIndex(): number {\n return this._memberIndex;\n }\n\n memberThreshold(): number {\n return this._memberThreshold;\n }\n\n value(): Secret {\n return this._value;\n }\n}\n","// Ported from bc-sskr-rust/src/encoding.rs\n\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { SecureRandomNumberGenerator } from \"@bcts/rand\";\nimport { splitSecret, recoverSecret, ShamirError } from \"@bcts/shamir\";\n\nimport { SSKRError, SSKRErrorType } from \"./error.js\";\nimport { Secret } from \"./secret.js\";\nimport type { Spec } from \"./spec.js\";\nimport { SSKRShare } from \"./share.js\";\nimport { METADATA_SIZE_BYTES } from \"./index.js\";\n\n/**\n * Generates SSKR shares for the given Spec and Secret.\n *\n * @param spec - The Spec instance that defines the group and member thresholds.\n * @param masterSecret - The Secret instance to be split into shares.\n * @returns A vector of groups, each containing a vector of shares,\n * each of which is a Uint8Array.\n */\nexport function sskrGenerate(spec: Spec, masterSecret: Secret): Uint8Array[][] {\n const rng = new SecureRandomNumberGenerator();\n return sskrGenerateUsing(spec, masterSecret, rng);\n}\n\n/**\n * Generates SSKR shares for the given Spec and Secret using the provided\n * random number generator.\n *\n * @param spec - The Spec instance that defines the group and member thresholds.\n * @param masterSecret - The Secret instance to be split into shares.\n * @param randomGenerator - The random number generator to use for generating\n * shares.\n * @returns A vector of groups, each containing a vector of shares,\n * each of which is a Uint8Array.\n */\nexport function sskrGenerateUsing(\n spec: Spec,\n masterSecret: Secret,\n randomGenerator: RandomNumberGenerator,\n): Uint8Array[][] {\n const groupsShares = generateShares(spec, masterSecret, randomGenerator);\n\n const result: Uint8Array[][] = groupsShares.map((group) => group.map(serializeShare));\n\n return result;\n}\n\n/**\n * Combines the given SSKR shares into a Secret.\n *\n * @param shares - A array of SSKR shares to be combined.\n * @returns The reconstructed Secret.\n * @throws SSKRError if the shares do not meet the necessary quorum of groups\n * and member shares within each group.\n */\nexport function sskrCombine(shares: Uint8Array[]): Secret {\n const sskrShares: SSKRShare[] = [];\n\n for (const share of shares) {\n const sskrShare = deserializeShare(share);\n sskrShares.push(sskrShare);\n }\n\n return combineShares(sskrShares);\n}\n\nfunction serializeShare(share: SSKRShare): Uint8Array {\n // pack the id, group and member data into 5 bytes:\n // 76543210 76543210 76543210\n // 76543210 76543210\n // ----------------====----====----====----\n // identifier: 16\n // group-threshold: 4\n // group-count: 4\n // group-index: 4\n // member-threshold: 4\n // reserved (MUST be zero): 4\n // member-index: 4\n\n const valueData = share.value().getData();\n const result = new Uint8Array(valueData.length + METADATA_SIZE_BYTES);\n\n const id = share.identifier();\n const gt = (share.groupThreshold() - 1) & 0xf;\n const gc = (share.groupCount() - 1) & 0xf;\n const gi = share.groupIndex() & 0xf;\n const mt = (share.memberThreshold() - 1) & 0xf;\n const mi = share.memberIndex() & 0xf;\n\n const id1 = id >> 8;\n const id2 = id & 0xff;\n\n result[0] = id1;\n result[1] = id2;\n result[2] = (gt << 4) | gc;\n result[3] = (gi << 4) | mt;\n result[4] = mi;\n result.set(valueData, METADATA_SIZE_BYTES);\n\n return result;\n}\n\nfunction deserializeShare(source: Uint8Array): SSKRShare {\n if (source.length < METADATA_SIZE_BYTES) {\n throw new SSKRError(SSKRErrorType.ShareLengthInvalid);\n }\n\n const groupThreshold = (source[2] >> 4) + 1;\n const groupCount = (source[2] & 0xf) + 1;\n\n if (groupThreshold > groupCount) {\n throw new SSKRError(SSKRErrorType.GroupThresholdInvalid);\n }\n\n const identifier = (source[0] << 8) | source[1];\n const groupIndex = source[3] >> 4;\n const memberThreshold = (source[3] & 0xf) + 1;\n const reserved = source[4] >> 4;\n if (reserved !== 0) {\n throw new SSKRError(SSKRErrorType.ShareReservedBitsInvalid);\n }\n const memberIndex = source[4] & 0xf;\n const value = Secret.new(source.subarray(METADATA_SIZE_BYTES));\n\n return new SSKRShare(\n identifier,\n groupIndex,\n groupThreshold,\n groupCount,\n memberIndex,\n memberThreshold,\n value,\n );\n}\n\nfunction generateShares(\n spec: Spec,\n masterSecret: Secret,\n randomGenerator: RandomNumberGenerator,\n): SSKRShare[][] {\n // assign a random identifier\n const identifierBytes = new Uint8Array(2);\n randomGenerator.fillRandomData(identifierBytes);\n const identifier = (identifierBytes[0] << 8) | identifierBytes[1];\n\n const groupsShares: SSKRShare[][] = [];\n\n let groupSecrets: Uint8Array[];\n try {\n groupSecrets = splitSecret(\n spec.groupThreshold(),\n spec.groupCount(),\n masterSecret.getData(),\n randomGenerator,\n );\n } catch (e) {\n if (e instanceof ShamirError) {\n throw SSKRError.fromShamirError(e);\n }\n throw e;\n }\n\n for (let groupIndex = 0; groupIndex < spec.groups().length; groupIndex++) {\n const group = spec.groups()[groupIndex];\n const groupSecret = groupSecrets[groupIndex];\n\n let memberSecrets: Uint8Array[];\n try {\n memberSecrets = splitSecret(\n group.memberThreshold(),\n group.memberCount(),\n groupSecret,\n randomGenerator,\n );\n } catch (e) {\n if (e instanceof ShamirError) {\n throw SSKRError.fromShamirError(e);\n }\n throw e;\n }\n\n const memberSSKRShares: SSKRShare[] = memberSecrets.map((memberSecret, memberIndex) => {\n const secret = Secret.new(memberSecret);\n return new SSKRShare(\n identifier,\n groupIndex,\n spec.groupThreshold(),\n spec.groupCount(),\n memberIndex,\n group.memberThreshold(),\n secret,\n );\n });\n\n groupsShares.push(memberSSKRShares);\n }\n\n return groupsShares;\n}\n\ninterface Group {\n groupIndex: number;\n memberThreshold: number;\n memberIndexes: number[];\n memberShares: Secret[];\n}\n\nfunction combineShares(shares: SSKRShare[]): Secret {\n let identifier = 0;\n let groupThreshold = 0;\n let groupCount = 0;\n\n if (shares.length === 0) {\n throw new SSKRError(SSKRErrorType.SharesEmpty);\n }\n\n let nextGroup = 0;\n const groups: Group[] = [];\n let secretLen = 0;\n\n for (let i = 0; i < shares.length; i++) {\n const share = shares[i];\n\n if (i === 0) {\n // on the first one, establish expected values for common metadata\n identifier = share.identifier();\n groupCount = share.groupCount();\n groupThreshold = share.groupThreshold();\n secretLen = share.value().len();\n } else {\n // on subsequent shares, check that common metadata matches\n if (\n share.identifier() !== identifier ||\n share.groupThreshold() !== groupThreshold ||\n share.groupCount() !== groupCount ||\n share.value().len() !== secretLen\n ) {\n throw new SSKRError(SSKRErrorType.ShareSetInvalid);\n }\n }\n\n // sort shares into member groups\n let groupFound = false;\n for (const group of groups) {\n if (share.groupIndex() === group.groupIndex) {\n groupFound = true;\n if (share.memberThreshold() !== group.memberThreshold) {\n throw new SSKRError(SSKRErrorType.MemberThresholdInvalid);\n }\n for (const memberIndex of group.memberIndexes) {\n if (share.memberIndex() === memberIndex) {\n throw new SSKRError(SSKRErrorType.DuplicateMemberIndex);\n }\n }\n if (group.memberIndexes.length < group.memberThreshold) {\n group.memberIndexes.push(share.memberIndex());\n group.memberShares.push(share.value().clone());\n }\n }\n }\n\n if (!groupFound) {\n const g: Group = {\n groupIndex: share.groupIndex(),\n memberThreshold: share.memberThreshold(),\n memberIndexes: [share.memberIndex()],\n memberShares: [share.value().clone()],\n };\n groups.push(g);\n nextGroup++;\n }\n }\n\n // Check that we have enough groups to recover the master secret\n if (nextGroup < groupThreshold) {\n throw new SSKRError(SSKRErrorType.NotEnoughGroups);\n }\n\n // Here, all of the shares are unpacked into member groups. Now we go\n // through each group and recover the group secret, and then use the\n // result to recover the master secret\n const masterIndexes: number[] = [];\n const masterShares: Uint8Array[] = [];\n\n for (const group of groups) {\n // Only attempt to recover the group secret if we have enough shares\n if (group.memberIndexes.length < group.memberThreshold) {\n continue;\n }\n\n // Recover the group secret\n try {\n const memberSharesData = group.memberShares.map((s) => s.getData());\n const groupSecret = recoverSecret(group.memberIndexes, memberSharesData);\n masterIndexes.push(group.groupIndex);\n masterShares.push(groupSecret);\n } catch {\n // If we can't recover this group, just skip it\n continue;\n }\n\n // Stop if we have enough groups to recover the master secret\n if (masterIndexes.length === groupThreshold) {\n break;\n }\n }\n\n // If we don't have enough groups to recover the master secret, return an error\n if (masterIndexes.length < groupThreshold) {\n throw new SSKRError(SSKRErrorType.NotEnoughGroups);\n }\n\n // Recover the master secret\n let masterSecretData: Uint8Array;\n try {\n masterSecretData = recoverSecret(masterIndexes, masterShares);\n } catch (e) {\n if (e instanceof ShamirError) {\n throw SSKRError.fromShamirError(e);\n }\n throw e;\n }\n\n return Secret.new(masterSecretData);\n}\n","// Blockchain Commons Sharded Secret Key Reconstruction (SSKR)\n// Ported from bc-sskr-rust\n//\n// Sharded Secret Key Reconstruction (SSKR) is a protocol for splitting a\n// secret into a set of shares across one or more groups, such that the\n// secret can be reconstructed from any combination of shares totaling or\n// exceeding a threshold number of shares within each group and across all\n// groups. SSKR is a generalization of Shamir's Secret Sharing (SSS) that\n// allows for multiple groups and multiple thresholds.\n\nimport {\n MIN_SECRET_LEN as SHAMIR_MIN_SECRET_LEN,\n MAX_SECRET_LEN as SHAMIR_MAX_SECRET_LEN,\n MAX_SHARE_COUNT as SHAMIR_MAX_SHARE_COUNT,\n} from \"@bcts/shamir\";\n\n/**\n * The minimum length of a secret.\n */\nexport const MIN_SECRET_LEN = SHAMIR_MIN_SECRET_LEN;\n\n/**\n * The maximum length of a secret.\n */\nexport const MAX_SECRET_LEN = SHAMIR_MAX_SECRET_LEN;\n\n/**\n * The maximum number of shares that can be generated from a secret.\n */\nexport const MAX_SHARE_COUNT = SHAMIR_MAX_SHARE_COUNT;\n\n/**\n * The maximum number of groups in a split.\n */\nexport const MAX_GROUPS_COUNT = MAX_SHARE_COUNT;\n\n/**\n * The number of bytes used to encode the metadata for a share.\n */\nexport const METADATA_SIZE_BYTES = 5;\n\n/**\n * The minimum number of bytes required to encode a share.\n */\nexport const MIN_SERIALIZE_SIZE_BYTES = METADATA_SIZE_BYTES + MIN_SECRET_LEN;\n\n// Error types\nexport { SSKRError, SSKRErrorType, type SSKRResult } from \"./error.js\";\n\n// Secret\nexport { Secret } from \"./secret.js\";\n\n// Specifications\nexport { GroupSpec, Spec } from \"./spec.js\";\n\n// Share\nexport { SSKRShare } from \"./share.js\";\n\n// Encoding/Decoding\nexport { sskrGenerate, sskrGenerateUsing, sskrCombine } from \"./encoding.js\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.iife.js","names":["MAX_SHARE_COUNT","SecureRandomNumberGenerator","ShamirError","SHAMIR_MIN_SECRET_LEN","SHAMIR_MAX_SECRET_LEN","SHAMIR_MAX_SHARE_COUNT"],"sources":["../src/error.ts","../src/secret.ts","../src/spec.ts","../src/share.ts","../src/encoding.ts","../src/index.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-sskr-rust/src/error.rs\n\nimport type { ShamirError } from \"@bcts/shamir\";\n\n/**\n * Error types for SSKR operations.\n */\nexport enum SSKRErrorType {\n DuplicateMemberIndex = \"DuplicateMemberIndex\",\n GroupSpecInvalid = \"GroupSpecInvalid\",\n GroupCountInvalid = \"GroupCountInvalid\",\n GroupThresholdInvalid = \"GroupThresholdInvalid\",\n MemberCountInvalid = \"MemberCountInvalid\",\n MemberThresholdInvalid = \"MemberThresholdInvalid\",\n NotEnoughGroups = \"NotEnoughGroups\",\n SecretLengthNotEven = \"SecretLengthNotEven\",\n SecretTooLong = \"SecretTooLong\",\n SecretTooShort = \"SecretTooShort\",\n ShareLengthInvalid = \"ShareLengthInvalid\",\n ShareReservedBitsInvalid = \"ShareReservedBitsInvalid\",\n SharesEmpty = \"SharesEmpty\",\n ShareSetInvalid = \"ShareSetInvalid\",\n ShamirError = \"ShamirError\",\n}\n\n/**\n * Error class for SSKR operations.\n */\nexport class SSKRError extends Error {\n readonly type: SSKRErrorType;\n readonly shamirError?: ShamirError | undefined;\n\n constructor(type: SSKRErrorType, message?: string, shamirError?: ShamirError) {\n super(message ?? SSKRError.defaultMessage(type, shamirError));\n this.type = type;\n this.shamirError = shamirError;\n this.name = \"SSKRError\";\n }\n\n private static defaultMessage(type: SSKRErrorType, shamirError?: ShamirError): string {\n switch (type) {\n case SSKRErrorType.DuplicateMemberIndex:\n return \"When combining shares, the provided shares contained a duplicate member index\";\n case SSKRErrorType.GroupSpecInvalid:\n return \"Invalid group specification.\";\n case SSKRErrorType.GroupCountInvalid:\n return \"When creating a split spec, the group count is invalid\";\n case SSKRErrorType.GroupThresholdInvalid:\n return \"SSKR group threshold is invalid\";\n case SSKRErrorType.MemberCountInvalid:\n return \"SSKR member count is invalid\";\n case SSKRErrorType.MemberThresholdInvalid:\n return \"SSKR member threshold is invalid\";\n case SSKRErrorType.NotEnoughGroups:\n return \"SSKR shares did not contain enough groups\";\n case SSKRErrorType.SecretLengthNotEven:\n return \"SSKR secret is not of even length\";\n case SSKRErrorType.SecretTooLong:\n return \"SSKR secret is too long\";\n case SSKRErrorType.SecretTooShort:\n return \"SSKR secret is too short\";\n case SSKRErrorType.ShareLengthInvalid:\n return \"SSKR shares did not contain enough serialized bytes\";\n case SSKRErrorType.ShareReservedBitsInvalid:\n return \"SSKR shares contained invalid reserved bits\";\n case SSKRErrorType.SharesEmpty:\n return \"SSKR shares were empty\";\n case SSKRErrorType.ShareSetInvalid:\n return \"SSKR shares were invalid\";\n case SSKRErrorType.ShamirError:\n return shamirError != null\n ? `SSKR Shamir error: ${shamirError.message}`\n : \"SSKR Shamir error\";\n }\n }\n\n static fromShamirError(error: ShamirError): SSKRError {\n return new SSKRError(SSKRErrorType.ShamirError, undefined, error);\n }\n}\n\n/**\n * Mirrors Rust's `Result<T, Error>` (`bc-sskr-rust/src/error.rs:54`).\n *\n * The TypeScript port surfaces failures by throwing {@link SSKRError}\n * rather than returning a sum type, so this alias is a no-op\n * (`SSKRResult<T>` ≡ `T`). It is kept so signatures published in\n * `@bcts/sskr` remain visually parallel to their Rust counterparts.\n */\nexport type SSKRResult<T> = T;\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-sskr-rust/src/secret.rs\n\nimport { MIN_SECRET_LEN, MAX_SECRET_LEN } from \"./index.js\";\nimport { SSKRError, SSKRErrorType } from \"./error.js\";\n\n/**\n * A secret to be split into shares.\n */\nexport class Secret {\n private readonly data: Uint8Array;\n\n private constructor(data: Uint8Array) {\n this.data = data;\n }\n\n /**\n * Creates a new Secret instance with the given data.\n *\n * @param data - The secret data to be split into shares.\n * @returns A new Secret instance.\n * @throws SSKRError if the length of the secret is less than\n * MIN_SECRET_LEN, greater than MAX_SECRET_LEN, or not even.\n */\n static new(data: Uint8Array | string): Secret {\n const bytes = typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n const len = bytes.length;\n\n if (len < MIN_SECRET_LEN) {\n throw new SSKRError(SSKRErrorType.SecretTooShort);\n }\n if (len > MAX_SECRET_LEN) {\n throw new SSKRError(SSKRErrorType.SecretTooLong);\n }\n if ((len & 1) !== 0) {\n throw new SSKRError(SSKRErrorType.SecretLengthNotEven);\n }\n\n return new Secret(new Uint8Array(bytes));\n }\n\n /**\n * Returns the length of the secret.\n */\n len(): number {\n return this.data.length;\n }\n\n /**\n * Returns true if the secret is empty.\n */\n isEmpty(): boolean {\n return this.len() === 0;\n }\n\n /**\n * Returns a reference to the secret data.\n *\n * Mirrors Rust's `Secret::data(&self) -> &[u8]`\n * (`bc-sskr-rust/src/secret.rs:43`).\n */\n getData(): Uint8Array {\n return this.data;\n }\n\n /**\n * Returns the secret data as a Uint8Array.\n *\n * Mirrors Rust's `impl AsRef<[u8]> for Secret`\n * (`bc-sskr-rust/src/secret.rs:46-49`). In Rust, `as_ref()` is\n * provided via the `AsRef<[u8]>` trait, which lets the `Secret` flow\n * naturally through any API expecting `impl AsRef<[u8]>`. TypeScript\n * has no equivalent of that trait, so we expose the same backing\n * buffer through both {@link getData} (the field accessor) and\n * `asRef` (the trait-style accessor) for ergonomic parity. Callers\n * may pick whichever name reads better at the call site.\n */\n asRef(): Uint8Array {\n return this.data;\n }\n\n /**\n * Check equality with another Secret.\n */\n equals(other: Secret): boolean {\n if (this.data.length !== other.data.length) {\n return false;\n }\n for (let i = 0; i < this.data.length; i++) {\n if (this.data[i] !== other.data[i]) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Clone the secret.\n */\n clone(): Secret {\n return new Secret(new Uint8Array(this.data));\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-sskr-rust/src/spec.rs\n\nimport { MAX_SHARE_COUNT } from \"@bcts/shamir\";\nimport { SSKRError, SSKRErrorType } from \"./error.js\";\n\n/**\n * Strictly parses a non-negative integer string the way Rust's\n * `<usize as FromStr>::from_str` does (`bc-sskr-rust/src/spec.rs:102, 108`).\n *\n * Accepts an optional leading `+` followed by one or more decimal digits.\n * Rejects whitespace, decimals (`\"2.5\"`), trailing characters (`\"2x\"`),\n * the `-` sign, and the empty string. Returns `undefined` on rejection so\n * callers surface the appropriate `GroupSpecInvalid` error in the same\n * spot Rust's `?` would.\n */\nconst STRICT_USIZE_RE = /^\\+?\\d+$/;\nfunction parseStrictUsize(s: string): number | undefined {\n if (!STRICT_USIZE_RE.test(s)) return undefined;\n const n = Number(s);\n // `Number.isSafeInteger` rejects values outside ±2^53; usize on\n // 64-bit Rust covers a larger range but for SSKR's `member_count`\n // (capped at 16) this is far beyond any meaningful input.\n return Number.isSafeInteger(n) ? n : undefined;\n}\n\n/**\n * A specification for a group of shares within an SSKR split.\n */\nexport class GroupSpec {\n private readonly _memberThreshold: number;\n private readonly _memberCount: number;\n\n private constructor(memberThreshold: number, memberCount: number) {\n this._memberThreshold = memberThreshold;\n this._memberCount = memberCount;\n }\n\n /**\n * Creates a new GroupSpec instance with the given member threshold and count.\n *\n * @param memberThreshold - The minimum number of member shares required to\n * reconstruct the secret within the group.\n * @param memberCount - The total number of member shares in the group.\n * @returns A new GroupSpec instance.\n * @throws SSKRError if the member count is zero, if the member count is\n * greater than the maximum share count, or if the member threshold is\n * greater than the member count.\n */\n static new(memberThreshold: number, memberCount: number): GroupSpec {\n if (memberCount === 0) {\n throw new SSKRError(SSKRErrorType.MemberCountInvalid);\n }\n if (memberCount > MAX_SHARE_COUNT) {\n throw new SSKRError(SSKRErrorType.MemberCountInvalid);\n }\n if (memberThreshold > memberCount) {\n throw new SSKRError(SSKRErrorType.MemberThresholdInvalid);\n }\n return new GroupSpec(memberThreshold, memberCount);\n }\n\n /**\n * Returns the member share threshold for this group.\n */\n memberThreshold(): number {\n return this._memberThreshold;\n }\n\n /**\n * Returns the number of member shares in this group.\n */\n memberCount(): number {\n return this._memberCount;\n }\n\n /**\n * Parses a group specification from a string.\n * Format: `\"M-of-N\"` where `M` is the threshold and `N` is the count.\n *\n * Mirrors Rust's `GroupSpec::parse` (`bc-sskr-rust/src/spec.rs:97-112`),\n * which calls `parts[0].parse::<usize>()`. Rust's `usize::FromStr` is\n * strict: it rejects whitespace, decimals, trailing characters, and the\n * `-` sign, accepting only an optional `+` prefix followed by digits.\n * We mirror that with the regex `^\\+?\\d+$` so strings like `\"2.5\"`,\n * `\"2x\"`, `\" 2\"`, `\"-2\"`, and `\"\"` all surface\n * {@link SSKRErrorType.GroupSpecInvalid} on both sides.\n */\n static parse(s: string): GroupSpec {\n const parts = s.split(\"-\");\n if (parts.length !== 3) {\n throw new SSKRError(SSKRErrorType.GroupSpecInvalid);\n }\n\n const memberThreshold = parseStrictUsize(parts[0]);\n if (memberThreshold === undefined) {\n throw new SSKRError(SSKRErrorType.GroupSpecInvalid);\n }\n\n if (parts[1] !== \"of\") {\n throw new SSKRError(SSKRErrorType.GroupSpecInvalid);\n }\n\n const memberCount = parseStrictUsize(parts[2]);\n if (memberCount === undefined) {\n throw new SSKRError(SSKRErrorType.GroupSpecInvalid);\n }\n\n return GroupSpec.new(memberThreshold, memberCount);\n }\n\n /**\n * Creates a default GroupSpec (1-of-1).\n */\n static default(): GroupSpec {\n return GroupSpec.new(1, 1);\n }\n\n /**\n * Returns a string representation of the group spec.\n */\n toString(): string {\n return `${this._memberThreshold}-of-${this._memberCount}`;\n }\n}\n\n/**\n * A specification for an SSKR split.\n */\nexport class Spec {\n private readonly _groupThreshold: number;\n private readonly _groups: GroupSpec[];\n\n private constructor(groupThreshold: number, groups: GroupSpec[]) {\n this._groupThreshold = groupThreshold;\n this._groups = groups;\n }\n\n /**\n * Creates a new Spec instance with the given group threshold and groups.\n *\n * @param groupThreshold - The minimum number of groups required to\n * reconstruct the secret.\n * @param groups - The list of GroupSpec instances that define the groups\n * and their members.\n * @returns A new Spec instance.\n * @throws SSKRError if the group threshold is zero, if the group threshold\n * is greater than the number of groups, or if the number of groups is\n * greater than the maximum share count.\n */\n static new(groupThreshold: number, groups: GroupSpec[]): Spec {\n if (groupThreshold === 0) {\n throw new SSKRError(SSKRErrorType.GroupThresholdInvalid);\n }\n if (groupThreshold > groups.length) {\n throw new SSKRError(SSKRErrorType.GroupThresholdInvalid);\n }\n if (groups.length > MAX_SHARE_COUNT) {\n throw new SSKRError(SSKRErrorType.GroupCountInvalid);\n }\n return new Spec(groupThreshold, groups);\n }\n\n /**\n * Returns the group threshold.\n */\n groupThreshold(): number {\n return this._groupThreshold;\n }\n\n /**\n * Returns a slice of the group specifications.\n */\n groups(): GroupSpec[] {\n return this._groups;\n }\n\n /**\n * Returns the number of groups.\n */\n groupCount(): number {\n return this._groups.length;\n }\n\n /**\n * Returns the total number of shares across all groups.\n */\n shareCount(): number {\n return this._groups.reduce((sum, g) => sum + g.memberCount(), 0);\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-sskr-rust/src/share.rs\n\nimport type { Secret } from \"./secret.js\";\n\n/**\n * A share in the SSKR scheme.\n */\nexport class SSKRShare {\n private readonly _identifier: number;\n private readonly _groupIndex: number;\n private readonly _groupThreshold: number;\n private readonly _groupCount: number;\n private readonly _memberIndex: number;\n private readonly _memberThreshold: number;\n private readonly _value: Secret;\n\n constructor(\n identifier: number,\n groupIndex: number,\n groupThreshold: number,\n groupCount: number,\n memberIndex: number,\n memberThreshold: number,\n value: Secret,\n ) {\n this._identifier = identifier;\n this._groupIndex = groupIndex;\n this._groupThreshold = groupThreshold;\n this._groupCount = groupCount;\n this._memberIndex = memberIndex;\n this._memberThreshold = memberThreshold;\n this._value = value;\n }\n\n identifier(): number {\n return this._identifier;\n }\n\n groupIndex(): number {\n return this._groupIndex;\n }\n\n groupThreshold(): number {\n return this._groupThreshold;\n }\n\n groupCount(): number {\n return this._groupCount;\n }\n\n memberIndex(): number {\n return this._memberIndex;\n }\n\n memberThreshold(): number {\n return this._memberThreshold;\n }\n\n value(): Secret {\n return this._value;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-sskr-rust/src/encoding.rs\n\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { SecureRandomNumberGenerator } from \"@bcts/rand\";\nimport { splitSecret, recoverSecret, ShamirError } from \"@bcts/shamir\";\n\nimport { SSKRError, SSKRErrorType } from \"./error.js\";\nimport { Secret } from \"./secret.js\";\nimport type { Spec } from \"./spec.js\";\nimport { SSKRShare } from \"./share.js\";\nimport { METADATA_SIZE_BYTES } from \"./index.js\";\n\n/**\n * Generates SSKR shares for the given Spec and Secret.\n *\n * @param spec - The Spec instance that defines the group and member thresholds.\n * @param masterSecret - The Secret instance to be split into shares.\n * @returns A vector of groups, each containing a vector of shares,\n * each of which is a Uint8Array.\n */\nexport function sskrGenerate(spec: Spec, masterSecret: Secret): Uint8Array[][] {\n const rng = new SecureRandomNumberGenerator();\n return sskrGenerateUsing(spec, masterSecret, rng);\n}\n\n/**\n * Generates SSKR shares for the given Spec and Secret using the provided\n * random number generator.\n *\n * @param spec - The Spec instance that defines the group and member thresholds.\n * @param masterSecret - The Secret instance to be split into shares.\n * @param randomGenerator - The random number generator to use for generating\n * shares.\n * @returns A vector of groups, each containing a vector of shares,\n * each of which is a Uint8Array.\n */\nexport function sskrGenerateUsing(\n spec: Spec,\n masterSecret: Secret,\n randomGenerator: RandomNumberGenerator,\n): Uint8Array[][] {\n const groupsShares = generateShares(spec, masterSecret, randomGenerator);\n\n const result: Uint8Array[][] = groupsShares.map((group) => group.map(serializeShare));\n\n return result;\n}\n\n/**\n * Combines the given SSKR shares into a Secret.\n *\n * @param shares - A array of SSKR shares to be combined.\n * @returns The reconstructed Secret.\n * @throws SSKRError if the shares do not meet the necessary quorum of groups\n * and member shares within each group.\n */\nexport function sskrCombine(shares: Uint8Array[]): Secret {\n const sskrShares: SSKRShare[] = [];\n\n for (const share of shares) {\n const sskrShare = deserializeShare(share);\n sskrShares.push(sskrShare);\n }\n\n return combineShares(sskrShares);\n}\n\nfunction serializeShare(share: SSKRShare): Uint8Array {\n // pack the id, group and member data into 5 bytes:\n // 76543210 76543210 76543210\n // 76543210 76543210\n // ----------------====----====----====----\n // identifier: 16\n // group-threshold: 4\n // group-count: 4\n // group-index: 4\n // member-threshold: 4\n // reserved (MUST be zero): 4\n // member-index: 4\n\n const valueData = share.value().getData();\n const result = new Uint8Array(valueData.length + METADATA_SIZE_BYTES);\n\n const id = share.identifier();\n const gt = (share.groupThreshold() - 1) & 0xf;\n const gc = (share.groupCount() - 1) & 0xf;\n const gi = share.groupIndex() & 0xf;\n const mt = (share.memberThreshold() - 1) & 0xf;\n const mi = share.memberIndex() & 0xf;\n\n const id1 = id >> 8;\n const id2 = id & 0xff;\n\n result[0] = id1;\n result[1] = id2;\n result[2] = (gt << 4) | gc;\n result[3] = (gi << 4) | mt;\n result[4] = mi;\n result.set(valueData, METADATA_SIZE_BYTES);\n\n return result;\n}\n\nfunction deserializeShare(source: Uint8Array): SSKRShare {\n if (source.length < METADATA_SIZE_BYTES) {\n throw new SSKRError(SSKRErrorType.ShareLengthInvalid);\n }\n\n const groupThreshold = (source[2] >> 4) + 1;\n const groupCount = (source[2] & 0xf) + 1;\n\n if (groupThreshold > groupCount) {\n throw new SSKRError(SSKRErrorType.GroupThresholdInvalid);\n }\n\n const identifier = (source[0] << 8) | source[1];\n const groupIndex = source[3] >> 4;\n const memberThreshold = (source[3] & 0xf) + 1;\n const reserved = source[4] >> 4;\n if (reserved !== 0) {\n throw new SSKRError(SSKRErrorType.ShareReservedBitsInvalid);\n }\n const memberIndex = source[4] & 0xf;\n const value = Secret.new(source.subarray(METADATA_SIZE_BYTES));\n\n return new SSKRShare(\n identifier,\n groupIndex,\n groupThreshold,\n groupCount,\n memberIndex,\n memberThreshold,\n value,\n );\n}\n\nfunction generateShares(\n spec: Spec,\n masterSecret: Secret,\n randomGenerator: RandomNumberGenerator,\n): SSKRShare[][] {\n // assign a random identifier\n const identifierBytes = new Uint8Array(2);\n randomGenerator.fillRandomData(identifierBytes);\n const identifier = (identifierBytes[0] << 8) | identifierBytes[1];\n\n const groupsShares: SSKRShare[][] = [];\n\n let groupSecrets: Uint8Array[];\n try {\n groupSecrets = splitSecret(\n spec.groupThreshold(),\n spec.groupCount(),\n masterSecret.getData(),\n randomGenerator,\n );\n } catch (e) {\n if (e instanceof ShamirError) {\n throw SSKRError.fromShamirError(e);\n }\n throw e;\n }\n\n for (let groupIndex = 0; groupIndex < spec.groups().length; groupIndex++) {\n const group = spec.groups()[groupIndex];\n const groupSecret = groupSecrets[groupIndex];\n\n let memberSecrets: Uint8Array[];\n try {\n memberSecrets = splitSecret(\n group.memberThreshold(),\n group.memberCount(),\n groupSecret,\n randomGenerator,\n );\n } catch (e) {\n if (e instanceof ShamirError) {\n throw SSKRError.fromShamirError(e);\n }\n throw e;\n }\n\n const memberSSKRShares: SSKRShare[] = memberSecrets.map((memberSecret, memberIndex) => {\n const secret = Secret.new(memberSecret);\n return new SSKRShare(\n identifier,\n groupIndex,\n spec.groupThreshold(),\n spec.groupCount(),\n memberIndex,\n group.memberThreshold(),\n secret,\n );\n });\n\n groupsShares.push(memberSSKRShares);\n }\n\n return groupsShares;\n}\n\ninterface Group {\n groupIndex: number;\n memberThreshold: number;\n memberIndexes: number[];\n memberShares: Secret[];\n}\n\nfunction combineShares(shares: SSKRShare[]): Secret {\n let identifier = 0;\n let groupThreshold = 0;\n let groupCount = 0;\n\n if (shares.length === 0) {\n throw new SSKRError(SSKRErrorType.SharesEmpty);\n }\n\n let nextGroup = 0;\n const groups: Group[] = [];\n let secretLen = 0;\n\n for (let i = 0; i < shares.length; i++) {\n const share = shares[i];\n\n if (i === 0) {\n // on the first one, establish expected values for common metadata\n identifier = share.identifier();\n groupCount = share.groupCount();\n groupThreshold = share.groupThreshold();\n secretLen = share.value().len();\n } else {\n // on subsequent shares, check that common metadata matches\n if (\n share.identifier() !== identifier ||\n share.groupThreshold() !== groupThreshold ||\n share.groupCount() !== groupCount ||\n share.value().len() !== secretLen\n ) {\n throw new SSKRError(SSKRErrorType.ShareSetInvalid);\n }\n }\n\n // sort shares into member groups\n let groupFound = false;\n for (const group of groups) {\n if (share.groupIndex() === group.groupIndex) {\n groupFound = true;\n if (share.memberThreshold() !== group.memberThreshold) {\n throw new SSKRError(SSKRErrorType.MemberThresholdInvalid);\n }\n for (const memberIndex of group.memberIndexes) {\n if (share.memberIndex() === memberIndex) {\n throw new SSKRError(SSKRErrorType.DuplicateMemberIndex);\n }\n }\n if (group.memberIndexes.length < group.memberThreshold) {\n group.memberIndexes.push(share.memberIndex());\n group.memberShares.push(share.value().clone());\n }\n }\n }\n\n if (!groupFound) {\n const g: Group = {\n groupIndex: share.groupIndex(),\n memberThreshold: share.memberThreshold(),\n memberIndexes: [share.memberIndex()],\n memberShares: [share.value().clone()],\n };\n groups.push(g);\n nextGroup++;\n }\n }\n\n // Check that we have enough groups to recover the master secret\n if (nextGroup < groupThreshold) {\n throw new SSKRError(SSKRErrorType.NotEnoughGroups);\n }\n\n // Here, all of the shares are unpacked into member groups. Now we go\n // through each group and recover the group secret, and then use the\n // result to recover the master secret\n const masterIndexes: number[] = [];\n const masterShares: Uint8Array[] = [];\n\n for (const group of groups) {\n // Only attempt to recover the group secret if we have enough shares\n if (group.memberIndexes.length < group.memberThreshold) {\n continue;\n }\n\n // Recover the group secret. Mirrors Rust's `if let Ok(group_secret)\n // = recover_secret(...)` (`bc-sskr-rust/src/encoding.rs:289-294`):\n // we silently skip groups whose Shamir recovery fails (the\n // seedtool-cli #6 fix), but **rethrow any non-Shamir error** so\n // unexpected exceptions don't get swallowed — Rust's match-by-Result\n // already enforces that distinction at the type level.\n try {\n const memberSharesData = group.memberShares.map((s) => s.getData());\n const groupSecret = recoverSecret(group.memberIndexes, memberSharesData);\n masterIndexes.push(group.groupIndex);\n masterShares.push(groupSecret);\n } catch (e) {\n if (e instanceof ShamirError) {\n // Equivalent to Rust's \"Err arm\" of `if let Ok` — the seedtool\n // #6 fix demands we keep iterating to other groups.\n continue;\n }\n throw e;\n }\n\n // Stop if we have enough groups to recover the master secret\n if (masterIndexes.length === groupThreshold) {\n break;\n }\n }\n\n // If we don't have enough groups to recover the master secret, return an error\n if (masterIndexes.length < groupThreshold) {\n throw new SSKRError(SSKRErrorType.NotEnoughGroups);\n }\n\n // Recover the master secret\n let masterSecretData: Uint8Array;\n try {\n masterSecretData = recoverSecret(masterIndexes, masterShares);\n } catch (e) {\n if (e instanceof ShamirError) {\n throw SSKRError.fromShamirError(e);\n }\n throw e;\n }\n\n return Secret.new(masterSecretData);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Blockchain Commons Sharded Secret Key Reconstruction (SSKR)\n// Ported from bc-sskr-rust\n//\n// Sharded Secret Key Reconstruction (SSKR) is a protocol for splitting a\n// secret into a set of shares across one or more groups, such that the\n// secret can be reconstructed from any combination of shares totaling or\n// exceeding a threshold number of shares within each group and across all\n// groups. SSKR is a generalization of Shamir's Secret Sharing (SSS) that\n// allows for multiple groups and multiple thresholds.\n\nimport {\n MIN_SECRET_LEN as SHAMIR_MIN_SECRET_LEN,\n MAX_SECRET_LEN as SHAMIR_MAX_SECRET_LEN,\n MAX_SHARE_COUNT as SHAMIR_MAX_SHARE_COUNT,\n} from \"@bcts/shamir\";\n\n/**\n * The minimum length of a secret.\n */\nexport const MIN_SECRET_LEN = SHAMIR_MIN_SECRET_LEN;\n\n/**\n * The maximum length of a secret.\n */\nexport const MAX_SECRET_LEN = SHAMIR_MAX_SECRET_LEN;\n\n/**\n * The maximum number of shares that can be generated from a secret.\n */\nexport const MAX_SHARE_COUNT = SHAMIR_MAX_SHARE_COUNT;\n\n/**\n * The maximum number of groups in a split.\n */\nexport const MAX_GROUPS_COUNT = MAX_SHARE_COUNT;\n\n/**\n * The number of bytes used to encode the metadata for a share.\n */\nexport const METADATA_SIZE_BYTES = 5;\n\n/**\n * The minimum number of bytes required to encode a share.\n */\nexport const MIN_SERIALIZE_SIZE_BYTES = METADATA_SIZE_BYTES + MIN_SECRET_LEN;\n\n// Error types\nexport { SSKRError, SSKRErrorType, type SSKRResult } from \"./error.js\";\n\n// Secret\nexport { Secret } from \"./secret.js\";\n\n// Specifications\nexport { GroupSpec, Spec } from \"./spec.js\";\n\n// Encoding/Decoding\nexport { sskrGenerate, sskrGenerateUsing, sskrCombine } from \"./encoding.js\";\n"],"mappings":"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"}