@bcts/sskr 1.0.0-alpha.22 → 1.0.0-alpha.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +44 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.iife.js +77 -84
- package/dist/index.iife.js.map +1 -1
- package/dist/index.mjs +43 -49
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value:
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let _bcts_shamir = require("@bcts/shamir");
|
|
3
3
|
let _bcts_rand = require("@bcts/rand");
|
|
4
|
-
|
|
5
4
|
//#region src/error.ts
|
|
6
5
|
/**
|
|
7
6
|
* Error types for SSKR operations.
|
|
@@ -38,28 +37,27 @@ var SSKRError = class SSKRError extends Error {
|
|
|
38
37
|
}
|
|
39
38
|
static defaultMessage(type, shamirError) {
|
|
40
39
|
switch (type) {
|
|
41
|
-
case
|
|
42
|
-
case
|
|
43
|
-
case
|
|
44
|
-
case
|
|
45
|
-
case
|
|
46
|
-
case
|
|
47
|
-
case
|
|
48
|
-
case
|
|
49
|
-
case
|
|
50
|
-
case
|
|
51
|
-
case
|
|
52
|
-
case
|
|
53
|
-
case
|
|
54
|
-
case
|
|
55
|
-
case
|
|
40
|
+
case "DuplicateMemberIndex": return "When combining shares, the provided shares contained a duplicate member index";
|
|
41
|
+
case "GroupSpecInvalid": return "Invalid group specification.";
|
|
42
|
+
case "GroupCountInvalid": return "When creating a split spec, the group count is invalid";
|
|
43
|
+
case "GroupThresholdInvalid": return "SSKR group threshold is invalid";
|
|
44
|
+
case "MemberCountInvalid": return "SSKR member count is invalid";
|
|
45
|
+
case "MemberThresholdInvalid": return "SSKR member threshold is invalid";
|
|
46
|
+
case "NotEnoughGroups": return "SSKR shares did not contain enough groups";
|
|
47
|
+
case "SecretLengthNotEven": return "SSKR secret is not of even length";
|
|
48
|
+
case "SecretTooLong": return "SSKR secret is too long";
|
|
49
|
+
case "SecretTooShort": return "SSKR secret is too short";
|
|
50
|
+
case "ShareLengthInvalid": return "SSKR shares did not contain enough serialized bytes";
|
|
51
|
+
case "ShareReservedBitsInvalid": return "SSKR shares contained invalid reserved bits";
|
|
52
|
+
case "SharesEmpty": return "SSKR shares were empty";
|
|
53
|
+
case "ShareSetInvalid": return "SSKR shares were invalid";
|
|
54
|
+
case "ShamirError": return shamirError != null ? `SSKR Shamir error: ${shamirError.message}` : "SSKR Shamir error";
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
57
|
static fromShamirError(error) {
|
|
59
|
-
return new SSKRError(
|
|
58
|
+
return new SSKRError("ShamirError", void 0, error);
|
|
60
59
|
}
|
|
61
60
|
};
|
|
62
|
-
|
|
63
61
|
//#endregion
|
|
64
62
|
//#region src/secret.ts
|
|
65
63
|
/**
|
|
@@ -86,9 +84,9 @@ var Secret = class Secret {
|
|
|
86
84
|
static new(data) {
|
|
87
85
|
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
88
86
|
const len = bytes.length;
|
|
89
|
-
if (len < MIN_SECRET_LEN) throw new SSKRError(
|
|
90
|
-
if (len > MAX_SECRET_LEN) throw new SSKRError(
|
|
91
|
-
if ((len & 1) !== 0) throw new SSKRError(
|
|
87
|
+
if (len < MIN_SECRET_LEN) throw new SSKRError("SecretTooShort");
|
|
88
|
+
if (len > MAX_SECRET_LEN) throw new SSKRError("SecretTooLong");
|
|
89
|
+
if ((len & 1) !== 0) throw new SSKRError("SecretLengthNotEven");
|
|
92
90
|
return new Secret(new Uint8Array(bytes));
|
|
93
91
|
}
|
|
94
92
|
/**
|
|
@@ -130,7 +128,6 @@ var Secret = class Secret {
|
|
|
130
128
|
return new Secret(new Uint8Array(this.data));
|
|
131
129
|
}
|
|
132
130
|
};
|
|
133
|
-
|
|
134
131
|
//#endregion
|
|
135
132
|
//#region src/spec.ts
|
|
136
133
|
/**
|
|
@@ -160,9 +157,9 @@ var GroupSpec = class GroupSpec {
|
|
|
160
157
|
* greater than the member count.
|
|
161
158
|
*/
|
|
162
159
|
static new(memberThreshold, memberCount) {
|
|
163
|
-
if (memberCount === 0) throw new SSKRError(
|
|
164
|
-
if (memberCount > _bcts_shamir.MAX_SHARE_COUNT) throw new SSKRError(
|
|
165
|
-
if (memberThreshold > memberCount) throw new SSKRError(
|
|
160
|
+
if (memberCount === 0) throw new SSKRError("MemberCountInvalid");
|
|
161
|
+
if (memberCount > _bcts_shamir.MAX_SHARE_COUNT) throw new SSKRError("MemberCountInvalid");
|
|
162
|
+
if (memberThreshold > memberCount) throw new SSKRError("MemberThresholdInvalid");
|
|
166
163
|
return new GroupSpec(memberThreshold, memberCount);
|
|
167
164
|
}
|
|
168
165
|
/**
|
|
@@ -183,12 +180,12 @@ var GroupSpec = class GroupSpec {
|
|
|
183
180
|
*/
|
|
184
181
|
static parse(s) {
|
|
185
182
|
const parts = s.split("-");
|
|
186
|
-
if (parts.length !== 3) throw new SSKRError(
|
|
183
|
+
if (parts.length !== 3) throw new SSKRError("GroupSpecInvalid");
|
|
187
184
|
const memberThreshold = parseInt(parts[0], 10);
|
|
188
|
-
if (isNaN(memberThreshold)) throw new SSKRError(
|
|
189
|
-
if (parts[1] !== "of") throw new SSKRError(
|
|
185
|
+
if (isNaN(memberThreshold)) throw new SSKRError("GroupSpecInvalid");
|
|
186
|
+
if (parts[1] !== "of") throw new SSKRError("GroupSpecInvalid");
|
|
190
187
|
const memberCount = parseInt(parts[2], 10);
|
|
191
|
-
if (isNaN(memberCount)) throw new SSKRError(
|
|
188
|
+
if (isNaN(memberCount)) throw new SSKRError("GroupSpecInvalid");
|
|
192
189
|
return GroupSpec.new(memberThreshold, memberCount);
|
|
193
190
|
}
|
|
194
191
|
/**
|
|
@@ -227,9 +224,9 @@ var Spec = class Spec {
|
|
|
227
224
|
* greater than the maximum share count.
|
|
228
225
|
*/
|
|
229
226
|
static new(groupThreshold, groups) {
|
|
230
|
-
if (groupThreshold === 0) throw new SSKRError(
|
|
231
|
-
if (groupThreshold > groups.length) throw new SSKRError(
|
|
232
|
-
if (groups.length > _bcts_shamir.MAX_SHARE_COUNT) throw new SSKRError(
|
|
227
|
+
if (groupThreshold === 0) throw new SSKRError("GroupThresholdInvalid");
|
|
228
|
+
if (groupThreshold > groups.length) throw new SSKRError("GroupThresholdInvalid");
|
|
229
|
+
if (groups.length > _bcts_shamir.MAX_SHARE_COUNT) throw new SSKRError("GroupCountInvalid");
|
|
233
230
|
return new Spec(groupThreshold, groups);
|
|
234
231
|
}
|
|
235
232
|
/**
|
|
@@ -257,7 +254,6 @@ var Spec = class Spec {
|
|
|
257
254
|
return this._groups.reduce((sum, g) => sum + g.memberCount(), 0);
|
|
258
255
|
}
|
|
259
256
|
};
|
|
260
|
-
|
|
261
257
|
//#endregion
|
|
262
258
|
//#region src/share.ts
|
|
263
259
|
/**
|
|
@@ -302,7 +298,6 @@ var SSKRShare = class {
|
|
|
302
298
|
return this._value;
|
|
303
299
|
}
|
|
304
300
|
};
|
|
305
|
-
|
|
306
301
|
//#endregion
|
|
307
302
|
//#region src/encoding.ts
|
|
308
303
|
/**
|
|
@@ -348,7 +343,7 @@ function sskrCombine(shares) {
|
|
|
348
343
|
}
|
|
349
344
|
function serializeShare(share) {
|
|
350
345
|
const valueData = share.value().getData();
|
|
351
|
-
const result = new Uint8Array(valueData.length +
|
|
346
|
+
const result = new Uint8Array(valueData.length + 5);
|
|
352
347
|
const id = share.identifier();
|
|
353
348
|
const gt = share.groupThreshold() - 1 & 15;
|
|
354
349
|
const gc = share.groupCount() - 1 & 15;
|
|
@@ -362,19 +357,19 @@ function serializeShare(share) {
|
|
|
362
357
|
result[2] = gt << 4 | gc;
|
|
363
358
|
result[3] = gi << 4 | mt;
|
|
364
359
|
result[4] = mi;
|
|
365
|
-
result.set(valueData,
|
|
360
|
+
result.set(valueData, 5);
|
|
366
361
|
return result;
|
|
367
362
|
}
|
|
368
363
|
function deserializeShare(source) {
|
|
369
|
-
if (source.length <
|
|
364
|
+
if (source.length < 5) throw new SSKRError("ShareLengthInvalid");
|
|
370
365
|
const groupThreshold = (source[2] >> 4) + 1;
|
|
371
366
|
const groupCount = (source[2] & 15) + 1;
|
|
372
|
-
if (groupThreshold > groupCount) throw new SSKRError(
|
|
367
|
+
if (groupThreshold > groupCount) throw new SSKRError("GroupThresholdInvalid");
|
|
373
368
|
const identifier = source[0] << 8 | source[1];
|
|
374
369
|
const groupIndex = source[3] >> 4;
|
|
375
370
|
const memberThreshold = (source[3] & 15) + 1;
|
|
376
|
-
if (source[4] >> 4 !== 0) throw new SSKRError(
|
|
377
|
-
return new SSKRShare(identifier, groupIndex, groupThreshold, groupCount, source[4] & 15, memberThreshold, Secret.new(source.subarray(
|
|
371
|
+
if (source[4] >> 4 !== 0) throw new SSKRError("ShareReservedBitsInvalid");
|
|
372
|
+
return new SSKRShare(identifier, groupIndex, groupThreshold, groupCount, source[4] & 15, memberThreshold, Secret.new(source.subarray(5)));
|
|
378
373
|
}
|
|
379
374
|
function generateShares(spec, masterSecret, randomGenerator) {
|
|
380
375
|
const identifierBytes = new Uint8Array(2);
|
|
@@ -410,7 +405,7 @@ function combineShares(shares) {
|
|
|
410
405
|
let identifier = 0;
|
|
411
406
|
let groupThreshold = 0;
|
|
412
407
|
let groupCount = 0;
|
|
413
|
-
if (shares.length === 0) throw new SSKRError(
|
|
408
|
+
if (shares.length === 0) throw new SSKRError("SharesEmpty");
|
|
414
409
|
let nextGroup = 0;
|
|
415
410
|
const groups = [];
|
|
416
411
|
let secretLen = 0;
|
|
@@ -421,12 +416,12 @@ function combineShares(shares) {
|
|
|
421
416
|
groupCount = share.groupCount();
|
|
422
417
|
groupThreshold = share.groupThreshold();
|
|
423
418
|
secretLen = share.value().len();
|
|
424
|
-
} else if (share.identifier() !== identifier || share.groupThreshold() !== groupThreshold || share.groupCount() !== groupCount || share.value().len() !== secretLen) throw new SSKRError(
|
|
419
|
+
} else if (share.identifier() !== identifier || share.groupThreshold() !== groupThreshold || share.groupCount() !== groupCount || share.value().len() !== secretLen) throw new SSKRError("ShareSetInvalid");
|
|
425
420
|
let groupFound = false;
|
|
426
421
|
for (const group of groups) if (share.groupIndex() === group.groupIndex) {
|
|
427
422
|
groupFound = true;
|
|
428
|
-
if (share.memberThreshold() !== group.memberThreshold) throw new SSKRError(
|
|
429
|
-
for (const memberIndex of group.memberIndexes) if (share.memberIndex() === memberIndex) throw new SSKRError(
|
|
423
|
+
if (share.memberThreshold() !== group.memberThreshold) throw new SSKRError("MemberThresholdInvalid");
|
|
424
|
+
for (const memberIndex of group.memberIndexes) if (share.memberIndex() === memberIndex) throw new SSKRError("DuplicateMemberIndex");
|
|
430
425
|
if (group.memberIndexes.length < group.memberThreshold) {
|
|
431
426
|
group.memberIndexes.push(share.memberIndex());
|
|
432
427
|
group.memberShares.push(share.value().clone());
|
|
@@ -443,7 +438,7 @@ function combineShares(shares) {
|
|
|
443
438
|
nextGroup++;
|
|
444
439
|
}
|
|
445
440
|
}
|
|
446
|
-
if (nextGroup < groupThreshold) throw new SSKRError(
|
|
441
|
+
if (nextGroup < groupThreshold) throw new SSKRError("NotEnoughGroups");
|
|
447
442
|
const masterIndexes = [];
|
|
448
443
|
const masterShares = [];
|
|
449
444
|
for (const group of groups) {
|
|
@@ -458,7 +453,7 @@ function combineShares(shares) {
|
|
|
458
453
|
}
|
|
459
454
|
if (masterIndexes.length === groupThreshold) break;
|
|
460
455
|
}
|
|
461
|
-
if (masterIndexes.length < groupThreshold) throw new SSKRError(
|
|
456
|
+
if (masterIndexes.length < groupThreshold) throw new SSKRError("NotEnoughGroups");
|
|
462
457
|
let masterSecretData;
|
|
463
458
|
try {
|
|
464
459
|
masterSecretData = (0, _bcts_shamir.recoverSecret)(masterIndexes, masterShares);
|
|
@@ -468,7 +463,6 @@ function combineShares(shares) {
|
|
|
468
463
|
}
|
|
469
464
|
return Secret.new(masterSecretData);
|
|
470
465
|
}
|
|
471
|
-
|
|
472
466
|
//#endregion
|
|
473
467
|
//#region src/index.ts
|
|
474
468
|
/**
|
|
@@ -499,8 +493,7 @@ const METADATA_SIZE_BYTES = 5;
|
|
|
499
493
|
/**
|
|
500
494
|
* The minimum number of bytes required to encode a share.
|
|
501
495
|
*/
|
|
502
|
-
const MIN_SERIALIZE_SIZE_BYTES =
|
|
503
|
-
|
|
496
|
+
const MIN_SERIALIZE_SIZE_BYTES = 5 + MIN_SECRET_LEN;
|
|
504
497
|
//#endregion
|
|
505
498
|
exports.GroupSpec = GroupSpec;
|
|
506
499
|
exports.MAX_GROUPS_COUNT = MAX_GROUPS_COUNT;
|
|
@@ -516,4 +509,5 @@ exports.Spec = Spec;
|
|
|
516
509
|
exports.sskrCombine = sskrCombine;
|
|
517
510
|
exports.sskrGenerate = sskrGenerate;
|
|
518
511
|
exports.sskrGenerateUsing = sskrGenerateUsing;
|
|
512
|
+
|
|
519
513
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","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\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 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","/**\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 * 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","/**\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\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","/**\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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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","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\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 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","/**\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 * 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","/**\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\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","/**\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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"}
|
package/dist/index.iife.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
var bctsSskr = (function(exports, _bcts_shamir, _bcts_rand) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
//#region src/error.ts
|
|
6
|
-
/**
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
//#region src/error.ts
|
|
4
|
+
/**
|
|
7
5
|
* Error types for SSKR operations.
|
|
8
6
|
*/
|
|
9
7
|
let SSKRErrorType = /* @__PURE__ */ function(SSKRErrorType) {
|
|
@@ -38,31 +36,30 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
38
36
|
}
|
|
39
37
|
static defaultMessage(type, shamirError) {
|
|
40
38
|
switch (type) {
|
|
41
|
-
case
|
|
42
|
-
case
|
|
43
|
-
case
|
|
44
|
-
case
|
|
45
|
-
case
|
|
46
|
-
case
|
|
47
|
-
case
|
|
48
|
-
case
|
|
49
|
-
case
|
|
50
|
-
case
|
|
51
|
-
case
|
|
52
|
-
case
|
|
53
|
-
case
|
|
54
|
-
case
|
|
55
|
-
case
|
|
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";
|
|
56
54
|
}
|
|
57
55
|
}
|
|
58
56
|
static fromShamirError(error) {
|
|
59
|
-
return new SSKRError(
|
|
57
|
+
return new SSKRError("ShamirError", void 0, error);
|
|
60
58
|
}
|
|
61
59
|
};
|
|
62
|
-
|
|
63
|
-
//#
|
|
64
|
-
|
|
65
|
-
/**
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/secret.ts
|
|
62
|
+
/**
|
|
66
63
|
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
67
64
|
* Copyright © 2025-2026 Parity Technologies
|
|
68
65
|
*
|
|
@@ -86,9 +83,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
86
83
|
static new(data) {
|
|
87
84
|
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
88
85
|
const len = bytes.length;
|
|
89
|
-
if (len < MIN_SECRET_LEN) throw new SSKRError(
|
|
90
|
-
if (len > MAX_SECRET_LEN) throw new SSKRError(
|
|
91
|
-
if ((len & 1) !== 0) throw new SSKRError(
|
|
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");
|
|
92
89
|
return new Secret(new Uint8Array(bytes));
|
|
93
90
|
}
|
|
94
91
|
/**
|
|
@@ -130,10 +127,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
130
127
|
return new Secret(new Uint8Array(this.data));
|
|
131
128
|
}
|
|
132
129
|
};
|
|
133
|
-
|
|
134
|
-
//#
|
|
135
|
-
|
|
136
|
-
/**
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/spec.ts
|
|
132
|
+
/**
|
|
137
133
|
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
138
134
|
* Copyright © 2025-2026 Parity Technologies
|
|
139
135
|
*
|
|
@@ -160,9 +156,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
160
156
|
* greater than the member count.
|
|
161
157
|
*/
|
|
162
158
|
static new(memberThreshold, memberCount) {
|
|
163
|
-
if (memberCount === 0) throw new SSKRError(
|
|
164
|
-
if (memberCount > _bcts_shamir.MAX_SHARE_COUNT) throw new SSKRError(
|
|
165
|
-
if (memberThreshold > memberCount) throw new SSKRError(
|
|
159
|
+
if (memberCount === 0) throw new SSKRError("MemberCountInvalid");
|
|
160
|
+
if (memberCount > _bcts_shamir.MAX_SHARE_COUNT) throw new SSKRError("MemberCountInvalid");
|
|
161
|
+
if (memberThreshold > memberCount) throw new SSKRError("MemberThresholdInvalid");
|
|
166
162
|
return new GroupSpec(memberThreshold, memberCount);
|
|
167
163
|
}
|
|
168
164
|
/**
|
|
@@ -183,12 +179,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
183
179
|
*/
|
|
184
180
|
static parse(s) {
|
|
185
181
|
const parts = s.split("-");
|
|
186
|
-
if (parts.length !== 3) throw new SSKRError(
|
|
182
|
+
if (parts.length !== 3) throw new SSKRError("GroupSpecInvalid");
|
|
187
183
|
const memberThreshold = parseInt(parts[0], 10);
|
|
188
|
-
if (isNaN(memberThreshold)) throw new SSKRError(
|
|
189
|
-
if (parts[1] !== "of") throw new SSKRError(
|
|
184
|
+
if (isNaN(memberThreshold)) throw new SSKRError("GroupSpecInvalid");
|
|
185
|
+
if (parts[1] !== "of") throw new SSKRError("GroupSpecInvalid");
|
|
190
186
|
const memberCount = parseInt(parts[2], 10);
|
|
191
|
-
if (isNaN(memberCount)) throw new SSKRError(
|
|
187
|
+
if (isNaN(memberCount)) throw new SSKRError("GroupSpecInvalid");
|
|
192
188
|
return GroupSpec.new(memberThreshold, memberCount);
|
|
193
189
|
}
|
|
194
190
|
/**
|
|
@@ -227,9 +223,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
227
223
|
* greater than the maximum share count.
|
|
228
224
|
*/
|
|
229
225
|
static new(groupThreshold, groups) {
|
|
230
|
-
if (groupThreshold === 0) throw new SSKRError(
|
|
231
|
-
if (groupThreshold > groups.length) throw new SSKRError(
|
|
232
|
-
if (groups.length > _bcts_shamir.MAX_SHARE_COUNT) throw new SSKRError(
|
|
226
|
+
if (groupThreshold === 0) throw new SSKRError("GroupThresholdInvalid");
|
|
227
|
+
if (groupThreshold > groups.length) throw new SSKRError("GroupThresholdInvalid");
|
|
228
|
+
if (groups.length > _bcts_shamir.MAX_SHARE_COUNT) throw new SSKRError("GroupCountInvalid");
|
|
233
229
|
return new Spec(groupThreshold, groups);
|
|
234
230
|
}
|
|
235
231
|
/**
|
|
@@ -257,10 +253,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
257
253
|
return this._groups.reduce((sum, g) => sum + g.memberCount(), 0);
|
|
258
254
|
}
|
|
259
255
|
};
|
|
260
|
-
|
|
261
|
-
//#
|
|
262
|
-
|
|
263
|
-
/**
|
|
256
|
+
//#endregion
|
|
257
|
+
//#region src/share.ts
|
|
258
|
+
/**
|
|
264
259
|
* A share in the SSKR scheme.
|
|
265
260
|
*/
|
|
266
261
|
var SSKRShare = class {
|
|
@@ -302,10 +297,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
302
297
|
return this._value;
|
|
303
298
|
}
|
|
304
299
|
};
|
|
305
|
-
|
|
306
|
-
//#
|
|
307
|
-
|
|
308
|
-
/**
|
|
300
|
+
//#endregion
|
|
301
|
+
//#region src/encoding.ts
|
|
302
|
+
/**
|
|
309
303
|
* Generates SSKR shares for the given Spec and Secret.
|
|
310
304
|
*
|
|
311
305
|
* @param spec - The Spec instance that defines the group and member thresholds.
|
|
@@ -348,7 +342,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
348
342
|
}
|
|
349
343
|
function serializeShare(share) {
|
|
350
344
|
const valueData = share.value().getData();
|
|
351
|
-
const result = new Uint8Array(valueData.length +
|
|
345
|
+
const result = new Uint8Array(valueData.length + 5);
|
|
352
346
|
const id = share.identifier();
|
|
353
347
|
const gt = share.groupThreshold() - 1 & 15;
|
|
354
348
|
const gc = share.groupCount() - 1 & 15;
|
|
@@ -362,19 +356,19 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
362
356
|
result[2] = gt << 4 | gc;
|
|
363
357
|
result[3] = gi << 4 | mt;
|
|
364
358
|
result[4] = mi;
|
|
365
|
-
result.set(valueData,
|
|
359
|
+
result.set(valueData, 5);
|
|
366
360
|
return result;
|
|
367
361
|
}
|
|
368
362
|
function deserializeShare(source) {
|
|
369
|
-
if (source.length <
|
|
363
|
+
if (source.length < 5) throw new SSKRError("ShareLengthInvalid");
|
|
370
364
|
const groupThreshold = (source[2] >> 4) + 1;
|
|
371
365
|
const groupCount = (source[2] & 15) + 1;
|
|
372
|
-
if (groupThreshold > groupCount) throw new SSKRError(
|
|
366
|
+
if (groupThreshold > groupCount) throw new SSKRError("GroupThresholdInvalid");
|
|
373
367
|
const identifier = source[0] << 8 | source[1];
|
|
374
368
|
const groupIndex = source[3] >> 4;
|
|
375
369
|
const memberThreshold = (source[3] & 15) + 1;
|
|
376
|
-
if (source[4] >> 4 !== 0) throw new SSKRError(
|
|
377
|
-
return new SSKRShare(identifier, groupIndex, groupThreshold, groupCount, source[4] & 15, memberThreshold, Secret.new(source.subarray(
|
|
370
|
+
if (source[4] >> 4 !== 0) throw new SSKRError("ShareReservedBitsInvalid");
|
|
371
|
+
return new SSKRShare(identifier, groupIndex, groupThreshold, groupCount, source[4] & 15, memberThreshold, Secret.new(source.subarray(5)));
|
|
378
372
|
}
|
|
379
373
|
function generateShares(spec, masterSecret, randomGenerator) {
|
|
380
374
|
const identifierBytes = new Uint8Array(2);
|
|
@@ -410,7 +404,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
410
404
|
let identifier = 0;
|
|
411
405
|
let groupThreshold = 0;
|
|
412
406
|
let groupCount = 0;
|
|
413
|
-
if (shares.length === 0) throw new SSKRError(
|
|
407
|
+
if (shares.length === 0) throw new SSKRError("SharesEmpty");
|
|
414
408
|
let nextGroup = 0;
|
|
415
409
|
const groups = [];
|
|
416
410
|
let secretLen = 0;
|
|
@@ -421,12 +415,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
421
415
|
groupCount = share.groupCount();
|
|
422
416
|
groupThreshold = share.groupThreshold();
|
|
423
417
|
secretLen = share.value().len();
|
|
424
|
-
} else if (share.identifier() !== identifier || share.groupThreshold() !== groupThreshold || share.groupCount() !== groupCount || share.value().len() !== secretLen) throw new SSKRError(
|
|
418
|
+
} else if (share.identifier() !== identifier || share.groupThreshold() !== groupThreshold || share.groupCount() !== groupCount || share.value().len() !== secretLen) throw new SSKRError("ShareSetInvalid");
|
|
425
419
|
let groupFound = false;
|
|
426
420
|
for (const group of groups) if (share.groupIndex() === group.groupIndex) {
|
|
427
421
|
groupFound = true;
|
|
428
|
-
if (share.memberThreshold() !== group.memberThreshold) throw new SSKRError(
|
|
429
|
-
for (const memberIndex of group.memberIndexes) if (share.memberIndex() === memberIndex) throw new SSKRError(
|
|
422
|
+
if (share.memberThreshold() !== group.memberThreshold) throw new SSKRError("MemberThresholdInvalid");
|
|
423
|
+
for (const memberIndex of group.memberIndexes) if (share.memberIndex() === memberIndex) throw new SSKRError("DuplicateMemberIndex");
|
|
430
424
|
if (group.memberIndexes.length < group.memberThreshold) {
|
|
431
425
|
group.memberIndexes.push(share.memberIndex());
|
|
432
426
|
group.memberShares.push(share.value().clone());
|
|
@@ -443,7 +437,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
443
437
|
nextGroup++;
|
|
444
438
|
}
|
|
445
439
|
}
|
|
446
|
-
if (nextGroup < groupThreshold) throw new SSKRError(
|
|
440
|
+
if (nextGroup < groupThreshold) throw new SSKRError("NotEnoughGroups");
|
|
447
441
|
const masterIndexes = [];
|
|
448
442
|
const masterShares = [];
|
|
449
443
|
for (const group of groups) {
|
|
@@ -458,7 +452,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
458
452
|
}
|
|
459
453
|
if (masterIndexes.length === groupThreshold) break;
|
|
460
454
|
}
|
|
461
|
-
if (masterIndexes.length < groupThreshold) throw new SSKRError(
|
|
455
|
+
if (masterIndexes.length < groupThreshold) throw new SSKRError("NotEnoughGroups");
|
|
462
456
|
let masterSecretData;
|
|
463
457
|
try {
|
|
464
458
|
masterSecretData = (0, _bcts_shamir.recoverSecret)(masterIndexes, masterShares);
|
|
@@ -468,10 +462,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
468
462
|
}
|
|
469
463
|
return Secret.new(masterSecretData);
|
|
470
464
|
}
|
|
471
|
-
|
|
472
|
-
//#
|
|
473
|
-
|
|
474
|
-
/**
|
|
465
|
+
//#endregion
|
|
466
|
+
//#region src/index.ts
|
|
467
|
+
/**
|
|
475
468
|
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
476
469
|
* Copyright © 2025-2026 Parity Technologies
|
|
477
470
|
*
|
|
@@ -499,23 +492,23 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
499
492
|
/**
|
|
500
493
|
* The minimum number of bytes required to encode a share.
|
|
501
494
|
*/
|
|
502
|
-
const MIN_SERIALIZE_SIZE_BYTES =
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
exports.
|
|
506
|
-
exports.
|
|
507
|
-
exports.
|
|
508
|
-
exports.
|
|
509
|
-
exports.
|
|
510
|
-
exports.
|
|
511
|
-
exports.
|
|
512
|
-
exports.
|
|
513
|
-
exports.
|
|
514
|
-
exports.
|
|
515
|
-
exports.
|
|
516
|
-
exports.
|
|
517
|
-
exports.
|
|
518
|
-
exports
|
|
519
|
-
return exports;
|
|
495
|
+
const MIN_SERIALIZE_SIZE_BYTES = 5 + MIN_SECRET_LEN;
|
|
496
|
+
//#endregion
|
|
497
|
+
exports.GroupSpec = GroupSpec;
|
|
498
|
+
exports.MAX_GROUPS_COUNT = MAX_GROUPS_COUNT;
|
|
499
|
+
exports.MAX_SECRET_LEN = MAX_SECRET_LEN;
|
|
500
|
+
exports.MAX_SHARE_COUNT = MAX_SHARE_COUNT;
|
|
501
|
+
exports.METADATA_SIZE_BYTES = METADATA_SIZE_BYTES;
|
|
502
|
+
exports.MIN_SECRET_LEN = MIN_SECRET_LEN;
|
|
503
|
+
exports.MIN_SERIALIZE_SIZE_BYTES = MIN_SERIALIZE_SIZE_BYTES;
|
|
504
|
+
exports.SSKRError = SSKRError;
|
|
505
|
+
exports.SSKRErrorType = SSKRErrorType;
|
|
506
|
+
exports.Secret = Secret;
|
|
507
|
+
exports.Spec = Spec;
|
|
508
|
+
exports.sskrCombine = sskrCombine;
|
|
509
|
+
exports.sskrGenerate = sskrGenerate;
|
|
510
|
+
exports.sskrGenerateUsing = sskrGenerateUsing;
|
|
511
|
+
return exports;
|
|
520
512
|
})({}, bctsShamir, bctsRand);
|
|
513
|
+
|
|
521
514
|
//# sourceMappingURL=index.iife.js.map
|
package/dist/index.iife.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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\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 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","/**\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 * 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","/**\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\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","/**\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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"}
|
|
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\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 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","/**\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 * 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","/**\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\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","/**\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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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { MAX_SECRET_LEN as MAX_SECRET_LEN$1, MAX_SHARE_COUNT as MAX_SHARE_COUNT$1, MIN_SECRET_LEN as MIN_SECRET_LEN$1, ShamirError, recoverSecret, splitSecret } from "@bcts/shamir";
|
|
2
2
|
import { SecureRandomNumberGenerator } from "@bcts/rand";
|
|
3
|
-
|
|
4
3
|
//#region src/error.ts
|
|
5
4
|
/**
|
|
6
5
|
* Error types for SSKR operations.
|
|
@@ -37,28 +36,27 @@ var SSKRError = class SSKRError extends Error {
|
|
|
37
36
|
}
|
|
38
37
|
static defaultMessage(type, shamirError) {
|
|
39
38
|
switch (type) {
|
|
40
|
-
case
|
|
41
|
-
case
|
|
42
|
-
case
|
|
43
|
-
case
|
|
44
|
-
case
|
|
45
|
-
case
|
|
46
|
-
case
|
|
47
|
-
case
|
|
48
|
-
case
|
|
49
|
-
case
|
|
50
|
-
case
|
|
51
|
-
case
|
|
52
|
-
case
|
|
53
|
-
case
|
|
54
|
-
case
|
|
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(
|
|
57
|
+
return new SSKRError("ShamirError", void 0, error);
|
|
59
58
|
}
|
|
60
59
|
};
|
|
61
|
-
|
|
62
60
|
//#endregion
|
|
63
61
|
//#region src/secret.ts
|
|
64
62
|
/**
|
|
@@ -85,9 +83,9 @@ var Secret = class Secret {
|
|
|
85
83
|
static new(data) {
|
|
86
84
|
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
87
85
|
const len = bytes.length;
|
|
88
|
-
if (len < MIN_SECRET_LEN) throw new SSKRError(
|
|
89
|
-
if (len > MAX_SECRET_LEN) throw new SSKRError(
|
|
90
|
-
if ((len & 1) !== 0) throw new SSKRError(
|
|
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");
|
|
91
89
|
return new Secret(new Uint8Array(bytes));
|
|
92
90
|
}
|
|
93
91
|
/**
|
|
@@ -129,7 +127,6 @@ var Secret = class Secret {
|
|
|
129
127
|
return new Secret(new Uint8Array(this.data));
|
|
130
128
|
}
|
|
131
129
|
};
|
|
132
|
-
|
|
133
130
|
//#endregion
|
|
134
131
|
//#region src/spec.ts
|
|
135
132
|
/**
|
|
@@ -159,9 +156,9 @@ var GroupSpec = class GroupSpec {
|
|
|
159
156
|
* greater than the member count.
|
|
160
157
|
*/
|
|
161
158
|
static new(memberThreshold, memberCount) {
|
|
162
|
-
if (memberCount === 0) throw new SSKRError(
|
|
163
|
-
if (memberCount > MAX_SHARE_COUNT$1) throw new SSKRError(
|
|
164
|
-
if (memberThreshold > memberCount) throw new SSKRError(
|
|
159
|
+
if (memberCount === 0) throw new SSKRError("MemberCountInvalid");
|
|
160
|
+
if (memberCount > MAX_SHARE_COUNT$1) throw new SSKRError("MemberCountInvalid");
|
|
161
|
+
if (memberThreshold > memberCount) throw new SSKRError("MemberThresholdInvalid");
|
|
165
162
|
return new GroupSpec(memberThreshold, memberCount);
|
|
166
163
|
}
|
|
167
164
|
/**
|
|
@@ -182,12 +179,12 @@ var GroupSpec = class GroupSpec {
|
|
|
182
179
|
*/
|
|
183
180
|
static parse(s) {
|
|
184
181
|
const parts = s.split("-");
|
|
185
|
-
if (parts.length !== 3) throw new SSKRError(
|
|
182
|
+
if (parts.length !== 3) throw new SSKRError("GroupSpecInvalid");
|
|
186
183
|
const memberThreshold = parseInt(parts[0], 10);
|
|
187
|
-
if (isNaN(memberThreshold)) throw new SSKRError(
|
|
188
|
-
if (parts[1] !== "of") throw new SSKRError(
|
|
184
|
+
if (isNaN(memberThreshold)) throw new SSKRError("GroupSpecInvalid");
|
|
185
|
+
if (parts[1] !== "of") throw new SSKRError("GroupSpecInvalid");
|
|
189
186
|
const memberCount = parseInt(parts[2], 10);
|
|
190
|
-
if (isNaN(memberCount)) throw new SSKRError(
|
|
187
|
+
if (isNaN(memberCount)) throw new SSKRError("GroupSpecInvalid");
|
|
191
188
|
return GroupSpec.new(memberThreshold, memberCount);
|
|
192
189
|
}
|
|
193
190
|
/**
|
|
@@ -226,9 +223,9 @@ var Spec = class Spec {
|
|
|
226
223
|
* greater than the maximum share count.
|
|
227
224
|
*/
|
|
228
225
|
static new(groupThreshold, groups) {
|
|
229
|
-
if (groupThreshold === 0) throw new SSKRError(
|
|
230
|
-
if (groupThreshold > groups.length) throw new SSKRError(
|
|
231
|
-
if (groups.length > MAX_SHARE_COUNT$1) throw new SSKRError(
|
|
226
|
+
if (groupThreshold === 0) throw new SSKRError("GroupThresholdInvalid");
|
|
227
|
+
if (groupThreshold > groups.length) throw new SSKRError("GroupThresholdInvalid");
|
|
228
|
+
if (groups.length > MAX_SHARE_COUNT$1) throw new SSKRError("GroupCountInvalid");
|
|
232
229
|
return new Spec(groupThreshold, groups);
|
|
233
230
|
}
|
|
234
231
|
/**
|
|
@@ -256,7 +253,6 @@ var Spec = class Spec {
|
|
|
256
253
|
return this._groups.reduce((sum, g) => sum + g.memberCount(), 0);
|
|
257
254
|
}
|
|
258
255
|
};
|
|
259
|
-
|
|
260
256
|
//#endregion
|
|
261
257
|
//#region src/share.ts
|
|
262
258
|
/**
|
|
@@ -301,7 +297,6 @@ var SSKRShare = class {
|
|
|
301
297
|
return this._value;
|
|
302
298
|
}
|
|
303
299
|
};
|
|
304
|
-
|
|
305
300
|
//#endregion
|
|
306
301
|
//#region src/encoding.ts
|
|
307
302
|
/**
|
|
@@ -347,7 +342,7 @@ function sskrCombine(shares) {
|
|
|
347
342
|
}
|
|
348
343
|
function serializeShare(share) {
|
|
349
344
|
const valueData = share.value().getData();
|
|
350
|
-
const result = new Uint8Array(valueData.length +
|
|
345
|
+
const result = new Uint8Array(valueData.length + 5);
|
|
351
346
|
const id = share.identifier();
|
|
352
347
|
const gt = share.groupThreshold() - 1 & 15;
|
|
353
348
|
const gc = share.groupCount() - 1 & 15;
|
|
@@ -361,19 +356,19 @@ function serializeShare(share) {
|
|
|
361
356
|
result[2] = gt << 4 | gc;
|
|
362
357
|
result[3] = gi << 4 | mt;
|
|
363
358
|
result[4] = mi;
|
|
364
|
-
result.set(valueData,
|
|
359
|
+
result.set(valueData, 5);
|
|
365
360
|
return result;
|
|
366
361
|
}
|
|
367
362
|
function deserializeShare(source) {
|
|
368
|
-
if (source.length <
|
|
363
|
+
if (source.length < 5) throw new SSKRError("ShareLengthInvalid");
|
|
369
364
|
const groupThreshold = (source[2] >> 4) + 1;
|
|
370
365
|
const groupCount = (source[2] & 15) + 1;
|
|
371
|
-
if (groupThreshold > groupCount) throw new SSKRError(
|
|
366
|
+
if (groupThreshold > groupCount) throw new SSKRError("GroupThresholdInvalid");
|
|
372
367
|
const identifier = source[0] << 8 | source[1];
|
|
373
368
|
const groupIndex = source[3] >> 4;
|
|
374
369
|
const memberThreshold = (source[3] & 15) + 1;
|
|
375
|
-
if (source[4] >> 4 !== 0) throw new SSKRError(
|
|
376
|
-
return new SSKRShare(identifier, groupIndex, groupThreshold, groupCount, source[4] & 15, memberThreshold, Secret.new(source.subarray(
|
|
370
|
+
if (source[4] >> 4 !== 0) throw new SSKRError("ShareReservedBitsInvalid");
|
|
371
|
+
return new SSKRShare(identifier, groupIndex, groupThreshold, groupCount, source[4] & 15, memberThreshold, Secret.new(source.subarray(5)));
|
|
377
372
|
}
|
|
378
373
|
function generateShares(spec, masterSecret, randomGenerator) {
|
|
379
374
|
const identifierBytes = new Uint8Array(2);
|
|
@@ -409,7 +404,7 @@ function combineShares(shares) {
|
|
|
409
404
|
let identifier = 0;
|
|
410
405
|
let groupThreshold = 0;
|
|
411
406
|
let groupCount = 0;
|
|
412
|
-
if (shares.length === 0) throw new SSKRError(
|
|
407
|
+
if (shares.length === 0) throw new SSKRError("SharesEmpty");
|
|
413
408
|
let nextGroup = 0;
|
|
414
409
|
const groups = [];
|
|
415
410
|
let secretLen = 0;
|
|
@@ -420,12 +415,12 @@ function combineShares(shares) {
|
|
|
420
415
|
groupCount = share.groupCount();
|
|
421
416
|
groupThreshold = share.groupThreshold();
|
|
422
417
|
secretLen = share.value().len();
|
|
423
|
-
} else if (share.identifier() !== identifier || share.groupThreshold() !== groupThreshold || share.groupCount() !== groupCount || share.value().len() !== secretLen) throw new SSKRError(
|
|
418
|
+
} else if (share.identifier() !== identifier || share.groupThreshold() !== groupThreshold || share.groupCount() !== groupCount || share.value().len() !== secretLen) throw new SSKRError("ShareSetInvalid");
|
|
424
419
|
let groupFound = false;
|
|
425
420
|
for (const group of groups) if (share.groupIndex() === group.groupIndex) {
|
|
426
421
|
groupFound = true;
|
|
427
|
-
if (share.memberThreshold() !== group.memberThreshold) throw new SSKRError(
|
|
428
|
-
for (const memberIndex of group.memberIndexes) if (share.memberIndex() === memberIndex) throw new SSKRError(
|
|
422
|
+
if (share.memberThreshold() !== group.memberThreshold) throw new SSKRError("MemberThresholdInvalid");
|
|
423
|
+
for (const memberIndex of group.memberIndexes) if (share.memberIndex() === memberIndex) throw new SSKRError("DuplicateMemberIndex");
|
|
429
424
|
if (group.memberIndexes.length < group.memberThreshold) {
|
|
430
425
|
group.memberIndexes.push(share.memberIndex());
|
|
431
426
|
group.memberShares.push(share.value().clone());
|
|
@@ -442,7 +437,7 @@ function combineShares(shares) {
|
|
|
442
437
|
nextGroup++;
|
|
443
438
|
}
|
|
444
439
|
}
|
|
445
|
-
if (nextGroup < groupThreshold) throw new SSKRError(
|
|
440
|
+
if (nextGroup < groupThreshold) throw new SSKRError("NotEnoughGroups");
|
|
446
441
|
const masterIndexes = [];
|
|
447
442
|
const masterShares = [];
|
|
448
443
|
for (const group of groups) {
|
|
@@ -457,7 +452,7 @@ function combineShares(shares) {
|
|
|
457
452
|
}
|
|
458
453
|
if (masterIndexes.length === groupThreshold) break;
|
|
459
454
|
}
|
|
460
|
-
if (masterIndexes.length < groupThreshold) throw new SSKRError(
|
|
455
|
+
if (masterIndexes.length < groupThreshold) throw new SSKRError("NotEnoughGroups");
|
|
461
456
|
let masterSecretData;
|
|
462
457
|
try {
|
|
463
458
|
masterSecretData = recoverSecret(masterIndexes, masterShares);
|
|
@@ -467,7 +462,6 @@ function combineShares(shares) {
|
|
|
467
462
|
}
|
|
468
463
|
return Secret.new(masterSecretData);
|
|
469
464
|
}
|
|
470
|
-
|
|
471
465
|
//#endregion
|
|
472
466
|
//#region src/index.ts
|
|
473
467
|
/**
|
|
@@ -498,8 +492,8 @@ const METADATA_SIZE_BYTES = 5;
|
|
|
498
492
|
/**
|
|
499
493
|
* The minimum number of bytes required to encode a share.
|
|
500
494
|
*/
|
|
501
|
-
const MIN_SERIALIZE_SIZE_BYTES =
|
|
502
|
-
|
|
495
|
+
const MIN_SERIALIZE_SIZE_BYTES = 5 + MIN_SECRET_LEN;
|
|
503
496
|
//#endregion
|
|
504
497
|
export { GroupSpec, MAX_GROUPS_COUNT, MAX_SECRET_LEN, MAX_SHARE_COUNT, METADATA_SIZE_BYTES, MIN_SECRET_LEN, MIN_SERIALIZE_SIZE_BYTES, SSKRError, SSKRErrorType, Secret, Spec, sskrCombine, sskrGenerate, sskrGenerateUsing };
|
|
498
|
+
|
|
505
499
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["MAX_SHARE_COUNT","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\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 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","/**\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 * 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","/**\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\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","/**\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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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["MAX_SHARE_COUNT","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\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 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","/**\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 * 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","/**\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\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","/**\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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bcts/sskr",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.23",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Blockchain Commons Sharded Secret Key Reconstruction (SSKR) for TypeScript",
|
|
6
6
|
"license": "BSD-2-Clause-Patent",
|
|
@@ -56,19 +56,19 @@
|
|
|
56
56
|
"node": ">=18.0.0"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@bcts/rand": "^1.0.0-alpha.
|
|
60
|
-
"@bcts/shamir": "^1.0.0-alpha.
|
|
59
|
+
"@bcts/rand": "^1.0.0-alpha.23",
|
|
60
|
+
"@bcts/shamir": "^1.0.0-alpha.23"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@bcts/eslint": "^0.1.0",
|
|
64
64
|
"@bcts/tsconfig": "^0.1.0",
|
|
65
65
|
"@eslint/js": "^10.0.1",
|
|
66
|
-
"@types/node": "^25.
|
|
67
|
-
"eslint": "^10.
|
|
66
|
+
"@types/node": "^25.6.0",
|
|
67
|
+
"eslint": "^10.2.1",
|
|
68
68
|
"ts-node": "^10.9.2",
|
|
69
|
-
"tsdown": "^0.
|
|
70
|
-
"typedoc": "^0.28.
|
|
71
|
-
"typescript": "^
|
|
72
|
-
"vitest": "^4.
|
|
69
|
+
"tsdown": "^0.21.0",
|
|
70
|
+
"typedoc": "^0.28.19",
|
|
71
|
+
"typescript": "^6.0.3",
|
|
72
|
+
"vitest": "^4.1.5"
|
|
73
73
|
}
|
|
74
74
|
}
|