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.
- package/README.md +33 -35
- package/dist/core/bigint.d.ts +2 -1
- package/dist/core/bigint.js +6 -1
- package/dist/core/bytes.js +4 -0
- package/dist/core/crypto.js +5 -0
- package/dist/core/errors.d.ts +50 -11
- package/dist/core/errors.js +50 -11
- package/dist/core/groups.d.ts +6 -1
- package/dist/core/groups.js +13 -2
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.js +4 -0
- package/dist/core/public.d.ts +13 -0
- package/dist/core/public.js +12 -0
- package/dist/core/random.js +4 -0
- package/dist/core/ristretto.d.ts +7 -0
- package/dist/core/ristretto.js +7 -0
- package/dist/core/types.d.ts +14 -6
- package/dist/core/validation.d.ts +45 -12
- package/dist/core/validation.js +52 -12
- package/dist/dkg/pedersen-share-codec.d.ts +12 -2
- package/dist/dkg/pedersen-share-codec.js +19 -2
- package/dist/dkg/public.d.ts +12 -0
- package/dist/dkg/public.js +11 -0
- package/dist/dkg/verification.d.ts +33 -14
- package/dist/dkg/verification.js +16 -12
- package/dist/elgamal/additive.d.ts +15 -3
- package/dist/elgamal/additive.js +27 -23
- package/dist/elgamal/bsgs.js +7 -0
- package/dist/elgamal/public.d.ts +11 -0
- package/dist/elgamal/public.js +10 -0
- package/dist/elgamal/types.d.ts +6 -0
- package/dist/index.d.ts +27 -25
- package/dist/index.js +20 -19
- package/dist/proofs/disjunctive.d.ts +11 -16
- package/dist/proofs/disjunctive.js +12 -17
- package/dist/proofs/dleq.d.ts +17 -13
- package/dist/proofs/dleq.js +11 -12
- package/dist/proofs/helpers.d.ts +1 -1
- package/dist/proofs/helpers.js +5 -4
- package/dist/proofs/nonces.js +6 -0
- package/dist/proofs/public.d.ts +12 -0
- package/dist/proofs/public.js +11 -0
- package/dist/proofs/schnorr.d.ts +10 -11
- package/dist/proofs/schnorr.js +10 -11
- package/dist/proofs/types.d.ts +30 -5
- package/dist/protocol/board-audit.d.ts +8 -3
- package/dist/protocol/board-audit.js +8 -2
- package/dist/protocol/builders.d.ts +77 -13
- package/dist/protocol/builders.js +83 -13
- package/dist/protocol/canonical-json.js +4 -0
- package/dist/protocol/manifest.d.ts +32 -15
- package/dist/protocol/manifest.js +65 -18
- package/dist/protocol/ordering.js +6 -0
- package/dist/protocol/payloads.d.ts +3 -3
- package/dist/protocol/payloads.js +7 -3
- package/dist/protocol/public.d.ts +17 -0
- package/dist/protocol/public.js +16 -0
- package/dist/protocol/score-range.d.ts +6 -0
- package/dist/protocol/score-range.js +24 -0
- package/dist/protocol/transcript.js +4 -0
- package/dist/protocol/types.d.ts +110 -17
- package/dist/protocol/verification.d.ts +14 -7
- package/dist/protocol/verification.js +7 -5
- package/dist/protocol/voting-ballot-aggregation.d.ts +10 -2
- package/dist/protocol/voting-ballot-aggregation.js +6 -0
- package/dist/protocol/voting-ballots.d.ts +3 -5
- package/dist/protocol/voting-ballots.js +6 -5
- package/dist/protocol/voting-codecs.d.ts +8 -3
- package/dist/protocol/voting-codecs.js +18 -2
- package/dist/protocol/voting-decryption.d.ts +3 -5
- package/dist/protocol/voting-decryption.js +7 -5
- package/dist/protocol/voting-shared.d.ts +2 -1
- package/dist/protocol/voting-shared.js +9 -2
- package/dist/protocol/voting-verification.d.ts +27 -30
- package/dist/protocol/voting-verification.js +13 -26
- package/dist/serialize/encoding.js +4 -0
- package/dist/threshold/decrypt.d.ts +13 -5
- package/dist/threshold/decrypt.js +20 -5
- package/dist/threshold/public.d.ts +11 -0
- package/dist/threshold/public.js +10 -0
- package/dist/threshold/types.d.ts +23 -4
- package/dist/transport/auth.d.ts +10 -16
- package/dist/transport/auth.js +16 -16
- package/dist/transport/complaints.d.ts +2 -4
- package/dist/transport/complaints.js +8 -4
- package/dist/transport/envelopes.d.ts +5 -7
- package/dist/transport/envelopes.js +9 -7
- package/dist/transport/key-agreement.d.ts +15 -23
- package/dist/transport/key-agreement.js +21 -23
- package/dist/transport/types.d.ts +16 -2
- package/dist/vss/feldman.d.ts +11 -1
- package/dist/vss/feldman.js +11 -1
- package/dist/vss/pedersen.d.ts +13 -0
- package/dist/vss/pedersen.js +13 -0
- package/dist/vss/public.d.ts +10 -0
- package/dist/vss/public.js +9 -0
- package/dist/vss/types.d.ts +4 -0
- 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
|
-
*
|
|
8
|
-
*
|
|
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
|
-
*
|
|
22
|
-
*
|
|
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)
|
|
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
|
-
*
|
|
13
|
-
*
|
|
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
|
-
*
|
|
71
|
-
*
|
|
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);
|
package/dist/proofs/dleq.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
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
|
|
31
|
+
* Verifies a compact additive-form Chaum-Pedersen proof of equal discrete
|
|
32
|
+
* logs.
|
|
26
33
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
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>;
|
package/dist/proofs/dleq.js
CHANGED
|
@@ -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
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
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
|
|
36
|
+
* Verifies a compact additive-form Chaum-Pedersen proof of equal discrete
|
|
37
|
+
* logs.
|
|
36
38
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
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);
|
package/dist/proofs/helpers.d.ts
CHANGED
|
@@ -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
|
|
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;
|
package/dist/proofs/helpers.js
CHANGED
|
@@ -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
|
|
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);
|
package/dist/proofs/nonces.js
CHANGED
|
@@ -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';
|
package/dist/proofs/schnorr.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
7
|
-
*
|
|
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
|
-
*
|
|
18
|
-
*
|
|
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>;
|
package/dist/proofs/schnorr.js
CHANGED
|
@@ -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
|
-
*
|
|
12
|
-
*
|
|
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
|
-
*
|
|
34
|
-
*
|
|
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);
|
package/dist/proofs/types.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
29
|
-
*
|
|
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
|
-
*
|
|
24
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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;
|