threshold-elgamal 1.0.8 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/README.md +29 -35
  2. package/dist/core/bigint.js +4 -0
  3. package/dist/core/bytes.js +4 -0
  4. package/dist/core/crypto.js +5 -0
  5. package/dist/core/errors.d.ts +50 -11
  6. package/dist/core/errors.js +50 -11
  7. package/dist/core/groups.d.ts +6 -1
  8. package/dist/core/groups.js +13 -2
  9. package/dist/core/index.d.ts +4 -0
  10. package/dist/core/index.js +4 -0
  11. package/dist/core/public.d.ts +13 -0
  12. package/dist/core/public.js +12 -0
  13. package/dist/core/random.js +4 -0
  14. package/dist/core/ristretto.d.ts +7 -0
  15. package/dist/core/ristretto.js +7 -0
  16. package/dist/core/types.d.ts +14 -6
  17. package/dist/core/validation.d.ts +45 -12
  18. package/dist/core/validation.js +52 -12
  19. package/dist/dkg/pedersen-share-codec.d.ts +12 -2
  20. package/dist/dkg/pedersen-share-codec.js +19 -2
  21. package/dist/dkg/public.d.ts +12 -0
  22. package/dist/dkg/public.js +11 -0
  23. package/dist/dkg/verification.d.ts +33 -14
  24. package/dist/dkg/verification.js +16 -12
  25. package/dist/elgamal/additive.d.ts +15 -3
  26. package/dist/elgamal/additive.js +22 -4
  27. package/dist/elgamal/bsgs.js +7 -0
  28. package/dist/elgamal/public.d.ts +11 -0
  29. package/dist/elgamal/public.js +10 -0
  30. package/dist/elgamal/types.d.ts +6 -0
  31. package/dist/index.d.ts +11 -25
  32. package/dist/index.js +10 -19
  33. package/dist/proofs/disjunctive.d.ts +10 -16
  34. package/dist/proofs/disjunctive.js +10 -16
  35. package/dist/proofs/dleq.d.ts +17 -13
  36. package/dist/proofs/dleq.js +11 -12
  37. package/dist/proofs/helpers.js +4 -0
  38. package/dist/proofs/nonces.js +6 -0
  39. package/dist/proofs/public.d.ts +12 -0
  40. package/dist/proofs/public.js +11 -0
  41. package/dist/proofs/schnorr.d.ts +10 -11
  42. package/dist/proofs/schnorr.js +10 -11
  43. package/dist/proofs/types.d.ts +30 -5
  44. package/dist/protocol/board-audit.d.ts +8 -3
  45. package/dist/protocol/board-audit.js +8 -2
  46. package/dist/protocol/builders.d.ts +77 -13
  47. package/dist/protocol/builders.js +83 -13
  48. package/dist/protocol/canonical-json.js +4 -0
  49. package/dist/protocol/manifest.d.ts +32 -15
  50. package/dist/protocol/manifest.js +39 -16
  51. package/dist/protocol/ordering.js +6 -0
  52. package/dist/protocol/payloads.d.ts +3 -3
  53. package/dist/protocol/payloads.js +7 -3
  54. package/dist/protocol/public.d.ts +15 -0
  55. package/dist/protocol/public.js +14 -0
  56. package/dist/protocol/transcript.js +4 -0
  57. package/dist/protocol/types.d.ts +98 -17
  58. package/dist/protocol/verification.d.ts +14 -7
  59. package/dist/protocol/verification.js +7 -5
  60. package/dist/protocol/voting-ballot-aggregation.d.ts +10 -2
  61. package/dist/protocol/voting-ballot-aggregation.js +6 -0
  62. package/dist/protocol/voting-ballots.d.ts +3 -5
  63. package/dist/protocol/voting-ballots.js +6 -5
  64. package/dist/protocol/voting-codecs.d.ts +3 -1
  65. package/dist/protocol/voting-codecs.js +7 -1
  66. package/dist/protocol/voting-decryption.d.ts +3 -5
  67. package/dist/protocol/voting-decryption.js +7 -5
  68. package/dist/protocol/voting-shared.js +6 -0
  69. package/dist/protocol/voting-verification.d.ts +27 -30
  70. package/dist/protocol/voting-verification.js +11 -25
  71. package/dist/serialize/encoding.js +4 -0
  72. package/dist/threshold/decrypt.d.ts +13 -5
  73. package/dist/threshold/decrypt.js +20 -5
  74. package/dist/threshold/public.d.ts +11 -0
  75. package/dist/threshold/public.js +10 -0
  76. package/dist/threshold/types.d.ts +23 -4
  77. package/dist/transport/auth.d.ts +10 -16
  78. package/dist/transport/auth.js +16 -16
  79. package/dist/transport/complaints.d.ts +2 -4
  80. package/dist/transport/complaints.js +8 -4
  81. package/dist/transport/envelopes.d.ts +5 -7
  82. package/dist/transport/envelopes.js +9 -7
  83. package/dist/transport/key-agreement.d.ts +15 -23
  84. package/dist/transport/key-agreement.js +21 -23
  85. package/dist/transport/types.d.ts +16 -2
  86. package/dist/vss/feldman.d.ts +11 -1
  87. package/dist/vss/feldman.js +11 -1
  88. package/dist/vss/pedersen.d.ts +13 -0
  89. package/dist/vss/pedersen.js +13 -0
  90. package/dist/vss/public.d.ts +10 -0
  91. package/dist/vss/public.js +9 -0
  92. package/dist/vss/types.d.ts +4 -0
  93. package/package.json +31 -3
package/README.md CHANGED
@@ -1,20 +1,18 @@
1
1
  # threshold-elgamal
2
2
 
3
- [![npm version](https://badge.fury.io/js/threshold-elgamal.svg)](https://www.npmjs.com/package/threshold-elgamal)
4
- [![npm downloads](https://img.shields.io/npm/dm/threshold-elgamal)](https://www.npmjs.com/package/threshold-elgamal)
3
+ [![npm downloads](https://img.shields.io/npm/dm/threshold-elgamal?color=5FA04E)](https://www.npmjs.com/package/threshold-elgamal)
5
4
 
6
5
  ---
7
6
 
8
- [![CI](https://img.shields.io/github/actions/workflow/status/Tenemo/threshold-elgamal/ci.yml?branch=master&label=passing%20tests)](https://github.com/Tenemo/threshold-elgamal/actions/workflows/ci.yml)
7
+ [![CI](https://img.shields.io/github/actions/workflow/status/Tenemo/threshold-elgamal/ci.yml?branch=master&label=passing%20tests&color=5FA04E)](https://github.com/Tenemo/threshold-elgamal/actions/workflows/ci.yml)
9
8
  [![Tests coverage](https://img.shields.io/endpoint?url=https://tenemo.github.io/threshold-elgamal/coverage-badge.json)](https://tenemo.github.io/threshold-elgamal/coverage-summary.json)
10
- [![Documentation build](https://img.shields.io/github/actions/workflow/status/Tenemo/threshold-elgamal/pages.yml?branch=master&label=docs)](https://github.com/Tenemo/threshold-elgamal/actions/workflows/pages.yml)
9
+ [![Documentation build](https://img.shields.io/github/actions/workflow/status/Tenemo/threshold-elgamal/pages.yml?branch=master&label=docs&color=5FA04E)](https://github.com/Tenemo/threshold-elgamal/actions/workflows/pages.yml)
11
10
 
12
11
  ---
13
12
 
14
- [![Node version](https://img.shields.io/badge/node-%E2%89%A524.14.1-5FA04E?logo=node.js&logoColor=white)](https://nodejs.org/)
15
13
  [![License](https://img.shields.io/github/license/Tenemo/threshold-elgamal)](LICENSE)
16
14
 
17
- `threshold-elgamal` is a browser-native TypeScript library for verifiable score-voting research prototypes. The shipped beta line is focused on one workflow only:
15
+ `threshold-elgamal` is a browser-native TypeScript library for verifiable score-voting research prototypes. It focuses on one workflow:
18
16
 
19
17
  - additive ElGamal on `ristretto255`
20
18
  - honest-majority GJKR DKG
@@ -37,45 +35,40 @@ npm install threshold-elgamal
37
35
 
38
36
  - Use ESM imports such as `import { createElectionManifest } from 'threshold-elgamal'`.
39
37
  - Browsers need native `bigint` together with Web Crypto.
40
- - Node requires version `24.14.1` or newer with `globalThis.crypto`.
38
+ - Node must satisfy the package `engines.node` requirement and expose `globalThis.crypto`.
41
39
  - Authentication signatures require Web Crypto `Ed25519`.
42
40
  - Transport share exchange requires Web Crypto `X25519`.
43
41
 
44
- See [Runtime and compatibility](https://tenemo.github.io/threshold-elgamal/guides/runtime-and-compatibility/) for the tested browser and Node matrix.
45
-
46
- ## Start here
47
-
48
- - [Verifying a public board](https://tenemo.github.io/threshold-elgamal/guides/verifying-a-public-board/): start here for `tryVerifyElectionCeremony(...)` and `verifyElectionCeremony(...)`.
49
- - [Browser and worker usage](https://tenemo.github.io/threshold-elgamal/guides/browser-and-worker-usage/): start here for key generation, manifest setup, and encrypted transport envelopes.
50
- - [Published payload examples](https://tenemo.github.io/threshold-elgamal/guides/published-payload-examples/): start here if you need concrete JSON, posting, or persistence patterns.
51
- - [Honest-majority voting flow](https://tenemo.github.io/threshold-elgamal/guides/three-participant-voting-flow/): read this for the supported phase-by-phase transcript story.
42
+ See [Runtime and compatibility](https://tenemo.github.io/threshold-elgamal/guides/runtime-and-compatibility/) for environment requirements.
52
43
 
53
44
  ## Documentation
54
45
 
55
- - Hosted documentation site: [tenemo.github.io/threshold-elgamal](https://tenemo.github.io/threshold-elgamal/)
56
- - Get started: [tenemo.github.io/threshold-elgamal/guides/getting-started](https://tenemo.github.io/threshold-elgamal/guides/getting-started/)
57
- - Verifying a public board: [tenemo.github.io/threshold-elgamal/guides/verifying-a-public-board](https://tenemo.github.io/threshold-elgamal/guides/verifying-a-public-board/)
46
+ - Homepage: [tenemo.github.io/threshold-elgamal](https://tenemo.github.io/threshold-elgamal/)
47
+ - Getting started: [tenemo.github.io/threshold-elgamal/guides/getting-started](https://tenemo.github.io/threshold-elgamal/guides/getting-started/)
48
+ - Runtime and compatibility: [tenemo.github.io/threshold-elgamal/guides/runtime-and-compatibility](https://tenemo.github.io/threshold-elgamal/guides/runtime-and-compatibility/)
58
49
  - Browser and worker usage: [tenemo.github.io/threshold-elgamal/guides/browser-and-worker-usage](https://tenemo.github.io/threshold-elgamal/guides/browser-and-worker-usage/)
59
- - Published payload examples: [tenemo.github.io/threshold-elgamal/guides/published-payload-examples](https://tenemo.github.io/threshold-elgamal/guides/published-payload-examples/)
60
50
  - Honest-majority voting flow: [tenemo.github.io/threshold-elgamal/guides/three-participant-voting-flow](https://tenemo.github.io/threshold-elgamal/guides/three-participant-voting-flow/)
61
- - Runtime and compatibility: [tenemo.github.io/threshold-elgamal/guides/runtime-and-compatibility](https://tenemo.github.io/threshold-elgamal/guides/runtime-and-compatibility/)
51
+ - Published payload examples: [tenemo.github.io/threshold-elgamal/guides/published-payload-examples](https://tenemo.github.io/threshold-elgamal/guides/published-payload-examples/)
52
+
53
+ ---
54
+
55
+ - Verifying a public board: [tenemo.github.io/threshold-elgamal/guides/verifying-a-public-board](https://tenemo.github.io/threshold-elgamal/guides/verifying-a-public-board/)
62
56
  - Security boundary: [tenemo.github.io/threshold-elgamal/guides/security-and-non-goals](https://tenemo.github.io/threshold-elgamal/guides/security-and-non-goals/)
63
57
  - Production voting safety review: [tenemo.github.io/threshold-elgamal/guides/production-voting-safety-review](https://tenemo.github.io/threshold-elgamal/guides/production-voting-safety-review/)
58
+
59
+ ---
60
+
64
61
  - API docs: [tenemo.github.io/threshold-elgamal/api](https://tenemo.github.io/threshold-elgamal/api/)
65
62
 
66
63
  ## Browser support
67
64
 
68
- The shipped cryptographic browser path is fixed:
65
+ The cryptographic browser path is fixed:
69
66
 
70
67
  - `Ed25519` for protocol payload signatures
71
68
  - `X25519` for encrypted share transport
72
69
 
73
- Practical browser baseline for the public workflow:
74
-
75
- - Chrome and Edge `137+`
76
- - Firefox `130+`
77
- - Safari `18.4+`
78
- - iOS and iPadOS browsers on the Safari `18.4+` WebKit generation
70
+ - Use modern browsers that expose Web Crypto `Ed25519`, Web Crypto `X25519`, and native `bigint`
71
+ - Validate your target environments with `pnpm exec tsx ./tools/ci/verify-browser-compat.ts` before deployment
79
72
 
80
73
  Older browsers, stale embedded webviews, and runtimes without Web Crypto `X25519` support are not supported.
81
74
 
@@ -178,7 +171,7 @@ if (!result.ok) {
178
171
  }
179
172
  ```
180
173
 
181
- The root package also exposes builders for the signed protocol payloads used across the shipped ceremony, including:
174
+ The root package exposes the workflow-facing builders for the signed protocol payloads used across the documented ceremony, including:
182
175
 
183
176
  - manifest publication
184
177
  - registration
@@ -193,13 +186,14 @@ The root package also exposes builders for the signed protocol payloads used acr
193
186
  - decryption shares
194
187
  - tally publication
195
188
 
196
- For the reveal path, the public root surface is intentionally three-step:
189
+ For the reveal path, the workflow-facing API and the advanced public submodules split responsibilities intentionally:
197
190
 
198
- - prepare the accepted aggregate with `prepareAggregateForDecryption(...)`
199
- - compute each partial share with `createDecryptionShare(...)`
200
- - prove and publish it with `createDLEQProof(...)` and `createDecryptionSharePayload(...)`
191
+ - prepare the accepted aggregate with `prepareAggregateForDecryption(...)` from `threshold-elgamal/threshold`
192
+ - compute each partial share with `createDecryptionShare(...)` from `threshold-elgamal/threshold`
193
+ - prove it with `createDLEQProof(...)` from `threshold-elgamal/proofs`
194
+ - publish it with `createDecryptionSharePayload(...)` from `threshold-elgamal`
201
195
 
202
- After collecting a threshold subset, recover the tally with `combineDecryptionShares(...)` against the prepared aggregate ciphertext.
196
+ After collecting a threshold subset, recover the tally with `combineDecryptionShares(...)` from `threshold-elgamal/threshold` against the prepared aggregate ciphertext.
203
197
 
204
198
  For concrete posted JSON shapes, use [Published payload examples](https://tenemo.github.io/threshold-elgamal/guides/published-payload-examples/).
205
199
 
@@ -224,9 +218,9 @@ What it does not claim:
224
218
  - constant-time JavaScript `bigint` execution
225
219
  - production readiness
226
220
 
227
- `ballot-close` is an auditable administrative cutoff, not a fairness proof about board arrival order. The library proves what was counted, not whether the organizer waited long enough before closing.
221
+ `ballot-close` is an auditable administrative cutoff, not a fairness proof about board arrival order. The library proves which ballots count, not whether the organizer waited long enough before closing.
228
222
 
229
- For a production-threat-model verdict that maps these boundaries to the shipped verifier and tests, read the [production voting safety review](https://tenemo.github.io/threshold-elgamal/guides/production-voting-safety-review/).
223
+ For a production-threat-model verdict that maps these boundaries to the verifier and tests, read the [production voting safety review](https://tenemo.github.io/threshold-elgamal/guides/production-voting-safety-review/).
230
224
 
231
225
  ## Development
232
226
 
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Finite-field arithmetic helpers shared by proofs, verifiable secret sharing,
3
+ * threshold reconstruction, and transcript verification.
4
+ */
1
5
  import { InvalidScalarError } from './errors.js';
2
6
  const assertPositiveModulus = (modulus) => {
3
7
  if (modulus <= 0n) {
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Byte, hex, and buffer-shape conversion helpers used by hashing,
3
+ * serialization, signatures, and transport code throughout the package.
4
+ */
1
5
  import { InvalidPayloadError } from './errors.js';
2
6
  const hexPattern = /^[0-9a-f]+$/i;
3
7
  const defaultHexErrorMessage = 'Hex input must be a non-empty even-length hexadecimal string';
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Runtime crypto helpers that normalize Web Crypto access for hashing,
3
+ * HKDF-based key derivation, and UTF-8 encoding across browser and Node
4
+ * runtimes.
5
+ */
1
6
  import { toBufferSource } from './bytes.js';
2
7
  import { InvalidScalarError, UnsupportedSuiteError } from './errors.js';
3
8
  const textEncoder = new TextEncoder();
@@ -1,37 +1,76 @@
1
+ /**
2
+ * Shared error taxonomy for the package.
3
+ *
4
+ * Public helpers throw these errors when callers violate mathematical,
5
+ * encoding, transcript, or workflow invariants.
6
+ */
1
7
  declare class ThresholdElGamalError extends Error {
2
8
  constructor(message: string);
3
9
  }
4
- /** Raised when a scalar value falls outside the expected mathematical domain. */
10
+ /**
11
+ * Raised when a scalar value falls outside the expected field or subgroup
12
+ * domain for the current operation.
13
+ */
5
14
  export declare class InvalidScalarError extends ThresholdElGamalError {
6
15
  }
7
- /** Raised when a group element is not valid for the selected suite. */
16
+ /**
17
+ * Raised when a point or public key is not a canonical member of the selected
18
+ * cryptographic group.
19
+ */
8
20
  export declare class InvalidGroupElementError extends ThresholdElGamalError {
9
21
  }
10
- /** Raised when a participant index falls outside the valid `1..n` range. */
22
+ /**
23
+ * Raised when a participant index falls outside the supported `1..n`
24
+ * numbering scheme used across the protocol.
25
+ */
11
26
  export declare class IndexOutOfRangeError extends ThresholdElGamalError {
12
27
  }
13
- /** Raised when serialized payload bytes do not satisfy the required encoding. */
28
+ /**
29
+ * Raised when a payload, transcript field, manifest field, or serialized value
30
+ * does not satisfy the package's canonical encoding rules.
31
+ */
14
32
  export declare class InvalidPayloadError extends ThresholdElGamalError {
15
33
  }
16
- /** Raised when a proof transcript or response fails verification. */
34
+ /**
35
+ * Raised when a Schnorr, DLEQ, or disjunctive proof transcript fails
36
+ * structural checks or cryptographic verification.
37
+ */
17
38
  export declare class InvalidProofError extends ThresholdElGamalError {
18
39
  }
19
- /** Raised when the requested suite or runtime capability is unavailable. */
40
+ /**
41
+ * Raised when the requested suite or required runtime capability is unavailable
42
+ * in the current environment.
43
+ */
20
44
  export declare class UnsupportedSuiteError extends ThresholdElGamalError {
21
45
  }
22
- /** Raised when a plaintext lies outside the allowed domain for the chosen mode. */
46
+ /**
47
+ * Raised when an additive plaintext falls outside the explicitly bounded domain
48
+ * that the current workflow promised to support.
49
+ */
23
50
  export declare class PlaintextDomainError extends ThresholdElGamalError {
24
51
  }
25
- /** Raised when a serialized or reconstructed share fails validation. */
52
+ /**
53
+ * Raised when a serialized share, decrypted share envelope, or reconstructed
54
+ * share set fails threshold-specific validation.
55
+ */
26
56
  export declare class InvalidShareError extends ThresholdElGamalError {
27
57
  }
28
- /** Raised when a protocol step transition violates the state machine rules. */
58
+ /**
59
+ * Raised when a published payload claims to belong to a protocol phase that
60
+ * does not match the supported ceremony state machine.
61
+ */
29
62
  export declare class PhaseViolationError extends ThresholdElGamalError {
30
63
  }
31
- /** Raised when threshold parameters do not satisfy `1 <= k <= n`. */
64
+ /**
65
+ * Raised when threshold parameters or participant counts violate the supported
66
+ * `1 <= k <= n` relationship or the package's honest-majority policy.
67
+ */
32
68
  export declare class ThresholdViolationError extends ThresholdElGamalError {
33
69
  }
34
- /** Raised when transcript hashes or canonical bytes do not match expectations. */
70
+ /**
71
+ * Raised when transcript hashes, manifest hashes, or other canonical digest
72
+ * commitments do not match the values claimed by published payloads.
73
+ */
35
74
  export declare class TranscriptMismatchError extends ThresholdElGamalError {
36
75
  }
37
76
  export {};
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Shared error taxonomy for the package.
3
+ *
4
+ * Public helpers throw these errors when callers violate mathematical,
5
+ * encoding, transcript, or workflow invariants.
6
+ */
1
7
  class ThresholdElGamalError extends Error {
2
8
  constructor(message) {
3
9
  super(message);
@@ -5,36 +11,69 @@ class ThresholdElGamalError extends Error {
5
11
  Object.setPrototypeOf(this, new.target.prototype);
6
12
  }
7
13
  }
8
- /** Raised when a scalar value falls outside the expected mathematical domain. */
14
+ /**
15
+ * Raised when a scalar value falls outside the expected field or subgroup
16
+ * domain for the current operation.
17
+ */
9
18
  export class InvalidScalarError extends ThresholdElGamalError {
10
19
  }
11
- /** Raised when a group element is not valid for the selected suite. */
20
+ /**
21
+ * Raised when a point or public key is not a canonical member of the selected
22
+ * cryptographic group.
23
+ */
12
24
  export class InvalidGroupElementError extends ThresholdElGamalError {
13
25
  }
14
- /** Raised when a participant index falls outside the valid `1..n` range. */
26
+ /**
27
+ * Raised when a participant index falls outside the supported `1..n`
28
+ * numbering scheme used across the protocol.
29
+ */
15
30
  export class IndexOutOfRangeError extends ThresholdElGamalError {
16
31
  }
17
- /** Raised when serialized payload bytes do not satisfy the required encoding. */
32
+ /**
33
+ * Raised when a payload, transcript field, manifest field, or serialized value
34
+ * does not satisfy the package's canonical encoding rules.
35
+ */
18
36
  export class InvalidPayloadError extends ThresholdElGamalError {
19
37
  }
20
- /** Raised when a proof transcript or response fails verification. */
38
+ /**
39
+ * Raised when a Schnorr, DLEQ, or disjunctive proof transcript fails
40
+ * structural checks or cryptographic verification.
41
+ */
21
42
  export class InvalidProofError extends ThresholdElGamalError {
22
43
  }
23
- /** Raised when the requested suite or runtime capability is unavailable. */
44
+ /**
45
+ * Raised when the requested suite or required runtime capability is unavailable
46
+ * in the current environment.
47
+ */
24
48
  export class UnsupportedSuiteError extends ThresholdElGamalError {
25
49
  }
26
- /** Raised when a plaintext lies outside the allowed domain for the chosen mode. */
50
+ /**
51
+ * Raised when an additive plaintext falls outside the explicitly bounded domain
52
+ * that the current workflow promised to support.
53
+ */
27
54
  export class PlaintextDomainError extends ThresholdElGamalError {
28
55
  }
29
- /** Raised when a serialized or reconstructed share fails validation. */
56
+ /**
57
+ * Raised when a serialized share, decrypted share envelope, or reconstructed
58
+ * share set fails threshold-specific validation.
59
+ */
30
60
  export class InvalidShareError extends ThresholdElGamalError {
31
61
  }
32
- /** Raised when a protocol step transition violates the state machine rules. */
62
+ /**
63
+ * Raised when a published payload claims to belong to a protocol phase that
64
+ * does not match the supported ceremony state machine.
65
+ */
33
66
  export class PhaseViolationError extends ThresholdElGamalError {
34
67
  }
35
- /** Raised when threshold parameters do not satisfy `1 <= k <= n`. */
68
+ /**
69
+ * Raised when threshold parameters or participant counts violate the supported
70
+ * `1 <= k <= n` relationship or the package's honest-majority policy.
71
+ */
36
72
  export class ThresholdViolationError extends ThresholdElGamalError {
37
73
  }
38
- /** Raised when transcript hashes or canonical bytes do not match expectations. */
74
+ /**
75
+ * Raised when transcript hashes, manifest hashes, or other canonical digest
76
+ * commitments do not match the values claimed by published payloads.
77
+ */
39
78
  export class TranscriptMismatchError extends ThresholdElGamalError {
40
79
  }
@@ -1,4 +1,9 @@
1
1
  import type { CryptoGroup } from './types.js';
2
- /** Immutable definition of the shipped Ristretto255 tally group. */
2
+ /**
3
+ * Immutable definition of the built-in `ristretto255` tally group.
4
+ *
5
+ * Every public cryptographic workflow in this package ultimately routes
6
+ * through this suite definition.
7
+ */
3
8
  export declare const RISTRETTO_GROUP: CryptoGroup;
4
9
  export declare const assertCanonicalRistrettoGroup: (group: CryptoGroup, label?: string) => void;
@@ -1,6 +1,17 @@
1
+ /**
2
+ * Built-in group definitions and suite guard rails.
3
+ *
4
+ * The public API is intentionally tied to one canonical suite,
5
+ * `ristretto255`, and this module makes that choice explicit.
6
+ */
1
7
  import { UnsupportedSuiteError } from './errors.js';
2
8
  import { derivePedersenGenerator, RISTRETTO_BYTE_LENGTH } from './ristretto.js';
3
- /** Immutable definition of the shipped Ristretto255 tally group. */
9
+ /**
10
+ * Immutable definition of the built-in `ristretto255` tally group.
11
+ *
12
+ * Every public cryptographic workflow in this package ultimately routes
13
+ * through this suite definition.
14
+ */
4
15
  export const RISTRETTO_GROUP = Object.freeze({
5
16
  name: 'ristretto255',
6
17
  byteLength: RISTRETTO_BYTE_LENGTH,
@@ -20,6 +31,6 @@ const sameCanonicalRistrettoGroup = (group) => group.name === RISTRETTO_GROUP.na
20
31
  export const assertCanonicalRistrettoGroup = (group, label = 'Group') => {
21
32
  const normalizedLabel = label.length > 0 ? `${label[0].toLowerCase()}${label.slice(1)}` : label;
22
33
  if (!sameCanonicalRistrettoGroup(group)) {
23
- throw new UnsupportedSuiteError(`${normalizedLabel} must match the shipped canonical ristretto255 group definition`);
34
+ throw new UnsupportedSuiteError(`${normalizedLabel} must match the canonical ristretto255 group definition`);
24
35
  }
25
36
  };
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Internal barrel for the core arithmetic, encoding, randomness, and
3
+ * validation primitives that higher-level modules compose.
4
+ */
1
5
  export { modInvQ, modQ } from './bigint.js';
2
6
  export * from './crypto.js';
3
7
  export * from './errors.js';
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Internal barrel for the core arithmetic, encoding, randomness, and
3
+ * validation primitives that higher-level modules compose.
4
+ */
1
5
  export { modInvQ, modQ } from './bigint.js';
2
6
  export * from './crypto.js';
3
7
  export * from './errors.js';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Low-level core helpers for arithmetic, error handling, and group constants.
3
+ *
4
+ * Use this module when you need primitives that sit below the voting workflow
5
+ * surface exposed by the root package.
6
+ *
7
+ * @module threshold-elgamal/core
8
+ * @packageDocumentation
9
+ */
10
+ export { IndexOutOfRangeError, InvalidGroupElementError, InvalidPayloadError, InvalidProofError, InvalidScalarError, InvalidShareError, PhaseViolationError, PlaintextDomainError, ThresholdViolationError, TranscriptMismatchError, UnsupportedSuiteError, } from './errors.js';
11
+ export { modQ } from './bigint.js';
12
+ export { RISTRETTO_GROUP } from './groups.js';
13
+ export type { EncodedPoint } from './types.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Low-level core helpers for arithmetic, error handling, and group constants.
3
+ *
4
+ * Use this module when you need primitives that sit below the voting workflow
5
+ * surface exposed by the root package.
6
+ *
7
+ * @module threshold-elgamal/core
8
+ * @packageDocumentation
9
+ */
10
+ export { IndexOutOfRangeError, InvalidGroupElementError, InvalidPayloadError, InvalidProofError, InvalidScalarError, InvalidShareError, PhaseViolationError, PlaintextDomainError, ThresholdViolationError, TranscriptMismatchError, UnsupportedSuiteError, } from './errors.js';
11
+ export { modQ } from './bigint.js';
12
+ export { RISTRETTO_GROUP } from './groups.js';
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Randomness helpers used by proof generation, envelope encryption, and other
3
+ * cryptographic sampling paths.
4
+ */
1
5
  import { bytesToBigInt } from './bytes.js';
2
6
  import { getWebCrypto } from './crypto.js';
3
7
  import { InvalidScalarError } from './errors.js';
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Low-level Ristretto255 point and scalar operations.
3
+ *
4
+ * Higher-level modules such as additive ElGamal, proofs, VSS, and threshold
5
+ * reconstruction build on these wrappers instead of calling the curve library
6
+ * directly.
7
+ */
1
8
  import { ristretto255 } from '@noble/curves/ed25519.js';
2
9
  import type { EncodedPoint } from './types.js';
3
10
  type InternalPoint = InstanceType<typeof ristretto255.Point>;
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Low-level Ristretto255 point and scalar operations.
3
+ *
4
+ * Higher-level modules such as additive ElGamal, proofs, VSS, and threshold
5
+ * reconstruction build on these wrappers instead of calling the curve library
6
+ * directly.
7
+ */
1
8
  import { ristretto255, ristretto255_hasher } from '@noble/curves/ed25519.js';
2
9
  import { sha512 } from '@noble/hashes/sha2.js';
3
10
  import { bytesToBigInt, bytesToBigIntLE, bytesToHex, hexToBytes, } from './bytes.js';
@@ -1,3 +1,6 @@
1
+ /**
2
+ * Foundational nominal and suite types shared across the package.
3
+ */
1
4
  /**
2
5
  * Nominal typing helper used to distinguish compatible runtime values in the
3
6
  * type system.
@@ -5,13 +8,18 @@
5
8
  export type Brand<T, TBrand extends string> = T & {
6
9
  readonly __brand: TBrand;
7
10
  };
8
- /** @internal Canonical name for the shipped Ristretto255 suite. */
11
+ /** @internal Canonical name for the built-in Ristretto255 suite. */
9
12
  export type GroupName = 'ristretto255';
10
- /** @internal Accepted helper input identifiers for the shipped Ristretto suite. */
13
+ /** @internal Accepted helper input identifiers for the built-in Ristretto suite. */
11
14
  export type GroupIdentifier = GroupName;
12
- /** Canonical 32-byte Ristretto point encoding exposed at the public boundary. */
15
+ /**
16
+ * Canonical 32-byte Ristretto point encoding exposed at the public boundary.
17
+ *
18
+ * Public helpers use this branded string type to distinguish encoded points
19
+ * from ordinary hex strings.
20
+ */
13
21
  export type EncodedPoint = Brand<string, 'EncodedPoint'>;
14
- /** @internal Immutable built-in group definition for the shipped suite. */
22
+ /** @internal Immutable group definition for the built-in suite. */
15
23
  export type CryptoGroup = {
16
24
  /** Canonical suite name. */
17
25
  readonly name: GroupName;
@@ -29,7 +37,7 @@ export type CryptoGroup = {
29
37
  readonly securityEstimate: number;
30
38
  };
31
39
  /**
32
- * Random byte source injected into sampling helpers for deterministic testing
33
- * or custom runtime integration.
40
+ * Random byte source injected into sampling helpers for deterministic tests,
41
+ * reproducible vectors, or custom runtime integration.
34
42
  */
35
43
  export type RandomBytesSource = (length: number) => Uint8Array;
@@ -1,6 +1,16 @@
1
- /** Returns `true` when the value is a non-identity valid Ristretto point. */
1
+ /**
2
+ * Returns `true` when the value is a canonical non-identity Ristretto point.
3
+ *
4
+ * This is the predicate used for public keys and most commitment elements.
5
+ */
2
6
  export declare const isInSubgroup: (value: string) => boolean;
3
- /** Returns `true` when the value is a valid Ristretto point, including identity. */
7
+ /**
8
+ * Returns `true` when the value is a canonical Ristretto point, including the
9
+ * identity element.
10
+ *
11
+ * This variant is used for ciphertext components and transcript values that
12
+ * are allowed to land on the identity.
13
+ */
4
14
  export declare const isInSubgroupOrIdentity: (value: string) => boolean;
5
15
  /**
6
16
  * Validates that a scalar belongs to `Z_q`.
@@ -30,25 +40,48 @@ export declare const assertPlaintextAdditive: (value: bigint, bound: bigint, q:
30
40
  */
31
41
  export declare const assertThreshold: (threshold: number, participantCount: number) => void;
32
42
  /**
33
- * Derives the shipped GJKR honest-majority threshold `ceil(n / 2)`.
43
+ * Derives the supported honest-majority threshold `ceil(n / 2)`.
34
44
  *
35
- * For odd `n` this matches the usual strict-majority value. For even `n` the
36
- * shipped protocol uses the maximal honest-majority instantiation proved for
37
- * GJKR, which yields `k = n / 2`.
45
+ * This is the threshold policy used by the package's DKG and full voting flow.
46
+ * Callers do not choose a custom `k`; the verifier derives it from the
47
+ * accepted registration roster.
38
48
  */
39
49
  export declare const majorityThreshold: (participantCount: number) => number;
40
50
  /**
41
- * Validates that the supplied threshold matches the shipped GJKR
51
+ * Validates that the supplied threshold matches the library's GJKR
42
52
  * honest-majority policy.
43
53
  */
44
54
  export declare const assertMajorityThreshold: (threshold: number, participantCount: number) => number;
45
- /** Validates a 1-based participant index without assuming a fixed count. */
55
+ /**
56
+ * Validates a 1-based participant index without assuming a fixed participant
57
+ * count.
58
+ *
59
+ * The package consistently numbers trustees and voters from `1`.
60
+ */
46
61
  export declare const assertPositiveParticipantIndex: (index: number) => void;
47
- /** Validates a 1-based participant index for a fixed participant count. */
62
+ /**
63
+ * Validates a 1-based participant index against a fixed participant count.
64
+ *
65
+ * This is the usual check for published payloads that already sit inside a
66
+ * frozen roster.
67
+ */
48
68
  export declare const assertValidParticipantIndex: (index: number, participantCount: number) => void;
49
- /** Validates that a value is a non-identity valid Ristretto point. */
69
+ /**
70
+ * Validates that a value is a canonical non-identity Ristretto point.
71
+ *
72
+ * This is the assertion form of {@link isInSubgroup}.
73
+ */
50
74
  export declare const assertInSubgroup: (value: string) => void;
51
- /** Validates that a value is a valid Ristretto point, including identity. */
75
+ /**
76
+ * Validates that a value is a canonical Ristretto point, including identity.
77
+ *
78
+ * This is the assertion form of {@link isInSubgroupOrIdentity}.
79
+ */
52
80
  export declare const assertInSubgroupOrIdentity: (value: string) => void;
53
- /** Validates a public key as a non-identity Ristretto point. */
81
+ /**
82
+ * Validates a public key as a canonical non-identity Ristretto point.
83
+ *
84
+ * Public keys, verification keys, and commitment generators all route through
85
+ * this helper.
86
+ */
54
87
  export declare const assertValidPublicKey: (value: string) => void;