@bcts/sskr 1.0.0-alpha.10

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/src/spec.ts ADDED
@@ -0,0 +1,162 @@
1
+ // Ported from bc-sskr-rust/src/spec.rs
2
+
3
+ import { MAX_SHARE_COUNT } from "@bcts/shamir";
4
+ import { SSKRError, SSKRErrorType } from "./error.js";
5
+
6
+ /**
7
+ * A specification for a group of shares within an SSKR split.
8
+ */
9
+ export class GroupSpec {
10
+ private readonly _memberThreshold: number;
11
+ private readonly _memberCount: number;
12
+
13
+ private constructor(memberThreshold: number, memberCount: number) {
14
+ this._memberThreshold = memberThreshold;
15
+ this._memberCount = memberCount;
16
+ }
17
+
18
+ /**
19
+ * Creates a new GroupSpec instance with the given member threshold and count.
20
+ *
21
+ * @param memberThreshold - The minimum number of member shares required to
22
+ * reconstruct the secret within the group.
23
+ * @param memberCount - The total number of member shares in the group.
24
+ * @returns A new GroupSpec instance.
25
+ * @throws SSKRError if the member count is zero, if the member count is
26
+ * greater than the maximum share count, or if the member threshold is
27
+ * greater than the member count.
28
+ */
29
+ static new(memberThreshold: number, memberCount: number): GroupSpec {
30
+ if (memberCount === 0) {
31
+ throw new SSKRError(SSKRErrorType.MemberCountInvalid);
32
+ }
33
+ if (memberCount > MAX_SHARE_COUNT) {
34
+ throw new SSKRError(SSKRErrorType.MemberCountInvalid);
35
+ }
36
+ if (memberThreshold > memberCount) {
37
+ throw new SSKRError(SSKRErrorType.MemberThresholdInvalid);
38
+ }
39
+ return new GroupSpec(memberThreshold, memberCount);
40
+ }
41
+
42
+ /**
43
+ * Returns the member share threshold for this group.
44
+ */
45
+ memberThreshold(): number {
46
+ return this._memberThreshold;
47
+ }
48
+
49
+ /**
50
+ * Returns the number of member shares in this group.
51
+ */
52
+ memberCount(): number {
53
+ return this._memberCount;
54
+ }
55
+
56
+ /**
57
+ * Parses a group specification from a string.
58
+ * Format: "M-of-N" where M is the threshold and N is the count.
59
+ */
60
+ static parse(s: string): GroupSpec {
61
+ const parts = s.split("-");
62
+ if (parts.length !== 3) {
63
+ throw new SSKRError(SSKRErrorType.GroupSpecInvalid);
64
+ }
65
+
66
+ const memberThreshold = parseInt(parts[0], 10);
67
+ if (isNaN(memberThreshold)) {
68
+ throw new SSKRError(SSKRErrorType.GroupSpecInvalid);
69
+ }
70
+
71
+ if (parts[1] !== "of") {
72
+ throw new SSKRError(SSKRErrorType.GroupSpecInvalid);
73
+ }
74
+
75
+ const memberCount = parseInt(parts[2], 10);
76
+ if (isNaN(memberCount)) {
77
+ throw new SSKRError(SSKRErrorType.GroupSpecInvalid);
78
+ }
79
+
80
+ return GroupSpec.new(memberThreshold, memberCount);
81
+ }
82
+
83
+ /**
84
+ * Creates a default GroupSpec (1-of-1).
85
+ */
86
+ static default(): GroupSpec {
87
+ return GroupSpec.new(1, 1);
88
+ }
89
+
90
+ /**
91
+ * Returns a string representation of the group spec.
92
+ */
93
+ toString(): string {
94
+ return `${this._memberThreshold}-of-${this._memberCount}`;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * A specification for an SSKR split.
100
+ */
101
+ export class Spec {
102
+ private readonly _groupThreshold: number;
103
+ private readonly _groups: GroupSpec[];
104
+
105
+ private constructor(groupThreshold: number, groups: GroupSpec[]) {
106
+ this._groupThreshold = groupThreshold;
107
+ this._groups = groups;
108
+ }
109
+
110
+ /**
111
+ * Creates a new Spec instance with the given group threshold and groups.
112
+ *
113
+ * @param groupThreshold - The minimum number of groups required to
114
+ * reconstruct the secret.
115
+ * @param groups - The list of GroupSpec instances that define the groups
116
+ * and their members.
117
+ * @returns A new Spec instance.
118
+ * @throws SSKRError if the group threshold is zero, if the group threshold
119
+ * is greater than the number of groups, or if the number of groups is
120
+ * greater than the maximum share count.
121
+ */
122
+ static new(groupThreshold: number, groups: GroupSpec[]): Spec {
123
+ if (groupThreshold === 0) {
124
+ throw new SSKRError(SSKRErrorType.GroupThresholdInvalid);
125
+ }
126
+ if (groupThreshold > groups.length) {
127
+ throw new SSKRError(SSKRErrorType.GroupThresholdInvalid);
128
+ }
129
+ if (groups.length > MAX_SHARE_COUNT) {
130
+ throw new SSKRError(SSKRErrorType.GroupCountInvalid);
131
+ }
132
+ return new Spec(groupThreshold, groups);
133
+ }
134
+
135
+ /**
136
+ * Returns the group threshold.
137
+ */
138
+ groupThreshold(): number {
139
+ return this._groupThreshold;
140
+ }
141
+
142
+ /**
143
+ * Returns a slice of the group specifications.
144
+ */
145
+ groups(): GroupSpec[] {
146
+ return this._groups;
147
+ }
148
+
149
+ /**
150
+ * Returns the number of groups.
151
+ */
152
+ groupCount(): number {
153
+ return this._groups.length;
154
+ }
155
+
156
+ /**
157
+ * Returns the total number of shares across all groups.
158
+ */
159
+ shareCount(): number {
160
+ return this._groups.reduce((sum, g) => sum + g.memberCount(), 0);
161
+ }
162
+ }