threshold-elgamal 0.1.26 → 0.1.28

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 CHANGED
@@ -97,28 +97,24 @@ import {
97
97
  thresholdDecrypt,
98
98
  } from "threshold-elgamal";
99
99
 
100
- const primeBits = 2048; // Bit length of the prime modulus
101
100
  const threshold = 3; // A scenario for 3 participants with a threshold of 3
102
- const { prime, generator } = getGroup(2048);
101
+ const { prime, generator } = getGroup(); // 2048-bit by default
103
102
 
104
103
  // Each participant generates their public key share and private key individually
105
- const participant1Keys = generateKeys(1, threshold, primeBits);
106
- const participant2Keys = generateKeys(2, threshold, primeBits);
107
- const participant3Keys = generateKeys(3, threshold, primeBits);
104
+ const participant1Keys = generateKeys(1, threshold);
105
+ const participant2Keys = generateKeys(2, threshold);
106
+ const participant3Keys = generateKeys(3, threshold);
108
107
 
109
108
  // Combine the public keys to form a single public key
110
- const combinedPublicKey = combinePublicKeys(
111
- [
112
- participant1Keys.publicKey,
113
- participant2Keys.publicKey,
114
- participant3Keys.publicKey,
115
- ],
116
- prime,
117
- );
109
+ const commonPublicKey = combinePublicKeys([
110
+ participant1Keys.publicKey,
111
+ participant2Keys.publicKey,
112
+ participant3Keys.publicKey,
113
+ ]);
118
114
 
119
115
  // Encrypt a message using the combined public key
120
116
  const secret = 42;
121
- const encryptedMessage = encrypt(secret, prime, generator, combinedPublicKey);
117
+ const encryptedMessage = encrypt(secret, prime, generator, commonPublicKey);
122
118
 
123
119
  // Decryption shares
124
120
  const decryptionShares = [
@@ -139,6 +135,7 @@ const thresholdDecryptedMessage = thresholdDecrypt(
139
135
  prime,
140
136
  );
141
137
  console.log(thresholdDecryptedMessage); // 42
138
+ expect(thresholdDecryptedMessage).toBe(secret);
142
139
  ```
143
140
 
144
141
  ### Voting and multiplication with threshold scheme for 3 participants
@@ -157,24 +154,20 @@ import {
157
154
  getGroup,
158
155
  } from "threshold-elgamal";
159
156
 
160
- const primeBits = 2048; // Bit length of the prime modulus
161
157
  const threshold = 3; // A scenario for 3 participants with a threshold of 3
162
- const { prime, generator } = getGroup(2048);
158
+ const { prime, generator } = getGroup(); // 2048-bit by default
163
159
 
164
160
  // Each participant generates their public key share and private key individually
165
- const participant1Keys = generateKeys(1, threshold, primeBits);
166
- const participant2Keys = generateKeys(2, threshold, primeBits);
167
- const participant3Keys = generateKeys(3, threshold, primeBits);
161
+ const participant1Keys = generateKeys(1, threshold);
162
+ const participant2Keys = generateKeys(2, threshold);
163
+ const participant3Keys = generateKeys(3, threshold);
168
164
 
169
165
  // Combine the public keys to form a single public key
170
- const combinedPublicKey = combinePublicKeys(
171
- [
172
- participant1Keys.publicKey,
173
- participant2Keys.publicKey,
174
- participant3Keys.publicKey,
175
- ],
176
- prime,
177
- );
166
+ const commonPublicKey = combinePublicKeys([
167
+ participant1Keys.publicKey,
168
+ participant2Keys.publicKey,
169
+ participant3Keys.publicKey,
170
+ ]);
178
171
 
179
172
  // Participants cast their encrypted votes for two options
180
173
  const voteOption1 = [6, 7, 1]; // Votes for option 1 by participants 1, 2, and 3
@@ -182,10 +175,10 @@ const voteOption2 = [10, 7, 4]; // Votes for option 2 by participants 1, 2, and
182
175
 
183
176
  // Encrypt votes for both options
184
177
  const encryptedVotesOption1 = voteOption1.map((vote) =>
185
- encrypt(vote, prime, generator, combinedPublicKey),
178
+ encrypt(vote, prime, generator, commonPublicKey),
186
179
  );
187
180
  const encryptedVotesOption2 = voteOption2.map((vote) =>
188
- encrypt(vote, prime, generator, combinedPublicKey),
181
+ encrypt(vote, prime, generator, commonPublicKey),
189
182
  );
190
183
 
191
184
  // Multiply encrypted votes together to aggregate
@@ -39,7 +39,7 @@ export declare const generateKeyShares: (n: number, threshold: number, primeBits
39
39
  * @param {bigint} prime - The prime modulus used in the ElGamal system.
40
40
  * @returns {bigint} The combined public key.
41
41
  */
42
- export declare const combinePublicKeys: (publicKeys: bigint[], prime: bigint) => bigint;
42
+ export declare const combinePublicKeys: (publicKeys: bigint[], prime?: bigint) => bigint;
43
43
  /**
44
44
  * Performs a partial decryption on a ciphertext using an individual's private key share.
45
45
  *
@@ -59,7 +59,7 @@ export const generateKeyShares = (n, threshold, primeBits = 2048) => {
59
59
  * @param {bigint} prime - The prime modulus used in the ElGamal system.
60
60
  * @returns {bigint} The combined public key.
61
61
  */
62
- export const combinePublicKeys = (publicKeys, prime) => publicKeys.reduce((acc, current) => (acc * current) % prime, 1n);
62
+ export const combinePublicKeys = (publicKeys, prime = getGroup(2048).prime) => publicKeys.reduce((acc, current) => (acc * current) % prime, 1n);
63
63
  /**
64
64
  * Performs a partial decryption on a ciphertext using an individual's private key share.
65
65
  *
@@ -4,7 +4,7 @@ export declare const thresholdSetup: (partiesCount: number, threshold: number, p
4
4
  privateKey: bigint;
5
5
  publicKey: bigint;
6
6
  }[];
7
- combinedPublicKey: bigint;
7
+ commonPublicKey: bigint;
8
8
  prime: bigint;
9
9
  generator: bigint;
10
10
  };
@@ -7,12 +7,12 @@ export const thresholdSetup = (partiesCount, threshold, primeBits = 2048) => {
7
7
  const { prime, generator } = getGroup(primeBits);
8
8
  const keyShares = generateKeyShares(partiesCount, threshold, primeBits);
9
9
  const publicKeys = keyShares.map((ks) => ks.publicKey);
10
- const combinedPublicKey = combinePublicKeys(publicKeys, prime);
11
- return { keyShares, combinedPublicKey, prime, generator };
10
+ const commonPublicKey = combinePublicKeys(publicKeys, prime);
11
+ return { keyShares, commonPublicKey, prime, generator };
12
12
  };
13
13
  export const testSecureEncryptionAndDecryption = (participantsCount, threshold, secret) => {
14
- const { keyShares, combinedPublicKey, prime, generator } = thresholdSetup(participantsCount, threshold);
15
- const encryptedMessage = encrypt(secret, prime, generator, combinedPublicKey);
14
+ const { keyShares, commonPublicKey, prime, generator } = thresholdSetup(participantsCount, threshold);
15
+ const encryptedMessage = encrypt(secret, prime, generator, commonPublicKey);
16
16
  const selectedDecryptionShares = keyShares
17
17
  .sort(() => Math.random() - 0.5)
18
18
  .slice(0, threshold)
@@ -23,8 +23,8 @@ export const testSecureEncryptionAndDecryption = (participantsCount, threshold,
23
23
  };
24
24
  export const homomorphicMultiplicationTest = (participantsCount, threshold, messages) => {
25
25
  const expectedProduct = messages.reduce((product, secret) => product * secret, 1);
26
- const { keyShares, combinedPublicKey, prime, generator } = thresholdSetup(participantsCount, threshold);
27
- const encryptedMessages = messages.map((secret) => encrypt(secret, prime, generator, combinedPublicKey));
26
+ const { keyShares, commonPublicKey, prime, generator } = thresholdSetup(participantsCount, threshold);
27
+ const encryptedMessages = messages.map((secret) => encrypt(secret, prime, generator, commonPublicKey));
28
28
  const encryptedProduct = encryptedMessages.reduce((product, encryptedMessage) => multiplyEncryptedValues(product, encryptedMessage, prime), { c1: 1n, c2: 1n });
29
29
  const selectedDecryptionShares = keyShares
30
30
  .sort(() => Math.random() - 0.5)
@@ -35,10 +35,10 @@ export const homomorphicMultiplicationTest = (participantsCount, threshold, mess
35
35
  expect(decryptedProduct).toBe(expectedProduct);
36
36
  };
37
37
  export const votingTest = (participantsCount, threshold, candidatesCount) => {
38
- const { keyShares, combinedPublicKey, prime, generator } = thresholdSetup(participantsCount, threshold);
38
+ const { keyShares, commonPublicKey, prime, generator } = thresholdSetup(participantsCount, threshold);
39
39
  const votesMatrix = Array.from({ length: participantsCount }, () => Array.from({ length: candidatesCount }, () => getRandomScore(1, 10)));
40
40
  const expectedProducts = Array.from({ length: candidatesCount }, (_, candidateIndex) => votesMatrix.reduce((product, votes) => product * votes[candidateIndex], 1));
41
- const encryptedVotesMatrix = votesMatrix.map((votes) => votes.map((vote) => encrypt(vote, prime, generator, combinedPublicKey)));
41
+ const encryptedVotesMatrix = votesMatrix.map((votes) => votes.map((vote) => encrypt(vote, prime, generator, commonPublicKey)));
42
42
  const encryptedProducts = Array.from({ length: candidatesCount }, (_, candidateIndex) => encryptedVotesMatrix.reduce((product, encryptedVotes) => multiplyEncryptedValues(product, encryptedVotes[candidateIndex], prime), { c1: 1n, c2: 1n }));
43
43
  const partialDecryptionsMatrix = encryptedProducts.map((product) => keyShares
44
44
  .slice(0, threshold)
@@ -21,7 +21,7 @@ export declare const randomBigint: (bits: number) => bigint;
21
21
  * @param {2048 | 3072 | 4096} primeBits - The bit length of the prime modulus (2048, 3072, or 4096).
22
22
  * @returns {Object} The group parameters including prime and generator.
23
23
  */
24
- export declare const getGroup: (primeBits: 2048 | 3072 | 4096) => {
24
+ export declare const getGroup: (primeBits?: 2048 | 3072 | 4096) => {
25
25
  prime: bigint;
26
26
  generator: bigint;
27
27
  };
@@ -37,7 +37,7 @@ export const randomBigint = (bits) => {
37
37
  * @param {2048 | 3072 | 4096} primeBits - The bit length of the prime modulus (2048, 3072, or 4096).
38
38
  * @returns {Object} The group parameters including prime and generator.
39
39
  */
40
- export const getGroup = (primeBits) => {
40
+ export const getGroup = (primeBits = 2048) => {
41
41
  switch (primeBits) {
42
42
  case 2048:
43
43
  return GROUPS.ffdhe2048;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "threshold-elgamal",
3
- "version": "0.1.26",
3
+ "version": "0.1.28",
4
4
  "description": "Threshold ElGamal in TypeScript",
5
5
  "author": "Piotr Piech <piotr@piech.dev>",
6
6
  "license": "MIT",