threshold-elgamal 1.0.9 → 2.0.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 (98) hide show
  1. package/README.md +33 -35
  2. package/dist/core/bigint.d.ts +2 -1
  3. package/dist/core/bigint.js +6 -1
  4. package/dist/core/bytes.js +4 -0
  5. package/dist/core/crypto.js +5 -0
  6. package/dist/core/errors.d.ts +50 -11
  7. package/dist/core/errors.js +50 -11
  8. package/dist/core/groups.d.ts +6 -1
  9. package/dist/core/groups.js +13 -2
  10. package/dist/core/index.d.ts +4 -0
  11. package/dist/core/index.js +4 -0
  12. package/dist/core/public.d.ts +13 -0
  13. package/dist/core/public.js +12 -0
  14. package/dist/core/random.js +4 -0
  15. package/dist/core/ristretto.d.ts +7 -0
  16. package/dist/core/ristretto.js +7 -0
  17. package/dist/core/types.d.ts +14 -6
  18. package/dist/core/validation.d.ts +45 -12
  19. package/dist/core/validation.js +52 -12
  20. package/dist/dkg/pedersen-share-codec.d.ts +12 -2
  21. package/dist/dkg/pedersen-share-codec.js +19 -2
  22. package/dist/dkg/public.d.ts +12 -0
  23. package/dist/dkg/public.js +11 -0
  24. package/dist/dkg/verification.d.ts +33 -14
  25. package/dist/dkg/verification.js +16 -12
  26. package/dist/elgamal/additive.d.ts +15 -3
  27. package/dist/elgamal/additive.js +27 -23
  28. package/dist/elgamal/bsgs.js +7 -0
  29. package/dist/elgamal/public.d.ts +11 -0
  30. package/dist/elgamal/public.js +10 -0
  31. package/dist/elgamal/types.d.ts +6 -0
  32. package/dist/index.d.ts +27 -25
  33. package/dist/index.js +20 -19
  34. package/dist/proofs/disjunctive.d.ts +11 -16
  35. package/dist/proofs/disjunctive.js +12 -17
  36. package/dist/proofs/dleq.d.ts +17 -13
  37. package/dist/proofs/dleq.js +11 -12
  38. package/dist/proofs/helpers.d.ts +1 -1
  39. package/dist/proofs/helpers.js +5 -4
  40. package/dist/proofs/nonces.js +6 -0
  41. package/dist/proofs/public.d.ts +12 -0
  42. package/dist/proofs/public.js +11 -0
  43. package/dist/proofs/schnorr.d.ts +10 -11
  44. package/dist/proofs/schnorr.js +10 -11
  45. package/dist/proofs/types.d.ts +30 -5
  46. package/dist/protocol/board-audit.d.ts +8 -3
  47. package/dist/protocol/board-audit.js +8 -2
  48. package/dist/protocol/builders.d.ts +77 -13
  49. package/dist/protocol/builders.js +83 -13
  50. package/dist/protocol/canonical-json.js +4 -0
  51. package/dist/protocol/manifest.d.ts +32 -15
  52. package/dist/protocol/manifest.js +65 -18
  53. package/dist/protocol/ordering.js +6 -0
  54. package/dist/protocol/payloads.d.ts +3 -3
  55. package/dist/protocol/payloads.js +7 -3
  56. package/dist/protocol/public.d.ts +17 -0
  57. package/dist/protocol/public.js +16 -0
  58. package/dist/protocol/score-range.d.ts +6 -0
  59. package/dist/protocol/score-range.js +24 -0
  60. package/dist/protocol/transcript.js +4 -0
  61. package/dist/protocol/types.d.ts +110 -17
  62. package/dist/protocol/verification.d.ts +14 -7
  63. package/dist/protocol/verification.js +7 -5
  64. package/dist/protocol/voting-ballot-aggregation.d.ts +10 -2
  65. package/dist/protocol/voting-ballot-aggregation.js +6 -0
  66. package/dist/protocol/voting-ballots.d.ts +3 -5
  67. package/dist/protocol/voting-ballots.js +6 -5
  68. package/dist/protocol/voting-codecs.d.ts +8 -3
  69. package/dist/protocol/voting-codecs.js +18 -2
  70. package/dist/protocol/voting-decryption.d.ts +3 -5
  71. package/dist/protocol/voting-decryption.js +7 -5
  72. package/dist/protocol/voting-shared.d.ts +2 -1
  73. package/dist/protocol/voting-shared.js +9 -2
  74. package/dist/protocol/voting-verification.d.ts +27 -30
  75. package/dist/protocol/voting-verification.js +13 -26
  76. package/dist/serialize/encoding.js +4 -0
  77. package/dist/threshold/decrypt.d.ts +13 -5
  78. package/dist/threshold/decrypt.js +20 -5
  79. package/dist/threshold/public.d.ts +11 -0
  80. package/dist/threshold/public.js +10 -0
  81. package/dist/threshold/types.d.ts +23 -4
  82. package/dist/transport/auth.d.ts +10 -16
  83. package/dist/transport/auth.js +16 -16
  84. package/dist/transport/complaints.d.ts +2 -4
  85. package/dist/transport/complaints.js +8 -4
  86. package/dist/transport/envelopes.d.ts +5 -7
  87. package/dist/transport/envelopes.js +9 -7
  88. package/dist/transport/key-agreement.d.ts +15 -23
  89. package/dist/transport/key-agreement.js +21 -23
  90. package/dist/transport/types.d.ts +16 -2
  91. package/dist/vss/feldman.d.ts +11 -1
  92. package/dist/vss/feldman.js +11 -1
  93. package/dist/vss/pedersen.d.ts +13 -0
  94. package/dist/vss/pedersen.js +13 -0
  95. package/dist/vss/public.d.ts +10 -0
  96. package/dist/vss/public.js +9 -0
  97. package/dist/vss/types.d.ts +4 -0
  98. package/package.json +43 -14
@@ -1,29 +1,24 @@
1
+ /**
2
+ * CDS94-style disjunctive proofs for additive ElGamal plaintexts drawn from an
3
+ * explicit finite value set.
4
+ *
5
+ * Ballot payloads use this module to prove that a ciphertext encodes one value
6
+ * from the manifest-declared domain without revealing which value was chosen.
7
+ */
1
8
  import { type CryptoGroup, type RandomBytesSource } from '../core/index.js';
2
9
  import type { ElGamalCiphertext } from '../elgamal/types.js';
3
10
  import type { DisjunctiveProof, ProofContext } from './types.js';
4
11
  /**
5
12
  * Creates a CDS94-style disjunctive proof for additive ElGamal plaintexts.
6
13
  *
7
- * @param plaintext Actual plaintext encoded in the ciphertext.
8
- * @param randomness Encryption randomness used for the ciphertext.
9
- * @param ciphertext Fresh additive ciphertext.
10
- * @param publicKey Additive-mode public key.
11
- * @param validValues Ordered set of valid plaintext values.
12
- * @param group Resolved group definition.
13
- * @param context Fiat-Shamir binding context.
14
- * @param randomSource Optional random source used for deterministic tests.
15
- * @returns Compact disjunctive proof with one branch per valid value.
14
+ * In the supported voting flow this is the proof attached to every
15
+ * `ballot-submission` payload.
16
16
  */
17
17
  export declare const createDisjunctiveProof: (plaintext: bigint, randomness: bigint, ciphertext: ElGamalCiphertext, publicKey: string, validValues: readonly bigint[], group: CryptoGroup, context: ProofContext, randomSource?: RandomBytesSource) => Promise<DisjunctiveProof>;
18
18
  /**
19
19
  * Verifies a CDS94-style disjunctive proof for additive ElGamal plaintexts.
20
20
  *
21
- * @param proof Compact disjunctive proof with one branch per valid value.
22
- * @param ciphertext Fresh additive ciphertext.
23
- * @param publicKey Additive-mode public key.
24
- * @param validValues Ordered set of valid plaintext values.
25
- * @param group Resolved group definition.
26
- * @param context Fiat-Shamir binding context.
27
- * @returns `true` when the proof verifies.
21
+ * Ballot verification uses this to reject ciphertexts that do not encode one
22
+ * of the allowed manifest-domain values for the current option slot.
28
23
  */
29
24
  export declare const verifyDisjunctiveProof: (proof: DisjunctiveProof, ciphertext: ElGamalCiphertext, publicKey: string, validValues: readonly bigint[], group: CryptoGroup, context: ProofContext) => Promise<boolean>;
@@ -1,3 +1,10 @@
1
+ /**
2
+ * CDS94-style disjunctive proofs for additive ElGamal plaintexts drawn from an
3
+ * explicit finite value set.
4
+ *
5
+ * Ballot payloads use this module to prove that a ciphertext encodes one value
6
+ * from the manifest-declared domain without revealing which value was chosen.
7
+ */
1
8
  import { assertInSubgroup, assertInSubgroupOrIdentity, assertScalarInZq, InvalidProofError, modQ, randomScalarBelow, } from '../core/index.js';
2
9
  import { decodePoint, encodePoint, multiplyBase, pointMultiply, pointSubtract, } from '../core/ristretto.js';
3
10
  import { concatBytes, encodeForChallenge, encodeSequenceForChallenge, } from '../serialize/encoding.js';
@@ -5,19 +12,12 @@ import { assertProofContext, contextElements, fixedPoint, fixedScalar, hashChall
5
12
  import { hedgedNonce } from './nonces.js';
6
13
  const candidateEncoding = (ciphertext, candidateValue, group) => encodePoint(pointSubtract(decodePoint(ciphertext.c2, 'Ciphertext c2'), multiplyBase(modQ(candidateValue, group.q))));
7
14
  const commitmentSequence = (commitments) => encodeSequenceForChallenge(commitments.map((commitment) => concatBytes(encodeForChallenge(fixedPoint(commitment.a1)), encodeForChallenge(fixedPoint(commitment.a2)))));
8
- const challengePayload = (ciphertext, publicKey, validValues, commitments, group, context) => encodeForChallenge(...contextElements(context), fixedPoint(group.g), fixedPoint(publicKey), fixedPoint(ciphertext.c1), fixedPoint(ciphertext.c2), encodeSequenceForChallenge(validValues.map((value) => fixedScalar(modQ(value, group.q), group))), commitmentSequence(commitments));
15
+ const challengePayload = (ciphertext, publicKey, validValues, commitments, group, context) => encodeForChallenge(...contextElements(context), fixedPoint(group.g), fixedPoint(publicKey), fixedPoint(ciphertext.c1), fixedPoint(ciphertext.c2), encodeSequenceForChallenge(validValues.map((value) => fixedScalar(modQ(value, group.q)))), commitmentSequence(commitments));
9
16
  /**
10
17
  * Creates a CDS94-style disjunctive proof for additive ElGamal plaintexts.
11
18
  *
12
- * @param plaintext Actual plaintext encoded in the ciphertext.
13
- * @param randomness Encryption randomness used for the ciphertext.
14
- * @param ciphertext Fresh additive ciphertext.
15
- * @param publicKey Additive-mode public key.
16
- * @param validValues Ordered set of valid plaintext values.
17
- * @param group Resolved group definition.
18
- * @param context Fiat-Shamir binding context.
19
- * @param randomSource Optional random source used for deterministic tests.
20
- * @returns Compact disjunctive proof with one branch per valid value.
19
+ * In the supported voting flow this is the proof attached to every
20
+ * `ballot-submission` payload.
21
21
  */
22
22
  export const createDisjunctiveProof = async (plaintext, randomness, ciphertext, publicKey, validValues, group, context, randomSource) => {
23
23
  assertProofContext(context, group);
@@ -67,13 +67,8 @@ export const createDisjunctiveProof = async (plaintext, randomness, ciphertext,
67
67
  /**
68
68
  * Verifies a CDS94-style disjunctive proof for additive ElGamal plaintexts.
69
69
  *
70
- * @param proof Compact disjunctive proof with one branch per valid value.
71
- * @param ciphertext Fresh additive ciphertext.
72
- * @param publicKey Additive-mode public key.
73
- * @param validValues Ordered set of valid plaintext values.
74
- * @param group Resolved group definition.
75
- * @param context Fiat-Shamir binding context.
76
- * @returns `true` when the proof verifies.
70
+ * Ballot verification uses this to reject ciphertexts that do not encode one
71
+ * of the allowed manifest-domain values for the current option slot.
77
72
  */
78
73
  export const verifyDisjunctiveProof = async (proof, ciphertext, publicKey, validValues, group, context) => {
79
74
  assertProofContext(context, group);
@@ -1,7 +1,16 @@
1
+ /**
2
+ * Chaum-Pedersen equality-of-discrete-logs proofs used for threshold
3
+ * decryption-share publication and verification.
4
+ */
1
5
  import { type CryptoGroup, type RandomBytesSource } from '../core/index.js';
2
6
  import type { ElGamalCiphertext } from '../elgamal/types.js';
3
7
  import type { DLEQProof, ProofContext } from './types.js';
4
- /** Statement tuple for a Chaum-Pedersen equality-of-discrete-logs proof. */
8
+ /**
9
+ * Statement tuple for a Chaum-Pedersen equality-of-discrete-logs proof.
10
+ *
11
+ * In the supported voting flow this statement ties a trustee's decryption
12
+ * share to both the joint public key and the accepted aggregate ciphertext.
13
+ */
5
14
  export type DLEQStatement = {
6
15
  /** Transcript-derived trustee verification key. */
7
16
  readonly publicKey: string;
@@ -13,21 +22,16 @@ export type DLEQStatement = {
13
22
  /**
14
23
  * Creates a compact additive-form Chaum-Pedersen proof of equal discrete logs.
15
24
  *
16
- * @param secret Witness scalar.
17
- * @param statement DLEQ statement over `(g, publicKey)` and `(c1, share)`.
18
- * @param group Resolved group definition.
19
- * @param context Fiat-Shamir binding context.
20
- * @param randomSource Optional random source used for deterministic tests.
21
- * @returns Compact DLEQ proof `(challenge, response)`.
25
+ * This is the proof published alongside each threshold decryption share so
26
+ * observers can verify that the share came from the same secret exponent as the
27
+ * trustee's transcript-derived verification key.
22
28
  */
23
29
  export declare const createDLEQProof: (secret: bigint, statement: DLEQStatement, group: CryptoGroup, context: ProofContext, randomSource?: RandomBytesSource) => Promise<DLEQProof>;
24
30
  /**
25
- * Verifies a compact additive-form Chaum-Pedersen proof of equal discrete logs.
31
+ * Verifies a compact additive-form Chaum-Pedersen proof of equal discrete
32
+ * logs.
26
33
  *
27
- * @param proof Compact DLEQ proof `(challenge, response)`.
28
- * @param statement DLEQ statement over `(g, publicKey)` and `(c1, share)`.
29
- * @param group Resolved group definition.
30
- * @param context Fiat-Shamir binding context.
31
- * @returns `true` when the proof verifies.
34
+ * Decryption-share verification routes through this helper after reconstructing
35
+ * the transcript-bound proof statement for one option slot.
32
36
  */
33
37
  export declare const verifyDLEQProof: (proof: DLEQProof, statement: DLEQStatement, group: CryptoGroup, context: ProofContext) => Promise<boolean>;
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Chaum-Pedersen equality-of-discrete-logs proofs used for threshold
3
+ * decryption-share publication and verification.
4
+ */
1
5
  import { assertInSubgroup, assertInSubgroupOrIdentity, assertScalarInZq, modQ, } from '../core/index.js';
2
6
  import { decodePoint, encodePoint, multiplyBase, pointMultiply, pointSubtract, } from '../core/ristretto.js';
3
7
  import { encodeForChallenge } from '../serialize/encoding.js';
@@ -8,12 +12,9 @@ const challengePayload = (statement, a1, a2, group, context) => encodeForChallen
8
12
  /**
9
13
  * Creates a compact additive-form Chaum-Pedersen proof of equal discrete logs.
10
14
  *
11
- * @param secret Witness scalar.
12
- * @param statement DLEQ statement over `(g, publicKey)` and `(c1, share)`.
13
- * @param group Resolved group definition.
14
- * @param context Fiat-Shamir binding context.
15
- * @param randomSource Optional random source used for deterministic tests.
16
- * @returns Compact DLEQ proof `(challenge, response)`.
15
+ * This is the proof published alongside each threshold decryption share so
16
+ * observers can verify that the share came from the same secret exponent as the
17
+ * trustee's transcript-derived verification key.
17
18
  */
18
19
  export const createDLEQProof = async (secret, statement, group, context, randomSource) => {
19
20
  assertProofContext(context, group);
@@ -32,13 +33,11 @@ export const createDLEQProof = async (secret, statement, group, context, randomS
32
33
  };
33
34
  };
34
35
  /**
35
- * Verifies a compact additive-form Chaum-Pedersen proof of equal discrete logs.
36
+ * Verifies a compact additive-form Chaum-Pedersen proof of equal discrete
37
+ * logs.
36
38
  *
37
- * @param proof Compact DLEQ proof `(challenge, response)`.
38
- * @param statement DLEQ statement over `(g, publicKey)` and `(c1, share)`.
39
- * @param group Resolved group definition.
40
- * @param context Fiat-Shamir binding context.
41
- * @returns `true` when the proof verifies.
39
+ * Decryption-share verification routes through this helper after reconstructing
40
+ * the transcript-bound proof statement for one option slot.
42
41
  */
43
42
  export const verifyDLEQProof = async (proof, statement, group, context) => {
44
43
  assertProofContext(context, group);
@@ -3,6 +3,6 @@ import type { ProofContext } from './types.js';
3
3
  export declare const assertProofContext: (context: ProofContext, group: CryptoGroup) => void;
4
4
  export declare const contextElements: (context: ProofContext) => (bigint | string | Uint8Array)[];
5
5
  export declare const fixedPoint: (value: string) => Uint8Array;
6
- export declare const fixedScalar: (value: bigint, group: CryptoGroup) => Uint8Array;
6
+ export declare const fixedScalar: (value: bigint) => Uint8Array;
7
7
  export declare const hashChallenge: (payload: Uint8Array, q: bigint) => Promise<bigint>;
8
8
  export declare const sumChallenges: (values: readonly bigint[], q: bigint) => bigint;
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Shared Fiat-Shamir transcript helpers used by the Schnorr, DLEQ, and
3
+ * disjunctive proof implementations.
4
+ */
1
5
  import { hexToBytes } from '../core/bytes.js';
2
6
  import { assertCanonicalRistrettoGroup, InvalidProofError, modQ, } from '../core/index.js';
3
7
  import { encodeScalar, hashChallengeToScalar } from '../core/ristretto.js';
@@ -55,9 +59,6 @@ export const contextElements = (context) => {
55
59
  return fields;
56
60
  };
57
61
  export const fixedPoint = (value) => hexToBytes(value);
58
- export const fixedScalar = (value, group) => {
59
- void group;
60
- return hexToBytes(encodeScalar(value));
61
- };
62
+ export const fixedScalar = (value) => hexToBytes(encodeScalar(value));
62
63
  export const hashChallenge = (payload, q) => Promise.resolve(modQ(hashChallengeToScalar(payload), q));
63
64
  export const sumChallenges = (values, q) => values.reduce((sum, value) => modQ(sum + value, q), 0n);
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Hedged nonce derivation for proof generation.
3
+ *
4
+ * The proof systems use this module so they remain safe under poor randomness
5
+ * while still allowing deterministic tests and vector generation.
6
+ */
1
7
  import { bytesToBigInt } from '../core/bytes.js';
2
8
  import { modQ, randomBytes, sha256, } from '../core/index.js';
3
9
  import { bigintToFixedBytes, concatBytes, domainSeparator, } from '../serialize/encoding.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Proof-system helpers for Schnorr, DLEQ, and disjunctive ballot proofs.
3
+ *
4
+ * Use this module when you need to create or verify proof objects directly.
5
+ *
6
+ * @module threshold-elgamal/proofs
7
+ * @packageDocumentation
8
+ */
9
+ export { createDisjunctiveProof, verifyDisjunctiveProof } from './disjunctive.js';
10
+ export { createDLEQProof, type DLEQStatement, verifyDLEQProof } from './dleq.js';
11
+ export { createSchnorrProof, verifySchnorrProof } from './schnorr.js';
12
+ export type { DLEQProof, DisjunctiveProof, ProofContext, SchnorrProof, } from './types.js';
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Proof-system helpers for Schnorr, DLEQ, and disjunctive ballot proofs.
3
+ *
4
+ * Use this module when you need to create or verify proof objects directly.
5
+ *
6
+ * @module threshold-elgamal/proofs
7
+ * @packageDocumentation
8
+ */
9
+ export { createDisjunctiveProof, verifyDisjunctiveProof } from './disjunctive.js';
10
+ export { createDLEQProof, verifyDLEQProof } from './dleq.js';
11
+ export { createSchnorrProof, verifySchnorrProof } from './schnorr.js';
@@ -1,23 +1,22 @@
1
+ /**
2
+ * Schnorr proof helpers used for knowledge-of-discrete-log statements.
3
+ *
4
+ * In the supported workflow this is primarily used for Feldman coefficient
5
+ * proofs inside the DKG transcript.
6
+ */
1
7
  import { type CryptoGroup, type RandomBytesSource } from '../core/index.js';
2
8
  import type { ProofContext, SchnorrProof } from './types.js';
3
9
  /**
4
10
  * Creates a compact additive-form Schnorr proof of knowledge.
5
11
  *
6
- * @param secret Witness scalar.
7
- * @param statement Statement element `g^secret mod p`.
8
- * @param group Resolved group definition.
9
- * @param context Fiat-Shamir binding context.
10
- * @param randomSource Optional random source used for deterministic tests.
11
- * @returns Compact Schnorr proof `(challenge, response)`.
12
+ * This is the proof format used when a trustee needs to show knowledge of a
13
+ * secret coefficient without revealing it.
12
14
  */
13
15
  export declare const createSchnorrProof: (secret: bigint, statement: string, group: CryptoGroup, context: ProofContext, randomSource?: RandomBytesSource) => Promise<SchnorrProof>;
14
16
  /**
15
17
  * Verifies a compact additive-form Schnorr proof.
16
18
  *
17
- * @param proof Compact Schnorr proof `(challenge, response)`.
18
- * @param statement Statement element `g^secret mod p`.
19
- * @param group Resolved group definition.
20
- * @param context Fiat-Shamir binding context.
21
- * @returns `true` when the proof verifies.
19
+ * DKG transcript verification uses this to validate Feldman coefficient proofs
20
+ * before accepting the published commitment set.
22
21
  */
23
22
  export declare const verifySchnorrProof: (proof: SchnorrProof, statement: string, group: CryptoGroup, context: ProofContext) => Promise<boolean>;
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Schnorr proof helpers used for knowledge-of-discrete-log statements.
3
+ *
4
+ * In the supported workflow this is primarily used for Feldman coefficient
5
+ * proofs inside the DKG transcript.
6
+ */
1
7
  import { assertInSubgroup, assertScalarInZq, modQ, } from '../core/index.js';
2
8
  import { decodePoint, encodePoint, multiplyBase, pointMultiply, pointSubtract, } from '../core/ristretto.js';
3
9
  import { encodeForChallenge } from '../serialize/encoding.js';
@@ -8,12 +14,8 @@ const challengePayload = (statement, commitment, group, context) => encodeForCha
8
14
  /**
9
15
  * Creates a compact additive-form Schnorr proof of knowledge.
10
16
  *
11
- * @param secret Witness scalar.
12
- * @param statement Statement element `g^secret mod p`.
13
- * @param group Resolved group definition.
14
- * @param context Fiat-Shamir binding context.
15
- * @param randomSource Optional random source used for deterministic tests.
16
- * @returns Compact Schnorr proof `(challenge, response)`.
17
+ * This is the proof format used when a trustee needs to show knowledge of a
18
+ * secret coefficient without revealing it.
17
19
  */
18
20
  export const createSchnorrProof = async (secret, statement, group, context, randomSource) => {
19
21
  assertProofContext(context, group);
@@ -30,11 +32,8 @@ export const createSchnorrProof = async (secret, statement, group, context, rand
30
32
  /**
31
33
  * Verifies a compact additive-form Schnorr proof.
32
34
  *
33
- * @param proof Compact Schnorr proof `(challenge, response)`.
34
- * @param statement Statement element `g^secret mod p`.
35
- * @param group Resolved group definition.
36
- * @param context Fiat-Shamir binding context.
37
- * @returns `true` when the proof verifies.
35
+ * DKG transcript verification uses this to validate Feldman coefficient proofs
36
+ * before accepting the published commitment set.
38
37
  */
39
38
  export const verifySchnorrProof = async (proof, statement, group, context) => {
40
39
  assertProofContext(context, group);
@@ -1,7 +1,19 @@
1
+ /**
2
+ * Shared proof types and transcript context bindings.
3
+ *
4
+ * Every proof in the package binds itself to the same core ceremony context so
5
+ * proofs cannot be replayed across manifests, sessions, participants, or
6
+ * option slots.
7
+ */
1
8
  import type { GroupName } from '../core/types.js';
2
- /** Common Fiat-Shamir context fields used by the shipped proof systems. */
9
+ /**
10
+ * Common Fiat-Shamir context fields used by the proof systems.
11
+ *
12
+ * Higher-level modules derive these fields from the manifest, transcript, and
13
+ * payload slot currently being proved or verified.
14
+ */
3
15
  export type ProofContext = {
4
- /** Protocol version string bound into the transcript. */
16
+ /** Protocol namespace string bound into the transcript. */
5
17
  readonly protocolVersion: string;
6
18
  /** Group suite name bound into the transcript. */
7
19
  readonly suiteId: GroupName;
@@ -20,12 +32,20 @@ export type ProofContext = {
20
32
  /** Optional ballot option index so ballot proofs stay bound to one option slot. */
21
33
  readonly optionIndex?: number;
22
34
  };
23
- /** Compact Schnorr proof encoded as challenge and response only. */
35
+ /**
36
+ * Compact Schnorr proof encoded as challenge and response only.
37
+ *
38
+ * Used primarily for Feldman coefficient proofs in the DKG flow.
39
+ */
24
40
  export type SchnorrProof = {
25
41
  readonly challenge: bigint;
26
42
  readonly response: bigint;
27
43
  };
28
- /** Compact Chaum-Pedersen proof encoded as challenge and response only. */
44
+ /**
45
+ * Compact Chaum-Pedersen proof encoded as challenge and response only.
46
+ *
47
+ * Used for decryption-share correctness proofs.
48
+ */
29
49
  export type DLEQProof = {
30
50
  readonly challenge: bigint;
31
51
  readonly response: bigint;
@@ -35,7 +55,12 @@ export type DisjunctiveBranch = {
35
55
  readonly challenge: bigint;
36
56
  readonly response: bigint;
37
57
  };
38
- /** A disjunctive proof over an ordered set of valid plaintext values. */
58
+ /**
59
+ * A disjunctive proof over an ordered set of valid plaintext values.
60
+ *
61
+ * Ballot payloads use this to prove that an encrypted value came from the
62
+ * allowed manifest domain without revealing which value was chosen.
63
+ */
39
64
  export type DisjunctiveProof = {
40
65
  readonly branches: readonly DisjunctiveBranch[];
41
66
  };
@@ -13,7 +13,12 @@ type PhaseDigest = {
13
13
  readonly digest: string;
14
14
  readonly payloadCount: number;
15
15
  };
16
- /** Deterministic audit result for a set of signed protocol payloads. */
16
+ /**
17
+ * Deterministic audit result for a set of signed protocol payloads.
18
+ *
19
+ * Higher-level verifiers consume this output instead of raw board logs so they
20
+ * can operate on one canonical accepted transcript.
21
+ */
17
22
  export type BoardAudit<TPayload extends ProtocolPayload = ProtocolPayload> = {
18
23
  readonly acceptedPayloads: readonly SignedPayload<TPayload>[];
19
24
  readonly ceremonyDigest: string;
@@ -25,8 +30,8 @@ export type BoardAudit<TPayload extends ProtocolPayload = ProtocolPayload> = {
25
30
  * Audits signed payloads by canonical slot, rejecting equivocation and
26
31
  * collapsing only exact signed retransmissions to one representative payload.
27
32
  *
28
- * @param signedPayloads Signed payloads to audit.
29
- * @returns Deterministic audit output with accepted payloads and digests.
33
+ * All transcript-level verifiers run this step before they interpret the
34
+ * semantic contents of the board.
30
35
  */
31
36
  export declare const auditSignedPayloads: <TPayload extends ProtocolPayload>(signedPayloads: readonly SignedPayload<TPayload>[]) => Promise<BoardAudit<TPayload>>;
32
37
  export {};
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Deterministic bulletin-board audit for signed protocol payloads.
3
+ *
4
+ * This is the layer that collapses exact retransmissions, rejects
5
+ * equivocation, and produces stable digests over the accepted transcript.
6
+ */
1
7
  import { InvalidPayloadError } from '../core/index.js';
2
8
  import { compareProtocolPayloads } from './ordering.js';
3
9
  import { classifySlotConflict, payloadSlotKey } from './payloads.js';
@@ -20,8 +26,8 @@ const acceptedUnsignedPayloads = (acceptedPayloads) => acceptedPayloads.map((pay
20
26
  * Audits signed payloads by canonical slot, rejecting equivocation and
21
27
  * collapsing only exact signed retransmissions to one representative payload.
22
28
  *
23
- * @param signedPayloads Signed payloads to audit.
24
- * @returns Deterministic audit output with accepted payloads and digests.
29
+ * All transcript-level verifiers run this step before they interpret the
30
+ * semantic contents of the board.
25
31
  */
26
32
  export const auditSignedPayloads = async (signedPayloads) => {
27
33
  const sortedPayloads = [...signedPayloads].sort(compareSignedPayloads);
@@ -6,11 +6,21 @@ import type { BallotClosePayload, BallotSubmissionPayload, DecryptionSharePayloa
6
6
  type ProtocolPayloadByMessageType<TMessageType extends ProtocolMessageType> = Extract<ProtocolPayload, {
7
7
  readonly messageType: TMessageType;
8
8
  }>;
9
- /** Signs one canonical protocol payload with a participant auth key. */
9
+ /**
10
+ * Signs one canonical protocol payload with a participant auth key.
11
+ *
12
+ * All specialized payload builders in this module eventually route through
13
+ * this helper after normalizing the payload shape.
14
+ */
10
15
  export declare const signProtocolPayload: <TMessageType extends ProtocolMessageType>(privateKey: CryptoKey, payload: ProtocolPayloadInput<ProtocolPayloadByMessageType<TMessageType>> & {
11
16
  readonly messageType: TMessageType;
12
17
  }) => Promise<SignedPayload<ProtocolPayloadByMessageType<TMessageType>>>;
13
- /** Creates a signed manifest-publication payload. */
18
+ /**
19
+ * Creates a signed `manifest-publication` payload.
20
+ *
21
+ * This is the first public payload in the supported ceremony and anchors the
22
+ * explicit manifest on the board.
23
+ */
14
24
  export declare const createManifestPublicationPayload: (privateKey: CryptoKey, input: {
15
25
  readonly manifest: ElectionManifest;
16
26
  readonly manifestHash: string;
@@ -18,7 +28,12 @@ export declare const createManifestPublicationPayload: (privateKey: CryptoKey, i
18
28
  readonly protocolVersion?: string;
19
29
  readonly sessionId: string;
20
30
  }) => Promise<SignedPayload<ManifestPublicationPayload>>;
21
- /** Creates a signed registration payload for one participant. */
31
+ /**
32
+ * Creates a signed `registration` payload for one participant.
33
+ *
34
+ * Registrations publish the participant's auth key and transport key and are
35
+ * the source of truth for the accepted roster.
36
+ */
22
37
  export declare const createRegistrationPayload: (privateKey: CryptoKey, input: {
23
38
  readonly authPublicKey: EncodedAuthPublicKey;
24
39
  readonly manifestHash: string;
@@ -28,7 +43,12 @@ export declare const createRegistrationPayload: (privateKey: CryptoKey, input: {
28
43
  readonly sessionId: string;
29
44
  readonly transportPublicKey: EncodedTransportPublicKey;
30
45
  }) => Promise<SignedPayload<RegistrationPayload>>;
31
- /** Creates a signed manifest-acceptance payload. */
46
+ /**
47
+ * Creates a signed `manifest-acceptance` payload.
48
+ *
49
+ * This records that a participant accepted the frozen manifest and the roster
50
+ * hash under which they were assigned an index.
51
+ */
32
52
  export declare const createManifestAcceptancePayload: (privateKey: CryptoKey, input: {
33
53
  readonly accountIdHash?: string;
34
54
  readonly assignedParticipantIndex: number;
@@ -38,7 +58,12 @@ export declare const createManifestAcceptancePayload: (privateKey: CryptoKey, in
38
58
  readonly rosterHash: string;
39
59
  readonly sessionId: string;
40
60
  }) => Promise<SignedPayload<ManifestAcceptancePayload>>;
41
- /** Creates a signed phase-checkpoint payload over one DKG phase snapshot. */
61
+ /**
62
+ * Creates a signed `phase-checkpoint` payload over one DKG phase snapshot.
63
+ *
64
+ * Checkpoints let observers replay the DKG in coarse-grained epochs while
65
+ * preserving deterministic transcript commitments.
66
+ */
42
67
  export declare const createPhaseCheckpointPayload: (privateKey: CryptoKey, input: {
43
68
  readonly checkpointPhase: 0 | 1 | 2 | 3;
44
69
  readonly manifestHash: string;
@@ -48,15 +73,27 @@ export declare const createPhaseCheckpointPayload: (privateKey: CryptoKey, input
48
73
  readonly sessionId: string;
49
74
  readonly transcript: readonly SignedPayload[];
50
75
  }) => Promise<SignedPayload<PhaseCheckpointPayload>>;
51
- /** Creates a signed Pedersen-commitment payload for DKG phase 1. */
76
+ /**
77
+ * Creates a signed `pedersen-commitment` payload for DKG phase 1.
78
+ */
52
79
  export declare const createPedersenCommitmentPayload: (privateKey: CryptoKey, input: Omit<PedersenCommitmentPayload, "messageType" | "phase" | "protocolVersion"> & {
53
80
  readonly protocolVersion?: string;
54
81
  }) => Promise<SignedPayload<PedersenCommitmentPayload>>;
55
- /** Creates a signed encrypted dual-share payload for DKG phase 1. */
82
+ /**
83
+ * Creates a signed `encrypted-dual-share` payload for DKG phase 1.
84
+ *
85
+ * The envelope contents are produced separately by the transport layer and are
86
+ * merely wrapped and signed here.
87
+ */
56
88
  export declare const createEncryptedDualSharePayload: (privateKey: CryptoKey, input: Omit<EncryptedDualSharePayload, "messageType" | "phase" | "protocolVersion"> & {
57
89
  readonly protocolVersion?: string;
58
90
  }) => Promise<SignedPayload<EncryptedDualSharePayload>>;
59
- /** Creates a signed Feldman-commitment payload for DKG phase 3. */
91
+ /**
92
+ * Creates a signed `feldman-commitment` payload for DKG phase 3.
93
+ *
94
+ * This payload exposes the public Feldman commitments and their Schnorr proofs
95
+ * after the complaint phase has been resolved.
96
+ */
60
97
  export declare const createFeldmanCommitmentPayload: (privateKey: CryptoKey, input: Omit<FeldmanCommitmentPayload, "messageType" | "phase" | "proofs" | "protocolVersion"> & {
61
98
  readonly protocolVersion?: string;
62
99
  readonly proofs: FeldmanCommitmentPayload["proofs"] | readonly ({
@@ -67,26 +104,53 @@ export declare const createFeldmanCommitmentPayload: (privateKey: CryptoKey, inp
67
104
  readonly coefficientIndex: number;
68
105
  } & EncodedCompactProof))[];
69
106
  }) => Promise<SignedPayload<FeldmanCommitmentPayload>>;
70
- /** Creates a signed key-derivation-confirmation payload for DKG phase 4. */
107
+ /**
108
+ * Creates a signed `key-derivation-confirmation` payload for DKG phase 4.
109
+ *
110
+ * Trustees use this to confirm the final derived joint key and transcript
111
+ * digest they believe the DKG produced.
112
+ */
71
113
  export declare const createKeyDerivationConfirmationPayload: (privateKey: CryptoKey, input: Omit<KeyDerivationConfirmation, "messageType" | "phase" | "protocolVersion"> & {
72
114
  readonly protocolVersion?: string;
73
115
  }) => Promise<SignedPayload<KeyDerivationConfirmation>>;
74
- /** Creates a signed ballot payload for one participant and one option slot. */
116
+ /**
117
+ * Creates a signed `ballot-submission` payload for one participant and one
118
+ * option slot.
119
+ *
120
+ * Higher-level application code is expected to create the ciphertext and
121
+ * disjunctive proof first, then hand them to this builder for encoding and
122
+ * signing.
123
+ */
75
124
  export declare const createBallotSubmissionPayload: (privateKey: CryptoKey, input: Omit<BallotSubmissionPayload, "messageType" | "phase" | "ciphertext" | "proof" | "protocolVersion"> & {
76
125
  readonly protocolVersion?: string;
77
126
  readonly ciphertext: BallotSubmissionPayload["ciphertext"] | ElGamalCiphertext;
78
127
  readonly proof: BallotSubmissionPayload["proof"] | DisjunctiveProof;
79
128
  }) => Promise<SignedPayload<BallotSubmissionPayload>>;
80
- /** Creates the organizer-signed ballot cutoff payload. */
129
+ /**
130
+ * Creates the organizer-signed `ballot-close` payload.
131
+ *
132
+ * This freezes which complete ballots are counted for the tally and therefore
133
+ * determines the accepted aggregate seen by every later decryption step.
134
+ */
81
135
  export declare const createBallotClosePayload: (privateKey: CryptoKey, input: Omit<BallotClosePayload, "messageType" | "phase" | "protocolVersion"> & {
82
136
  readonly protocolVersion?: string;
83
137
  }) => Promise<SignedPayload<BallotClosePayload>>;
84
- /** Creates a signed threshold decryption-share payload for one option slot. */
138
+ /**
139
+ * Creates a signed `decryption-share` payload for one option slot.
140
+ *
141
+ * The caller is responsible for computing the share and DLEQ proof first; this
142
+ * helper encodes and signs the published object.
143
+ */
85
144
  export declare const createDecryptionSharePayload: (privateKey: CryptoKey, input: Omit<DecryptionSharePayload, "messageType" | "phase" | "proof" | "protocolVersion"> & {
86
145
  readonly protocolVersion?: string;
87
146
  readonly proof: DecryptionSharePayload["proof"] | DLEQProof;
88
147
  }) => Promise<SignedPayload<DecryptionSharePayload>>;
89
- /** Creates a signed tally-publication payload for one option slot. */
148
+ /**
149
+ * Creates a signed `tally-publication` payload for one option slot.
150
+ *
151
+ * This is the final organizer-facing publication step after the accepted
152
+ * decryption shares have been combined into a bounded plaintext tally.
153
+ */
90
154
  export declare const createTallyPublicationPayload: (privateKey: CryptoKey, input: Omit<TallyPublicationPayload, "messageType" | "phase" | "tally" | "protocolVersion"> & {
91
155
  readonly protocolVersion?: string;
92
156
  readonly tally: TallyPublicationPayload["tally"] | bigint;