@bcts/sskr 1.0.0-alpha.8 → 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/error.ts CHANGED
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Copyright © 2023-2026 Blockchain Commons, LLC
3
+ * Copyright © 2025-2026 Parity Technologies
4
+ *
5
+ */
6
+
1
7
  // Ported from bc-sskr-rust/src/error.rs
2
8
 
3
9
  import type { ShamirError } from "@bcts/shamir";
@@ -42,7 +48,7 @@ export class SSKRError extends Error {
42
48
  case SSKRErrorType.DuplicateMemberIndex:
43
49
  return "When combining shares, the provided shares contained a duplicate member index";
44
50
  case SSKRErrorType.GroupSpecInvalid:
45
- return "Invalid group specification";
51
+ return "Invalid group specification.";
46
52
  case SSKRErrorType.GroupCountInvalid:
47
53
  return "When creating a split spec, the group count is invalid";
48
54
  case SSKRErrorType.GroupThresholdInvalid:
@@ -79,4 +85,12 @@ export class SSKRError extends Error {
79
85
  }
80
86
  }
81
87
 
88
+ /**
89
+ * Mirrors Rust's `Result<T, Error>` (`bc-sskr-rust/src/error.rs:54`).
90
+ *
91
+ * The TypeScript port surfaces failures by throwing {@link SSKRError}
92
+ * rather than returning a sum type, so this alias is a no-op
93
+ * (`SSKRResult<T>` ≡ `T`). It is kept so signatures published in
94
+ * `@bcts/sskr` remain visually parallel to their Rust counterparts.
95
+ */
82
96
  export type SSKRResult<T> = T;
package/src/index.ts CHANGED
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Copyright © 2023-2026 Blockchain Commons, LLC
3
+ * Copyright © 2025-2026 Parity Technologies
4
+ *
5
+ */
6
+
1
7
  // Blockchain Commons Sharded Secret Key Reconstruction (SSKR)
2
8
  // Ported from bc-sskr-rust
3
9
  //
@@ -53,8 +59,5 @@ export { Secret } from "./secret.js";
53
59
  // Specifications
54
60
  export { GroupSpec, Spec } from "./spec.js";
55
61
 
56
- // Share
57
- export { SSKRShare } from "./share.js";
58
-
59
62
  // Encoding/Decoding
60
63
  export { sskrGenerate, sskrGenerateUsing, sskrCombine } from "./encoding.js";
package/src/secret.ts CHANGED
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Copyright © 2023-2026 Blockchain Commons, LLC
3
+ * Copyright © 2025-2026 Parity Technologies
4
+ *
5
+ */
6
+
1
7
  // Ported from bc-sskr-rust/src/secret.rs
2
8
 
3
9
  import { MIN_SECRET_LEN, MAX_SECRET_LEN } from "./index.js";
@@ -54,6 +60,9 @@ export class Secret {
54
60
 
55
61
  /**
56
62
  * Returns a reference to the secret data.
63
+ *
64
+ * Mirrors Rust's `Secret::data(&self) -> &[u8]`
65
+ * (`bc-sskr-rust/src/secret.rs:43`).
57
66
  */
58
67
  getData(): Uint8Array {
59
68
  return this.data;
@@ -61,6 +70,15 @@ export class Secret {
61
70
 
62
71
  /**
63
72
  * Returns the secret data as a Uint8Array.
73
+ *
74
+ * Mirrors Rust's `impl AsRef<[u8]> for Secret`
75
+ * (`bc-sskr-rust/src/secret.rs:46-49`). In Rust, `as_ref()` is
76
+ * provided via the `AsRef<[u8]>` trait, which lets the `Secret` flow
77
+ * naturally through any API expecting `impl AsRef<[u8]>`. TypeScript
78
+ * has no equivalent of that trait, so we expose the same backing
79
+ * buffer through both {@link getData} (the field accessor) and
80
+ * `asRef` (the trait-style accessor) for ergonomic parity. Callers
81
+ * may pick whichever name reads better at the call site.
64
82
  */
65
83
  asRef(): Uint8Array {
66
84
  return this.data;
package/src/share.ts CHANGED
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Copyright © 2023-2026 Blockchain Commons, LLC
3
+ * Copyright © 2025-2026 Parity Technologies
4
+ *
5
+ */
6
+
1
7
  // Ported from bc-sskr-rust/src/share.rs
2
8
 
3
9
  import type { Secret } from "./secret.js";
package/src/spec.ts CHANGED
@@ -1,8 +1,34 @@
1
+ /**
2
+ * Copyright © 2023-2026 Blockchain Commons, LLC
3
+ * Copyright © 2025-2026 Parity Technologies
4
+ *
5
+ */
6
+
1
7
  // Ported from bc-sskr-rust/src/spec.rs
2
8
 
3
9
  import { MAX_SHARE_COUNT } from "@bcts/shamir";
4
10
  import { SSKRError, SSKRErrorType } from "./error.js";
5
11
 
12
+ /**
13
+ * Strictly parses a non-negative integer string the way Rust's
14
+ * `<usize as FromStr>::from_str` does (`bc-sskr-rust/src/spec.rs:102, 108`).
15
+ *
16
+ * Accepts an optional leading `+` followed by one or more decimal digits.
17
+ * Rejects whitespace, decimals (`"2.5"`), trailing characters (`"2x"`),
18
+ * the `-` sign, and the empty string. Returns `undefined` on rejection so
19
+ * callers surface the appropriate `GroupSpecInvalid` error in the same
20
+ * spot Rust's `?` would.
21
+ */
22
+ const STRICT_USIZE_RE = /^\+?\d+$/;
23
+ function parseStrictUsize(s: string): number | undefined {
24
+ if (!STRICT_USIZE_RE.test(s)) return undefined;
25
+ const n = Number(s);
26
+ // `Number.isSafeInteger` rejects values outside ±2^53; usize on
27
+ // 64-bit Rust covers a larger range but for SSKR's `member_count`
28
+ // (capped at 16) this is far beyond any meaningful input.
29
+ return Number.isSafeInteger(n) ? n : undefined;
30
+ }
31
+
6
32
  /**
7
33
  * A specification for a group of shares within an SSKR split.
8
34
  */
@@ -55,7 +81,15 @@ export class GroupSpec {
55
81
 
56
82
  /**
57
83
  * Parses a group specification from a string.
58
- * Format: "M-of-N" where M is the threshold and N is the count.
84
+ * Format: `"M-of-N"` where `M` is the threshold and `N` is the count.
85
+ *
86
+ * Mirrors Rust's `GroupSpec::parse` (`bc-sskr-rust/src/spec.rs:97-112`),
87
+ * which calls `parts[0].parse::<usize>()`. Rust's `usize::FromStr` is
88
+ * strict: it rejects whitespace, decimals, trailing characters, and the
89
+ * `-` sign, accepting only an optional `+` prefix followed by digits.
90
+ * We mirror that with the regex `^\+?\d+$` so strings like `"2.5"`,
91
+ * `"2x"`, `" 2"`, `"-2"`, and `""` all surface
92
+ * {@link SSKRErrorType.GroupSpecInvalid} on both sides.
59
93
  */
60
94
  static parse(s: string): GroupSpec {
61
95
  const parts = s.split("-");
@@ -63,8 +97,8 @@ export class GroupSpec {
63
97
  throw new SSKRError(SSKRErrorType.GroupSpecInvalid);
64
98
  }
65
99
 
66
- const memberThreshold = parseInt(parts[0], 10);
67
- if (isNaN(memberThreshold)) {
100
+ const memberThreshold = parseStrictUsize(parts[0]);
101
+ if (memberThreshold === undefined) {
68
102
  throw new SSKRError(SSKRErrorType.GroupSpecInvalid);
69
103
  }
70
104
 
@@ -72,8 +106,8 @@ export class GroupSpec {
72
106
  throw new SSKRError(SSKRErrorType.GroupSpecInvalid);
73
107
  }
74
108
 
75
- const memberCount = parseInt(parts[2], 10);
76
- if (isNaN(memberCount)) {
109
+ const memberCount = parseStrictUsize(parts[2]);
110
+ if (memberCount === undefined) {
77
111
  throw new SSKRError(SSKRErrorType.GroupSpecInvalid);
78
112
  }
79
113